From 14579fb90ea12a09afcd5759a9649fd435cb2fda Mon Sep 17 00:00:00 2001 From: Nou Date: Tue, 14 Apr 2015 00:41:19 -0700 Subject: [PATCH 001/140] Explosive reflection, enabled on all frag rounds. --- addons/frag/CfgAmmo.hpp | 3 + addons/frag/CfgAmmoReflections.hpp | 2523 +++++++++++++++++ addons/frag/XEH_pre_Init.sqf | 4 + addons/frag/functions/fnc_doExplosions.sqf | 26 + addons/frag/functions/fnc_doReflections.sqf | 22 + addons/frag/functions/fnc_findReflections.sqf | 130 + addons/frag/functions/fnc_frago.sqf | 6 +- 7 files changed, 2712 insertions(+), 2 deletions(-) create mode 100644 addons/frag/CfgAmmoReflections.hpp create mode 100644 addons/frag/functions/fnc_doExplosions.sqf create mode 100644 addons/frag/functions/fnc_doReflections.sqf create mode 100644 addons/frag/functions/fnc_findReflections.sqf diff --git a/addons/frag/CfgAmmo.hpp b/addons/frag/CfgAmmo.hpp index 8ad76e6ae8..8d965e8d2e 100644 --- a/addons/frag/CfgAmmo.hpp +++ b/addons/frag/CfgAmmo.hpp @@ -8,6 +8,9 @@ class CfgAmmo { //class ace_arty_105mm_m1_m782_delay: ace_arty_105mm_m1_m782_prox { // ACE_FRAG_SKIP = 1; //}; + + #include "CfgAmmoReflections.hpp" + class Bo_GBU12_LGB; class Nou_GBU12 : Bo_GBU12_LGB { ACE_FRAG_CLASSES[] = {"ACE_frag_large", "ACE_frag_large", "ACE_frag_large_HD", "ACE_frag_large", "ACE_frag_huge", "ACE_frag_huge_HD", "ACE_frag_huge"}; diff --git a/addons/frag/CfgAmmoReflections.hpp b/addons/frag/CfgAmmoReflections.hpp new file mode 100644 index 0000000000..8e481a9cd0 --- /dev/null +++ b/addons/frag/CfgAmmoReflections.hpp @@ -0,0 +1,2523 @@ +//CfgAmmoReflections.hpp + +#define ACE_EXPLOSION_REFLECTION(range, hit) class ace_explosion_reflection_##range##_##hit : ace_explosion_reflection_base { indirectHitRange = range; indirectHit = hit; dangerRadiusHit = range*3; suppressionRadiusHit = range*2; }; +class Sh_120mm_HE; +class ace_explosion_reflection_base : Sh_120mm_HE { + CraterWaterEffects = ""; + CraterEffects = ""; + effectsMissile = ""; + ExplosionEffects = ""; + effectFlare = ""; + class HitEffects { + hitWater = ""; + }; + multiSoundHit[] = {}; + explosionTime = 0.0001; + explosive = 1; + soundFakeFall[] = {}; + typicalSpeed = 0; + model = "\A3\Weapons_F\empty.p3d"; + craterShape = "\A3\weapons_f\empty.p3d"; +}; + +ACE_EXPLOSION_REFLECTION(2,10); +ACE_EXPLOSION_REFLECTION(2,20); +ACE_EXPLOSION_REFLECTION(2,30); +ACE_EXPLOSION_REFLECTION(2,40); +ACE_EXPLOSION_REFLECTION(2,50); +ACE_EXPLOSION_REFLECTION(2,60); +ACE_EXPLOSION_REFLECTION(2,70); +ACE_EXPLOSION_REFLECTION(2,80); +ACE_EXPLOSION_REFLECTION(2,90); +ACE_EXPLOSION_REFLECTION(2,100); +ACE_EXPLOSION_REFLECTION(2,110); +ACE_EXPLOSION_REFLECTION(2,120); +ACE_EXPLOSION_REFLECTION(2,130); +ACE_EXPLOSION_REFLECTION(2,140); +ACE_EXPLOSION_REFLECTION(2,150); +ACE_EXPLOSION_REFLECTION(2,160); +ACE_EXPLOSION_REFLECTION(2,170); +ACE_EXPLOSION_REFLECTION(2,180); +ACE_EXPLOSION_REFLECTION(2,190); +ACE_EXPLOSION_REFLECTION(2,200); +ACE_EXPLOSION_REFLECTION(2,210); +ACE_EXPLOSION_REFLECTION(2,220); +ACE_EXPLOSION_REFLECTION(2,230); +ACE_EXPLOSION_REFLECTION(2,240); +ACE_EXPLOSION_REFLECTION(2,250); +ACE_EXPLOSION_REFLECTION(2,260); +ACE_EXPLOSION_REFLECTION(2,270); +ACE_EXPLOSION_REFLECTION(2,280); +ACE_EXPLOSION_REFLECTION(2,290); +ACE_EXPLOSION_REFLECTION(2,300); +ACE_EXPLOSION_REFLECTION(2,310); +ACE_EXPLOSION_REFLECTION(2,320); +ACE_EXPLOSION_REFLECTION(2,330); +ACE_EXPLOSION_REFLECTION(2,340); +ACE_EXPLOSION_REFLECTION(2,350); +ACE_EXPLOSION_REFLECTION(2,360); +ACE_EXPLOSION_REFLECTION(2,370); +ACE_EXPLOSION_REFLECTION(2,380); +ACE_EXPLOSION_REFLECTION(2,390); +ACE_EXPLOSION_REFLECTION(2,400); +ACE_EXPLOSION_REFLECTION(2,410); +ACE_EXPLOSION_REFLECTION(2,420); +ACE_EXPLOSION_REFLECTION(2,430); +ACE_EXPLOSION_REFLECTION(2,440); +ACE_EXPLOSION_REFLECTION(2,450); +ACE_EXPLOSION_REFLECTION(2,460); +ACE_EXPLOSION_REFLECTION(2,470); +ACE_EXPLOSION_REFLECTION(2,480); +ACE_EXPLOSION_REFLECTION(2,490); +ACE_EXPLOSION_REFLECTION(2,500); +ACE_EXPLOSION_REFLECTION(4,10); +ACE_EXPLOSION_REFLECTION(4,20); +ACE_EXPLOSION_REFLECTION(4,30); +ACE_EXPLOSION_REFLECTION(4,40); +ACE_EXPLOSION_REFLECTION(4,50); +ACE_EXPLOSION_REFLECTION(4,60); +ACE_EXPLOSION_REFLECTION(4,70); +ACE_EXPLOSION_REFLECTION(4,80); +ACE_EXPLOSION_REFLECTION(4,90); +ACE_EXPLOSION_REFLECTION(4,100); +ACE_EXPLOSION_REFLECTION(4,110); +ACE_EXPLOSION_REFLECTION(4,120); +ACE_EXPLOSION_REFLECTION(4,130); +ACE_EXPLOSION_REFLECTION(4,140); +ACE_EXPLOSION_REFLECTION(4,150); +ACE_EXPLOSION_REFLECTION(4,160); +ACE_EXPLOSION_REFLECTION(4,170); +ACE_EXPLOSION_REFLECTION(4,180); +ACE_EXPLOSION_REFLECTION(4,190); +ACE_EXPLOSION_REFLECTION(4,200); +ACE_EXPLOSION_REFLECTION(4,210); +ACE_EXPLOSION_REFLECTION(4,220); +ACE_EXPLOSION_REFLECTION(4,230); +ACE_EXPLOSION_REFLECTION(4,240); +ACE_EXPLOSION_REFLECTION(4,250); +ACE_EXPLOSION_REFLECTION(4,260); +ACE_EXPLOSION_REFLECTION(4,270); +ACE_EXPLOSION_REFLECTION(4,280); +ACE_EXPLOSION_REFLECTION(4,290); +ACE_EXPLOSION_REFLECTION(4,300); +ACE_EXPLOSION_REFLECTION(4,310); +ACE_EXPLOSION_REFLECTION(4,320); +ACE_EXPLOSION_REFLECTION(4,330); +ACE_EXPLOSION_REFLECTION(4,340); +ACE_EXPLOSION_REFLECTION(4,350); +ACE_EXPLOSION_REFLECTION(4,360); +ACE_EXPLOSION_REFLECTION(4,370); +ACE_EXPLOSION_REFLECTION(4,380); +ACE_EXPLOSION_REFLECTION(4,390); +ACE_EXPLOSION_REFLECTION(4,400); +ACE_EXPLOSION_REFLECTION(4,410); +ACE_EXPLOSION_REFLECTION(4,420); +ACE_EXPLOSION_REFLECTION(4,430); +ACE_EXPLOSION_REFLECTION(4,440); +ACE_EXPLOSION_REFLECTION(4,450); +ACE_EXPLOSION_REFLECTION(4,460); +ACE_EXPLOSION_REFLECTION(4,470); +ACE_EXPLOSION_REFLECTION(4,480); +ACE_EXPLOSION_REFLECTION(4,490); +ACE_EXPLOSION_REFLECTION(4,500); +ACE_EXPLOSION_REFLECTION(6,10); +ACE_EXPLOSION_REFLECTION(6,20); +ACE_EXPLOSION_REFLECTION(6,30); +ACE_EXPLOSION_REFLECTION(6,40); +ACE_EXPLOSION_REFLECTION(6,50); +ACE_EXPLOSION_REFLECTION(6,60); +ACE_EXPLOSION_REFLECTION(6,70); +ACE_EXPLOSION_REFLECTION(6,80); +ACE_EXPLOSION_REFLECTION(6,90); +ACE_EXPLOSION_REFLECTION(6,100); +ACE_EXPLOSION_REFLECTION(6,110); +ACE_EXPLOSION_REFLECTION(6,120); +ACE_EXPLOSION_REFLECTION(6,130); +ACE_EXPLOSION_REFLECTION(6,140); +ACE_EXPLOSION_REFLECTION(6,150); +ACE_EXPLOSION_REFLECTION(6,160); +ACE_EXPLOSION_REFLECTION(6,170); +ACE_EXPLOSION_REFLECTION(6,180); +ACE_EXPLOSION_REFLECTION(6,190); +ACE_EXPLOSION_REFLECTION(6,200); +ACE_EXPLOSION_REFLECTION(6,210); +ACE_EXPLOSION_REFLECTION(6,220); +ACE_EXPLOSION_REFLECTION(6,230); +ACE_EXPLOSION_REFLECTION(6,240); +ACE_EXPLOSION_REFLECTION(6,250); +ACE_EXPLOSION_REFLECTION(6,260); +ACE_EXPLOSION_REFLECTION(6,270); +ACE_EXPLOSION_REFLECTION(6,280); +ACE_EXPLOSION_REFLECTION(6,290); +ACE_EXPLOSION_REFLECTION(6,300); +ACE_EXPLOSION_REFLECTION(6,310); +ACE_EXPLOSION_REFLECTION(6,320); +ACE_EXPLOSION_REFLECTION(6,330); +ACE_EXPLOSION_REFLECTION(6,340); +ACE_EXPLOSION_REFLECTION(6,350); +ACE_EXPLOSION_REFLECTION(6,360); +ACE_EXPLOSION_REFLECTION(6,370); +ACE_EXPLOSION_REFLECTION(6,380); +ACE_EXPLOSION_REFLECTION(6,390); +ACE_EXPLOSION_REFLECTION(6,400); +ACE_EXPLOSION_REFLECTION(6,410); +ACE_EXPLOSION_REFLECTION(6,420); +ACE_EXPLOSION_REFLECTION(6,430); +ACE_EXPLOSION_REFLECTION(6,440); +ACE_EXPLOSION_REFLECTION(6,450); +ACE_EXPLOSION_REFLECTION(6,460); +ACE_EXPLOSION_REFLECTION(6,470); +ACE_EXPLOSION_REFLECTION(6,480); +ACE_EXPLOSION_REFLECTION(6,490); +ACE_EXPLOSION_REFLECTION(6,500); +ACE_EXPLOSION_REFLECTION(8,10); +ACE_EXPLOSION_REFLECTION(8,20); +ACE_EXPLOSION_REFLECTION(8,30); +ACE_EXPLOSION_REFLECTION(8,40); +ACE_EXPLOSION_REFLECTION(8,50); +ACE_EXPLOSION_REFLECTION(8,60); +ACE_EXPLOSION_REFLECTION(8,70); +ACE_EXPLOSION_REFLECTION(8,80); +ACE_EXPLOSION_REFLECTION(8,90); +ACE_EXPLOSION_REFLECTION(8,100); +ACE_EXPLOSION_REFLECTION(8,110); +ACE_EXPLOSION_REFLECTION(8,120); +ACE_EXPLOSION_REFLECTION(8,130); +ACE_EXPLOSION_REFLECTION(8,140); +ACE_EXPLOSION_REFLECTION(8,150); +ACE_EXPLOSION_REFLECTION(8,160); +ACE_EXPLOSION_REFLECTION(8,170); +ACE_EXPLOSION_REFLECTION(8,180); +ACE_EXPLOSION_REFLECTION(8,190); +ACE_EXPLOSION_REFLECTION(8,200); +ACE_EXPLOSION_REFLECTION(8,210); +ACE_EXPLOSION_REFLECTION(8,220); +ACE_EXPLOSION_REFLECTION(8,230); +ACE_EXPLOSION_REFLECTION(8,240); +ACE_EXPLOSION_REFLECTION(8,250); +ACE_EXPLOSION_REFLECTION(8,260); +ACE_EXPLOSION_REFLECTION(8,270); +ACE_EXPLOSION_REFLECTION(8,280); +ACE_EXPLOSION_REFLECTION(8,290); +ACE_EXPLOSION_REFLECTION(8,300); +ACE_EXPLOSION_REFLECTION(8,310); +ACE_EXPLOSION_REFLECTION(8,320); +ACE_EXPLOSION_REFLECTION(8,330); +ACE_EXPLOSION_REFLECTION(8,340); +ACE_EXPLOSION_REFLECTION(8,350); +ACE_EXPLOSION_REFLECTION(8,360); +ACE_EXPLOSION_REFLECTION(8,370); +ACE_EXPLOSION_REFLECTION(8,380); +ACE_EXPLOSION_REFLECTION(8,390); +ACE_EXPLOSION_REFLECTION(8,400); +ACE_EXPLOSION_REFLECTION(8,410); +ACE_EXPLOSION_REFLECTION(8,420); +ACE_EXPLOSION_REFLECTION(8,430); +ACE_EXPLOSION_REFLECTION(8,440); +ACE_EXPLOSION_REFLECTION(8,450); +ACE_EXPLOSION_REFLECTION(8,460); +ACE_EXPLOSION_REFLECTION(8,470); +ACE_EXPLOSION_REFLECTION(8,480); +ACE_EXPLOSION_REFLECTION(8,490); +ACE_EXPLOSION_REFLECTION(8,500); +ACE_EXPLOSION_REFLECTION(10,10); +ACE_EXPLOSION_REFLECTION(10,20); +ACE_EXPLOSION_REFLECTION(10,30); +ACE_EXPLOSION_REFLECTION(10,40); +ACE_EXPLOSION_REFLECTION(10,50); +ACE_EXPLOSION_REFLECTION(10,60); +ACE_EXPLOSION_REFLECTION(10,70); +ACE_EXPLOSION_REFLECTION(10,80); +ACE_EXPLOSION_REFLECTION(10,90); +ACE_EXPLOSION_REFLECTION(10,100); +ACE_EXPLOSION_REFLECTION(10,110); +ACE_EXPLOSION_REFLECTION(10,120); +ACE_EXPLOSION_REFLECTION(10,130); +ACE_EXPLOSION_REFLECTION(10,140); +ACE_EXPLOSION_REFLECTION(10,150); +ACE_EXPLOSION_REFLECTION(10,160); +ACE_EXPLOSION_REFLECTION(10,170); +ACE_EXPLOSION_REFLECTION(10,180); +ACE_EXPLOSION_REFLECTION(10,190); +ACE_EXPLOSION_REFLECTION(10,200); +ACE_EXPLOSION_REFLECTION(10,210); +ACE_EXPLOSION_REFLECTION(10,220); +ACE_EXPLOSION_REFLECTION(10,230); +ACE_EXPLOSION_REFLECTION(10,240); +ACE_EXPLOSION_REFLECTION(10,250); +ACE_EXPLOSION_REFLECTION(10,260); +ACE_EXPLOSION_REFLECTION(10,270); +ACE_EXPLOSION_REFLECTION(10,280); +ACE_EXPLOSION_REFLECTION(10,290); +ACE_EXPLOSION_REFLECTION(10,300); +ACE_EXPLOSION_REFLECTION(10,310); +ACE_EXPLOSION_REFLECTION(10,320); +ACE_EXPLOSION_REFLECTION(10,330); +ACE_EXPLOSION_REFLECTION(10,340); +ACE_EXPLOSION_REFLECTION(10,350); +ACE_EXPLOSION_REFLECTION(10,360); +ACE_EXPLOSION_REFLECTION(10,370); +ACE_EXPLOSION_REFLECTION(10,380); +ACE_EXPLOSION_REFLECTION(10,390); +ACE_EXPLOSION_REFLECTION(10,400); +ACE_EXPLOSION_REFLECTION(10,410); +ACE_EXPLOSION_REFLECTION(10,420); +ACE_EXPLOSION_REFLECTION(10,430); +ACE_EXPLOSION_REFLECTION(10,440); +ACE_EXPLOSION_REFLECTION(10,450); +ACE_EXPLOSION_REFLECTION(10,460); +ACE_EXPLOSION_REFLECTION(10,470); +ACE_EXPLOSION_REFLECTION(10,480); +ACE_EXPLOSION_REFLECTION(10,490); +ACE_EXPLOSION_REFLECTION(10,500); +ACE_EXPLOSION_REFLECTION(12,10); +ACE_EXPLOSION_REFLECTION(12,20); +ACE_EXPLOSION_REFLECTION(12,30); +ACE_EXPLOSION_REFLECTION(12,40); +ACE_EXPLOSION_REFLECTION(12,50); +ACE_EXPLOSION_REFLECTION(12,60); +ACE_EXPLOSION_REFLECTION(12,70); +ACE_EXPLOSION_REFLECTION(12,80); +ACE_EXPLOSION_REFLECTION(12,90); +ACE_EXPLOSION_REFLECTION(12,100); +ACE_EXPLOSION_REFLECTION(12,110); +ACE_EXPLOSION_REFLECTION(12,120); +ACE_EXPLOSION_REFLECTION(12,130); +ACE_EXPLOSION_REFLECTION(12,140); +ACE_EXPLOSION_REFLECTION(12,150); +ACE_EXPLOSION_REFLECTION(12,160); +ACE_EXPLOSION_REFLECTION(12,170); +ACE_EXPLOSION_REFLECTION(12,180); +ACE_EXPLOSION_REFLECTION(12,190); +ACE_EXPLOSION_REFLECTION(12,200); +ACE_EXPLOSION_REFLECTION(12,210); +ACE_EXPLOSION_REFLECTION(12,220); +ACE_EXPLOSION_REFLECTION(12,230); +ACE_EXPLOSION_REFLECTION(12,240); +ACE_EXPLOSION_REFLECTION(12,250); +ACE_EXPLOSION_REFLECTION(12,260); +ACE_EXPLOSION_REFLECTION(12,270); +ACE_EXPLOSION_REFLECTION(12,280); +ACE_EXPLOSION_REFLECTION(12,290); +ACE_EXPLOSION_REFLECTION(12,300); +ACE_EXPLOSION_REFLECTION(12,310); +ACE_EXPLOSION_REFLECTION(12,320); +ACE_EXPLOSION_REFLECTION(12,330); +ACE_EXPLOSION_REFLECTION(12,340); +ACE_EXPLOSION_REFLECTION(12,350); +ACE_EXPLOSION_REFLECTION(12,360); +ACE_EXPLOSION_REFLECTION(12,370); +ACE_EXPLOSION_REFLECTION(12,380); +ACE_EXPLOSION_REFLECTION(12,390); +ACE_EXPLOSION_REFLECTION(12,400); +ACE_EXPLOSION_REFLECTION(12,410); +ACE_EXPLOSION_REFLECTION(12,420); +ACE_EXPLOSION_REFLECTION(12,430); +ACE_EXPLOSION_REFLECTION(12,440); +ACE_EXPLOSION_REFLECTION(12,450); +ACE_EXPLOSION_REFLECTION(12,460); +ACE_EXPLOSION_REFLECTION(12,470); +ACE_EXPLOSION_REFLECTION(12,480); +ACE_EXPLOSION_REFLECTION(12,490); +ACE_EXPLOSION_REFLECTION(12,500); +ACE_EXPLOSION_REFLECTION(14,10); +ACE_EXPLOSION_REFLECTION(14,20); +ACE_EXPLOSION_REFLECTION(14,30); +ACE_EXPLOSION_REFLECTION(14,40); +ACE_EXPLOSION_REFLECTION(14,50); +ACE_EXPLOSION_REFLECTION(14,60); +ACE_EXPLOSION_REFLECTION(14,70); +ACE_EXPLOSION_REFLECTION(14,80); +ACE_EXPLOSION_REFLECTION(14,90); +ACE_EXPLOSION_REFLECTION(14,100); +ACE_EXPLOSION_REFLECTION(14,110); +ACE_EXPLOSION_REFLECTION(14,120); +ACE_EXPLOSION_REFLECTION(14,130); +ACE_EXPLOSION_REFLECTION(14,140); +ACE_EXPLOSION_REFLECTION(14,150); +ACE_EXPLOSION_REFLECTION(14,160); +ACE_EXPLOSION_REFLECTION(14,170); +ACE_EXPLOSION_REFLECTION(14,180); +ACE_EXPLOSION_REFLECTION(14,190); +ACE_EXPLOSION_REFLECTION(14,200); +ACE_EXPLOSION_REFLECTION(14,210); +ACE_EXPLOSION_REFLECTION(14,220); +ACE_EXPLOSION_REFLECTION(14,230); +ACE_EXPLOSION_REFLECTION(14,240); +ACE_EXPLOSION_REFLECTION(14,250); +ACE_EXPLOSION_REFLECTION(14,260); +ACE_EXPLOSION_REFLECTION(14,270); +ACE_EXPLOSION_REFLECTION(14,280); +ACE_EXPLOSION_REFLECTION(14,290); +ACE_EXPLOSION_REFLECTION(14,300); +ACE_EXPLOSION_REFLECTION(14,310); +ACE_EXPLOSION_REFLECTION(14,320); +ACE_EXPLOSION_REFLECTION(14,330); +ACE_EXPLOSION_REFLECTION(14,340); +ACE_EXPLOSION_REFLECTION(14,350); +ACE_EXPLOSION_REFLECTION(14,360); +ACE_EXPLOSION_REFLECTION(14,370); +ACE_EXPLOSION_REFLECTION(14,380); +ACE_EXPLOSION_REFLECTION(14,390); +ACE_EXPLOSION_REFLECTION(14,400); +ACE_EXPLOSION_REFLECTION(14,410); +ACE_EXPLOSION_REFLECTION(14,420); +ACE_EXPLOSION_REFLECTION(14,430); +ACE_EXPLOSION_REFLECTION(14,440); +ACE_EXPLOSION_REFLECTION(14,450); +ACE_EXPLOSION_REFLECTION(14,460); +ACE_EXPLOSION_REFLECTION(14,470); +ACE_EXPLOSION_REFLECTION(14,480); +ACE_EXPLOSION_REFLECTION(14,490); +ACE_EXPLOSION_REFLECTION(14,500); +ACE_EXPLOSION_REFLECTION(16,10); +ACE_EXPLOSION_REFLECTION(16,20); +ACE_EXPLOSION_REFLECTION(16,30); +ACE_EXPLOSION_REFLECTION(16,40); +ACE_EXPLOSION_REFLECTION(16,50); +ACE_EXPLOSION_REFLECTION(16,60); +ACE_EXPLOSION_REFLECTION(16,70); +ACE_EXPLOSION_REFLECTION(16,80); +ACE_EXPLOSION_REFLECTION(16,90); +ACE_EXPLOSION_REFLECTION(16,100); +ACE_EXPLOSION_REFLECTION(16,110); +ACE_EXPLOSION_REFLECTION(16,120); +ACE_EXPLOSION_REFLECTION(16,130); +ACE_EXPLOSION_REFLECTION(16,140); +ACE_EXPLOSION_REFLECTION(16,150); +ACE_EXPLOSION_REFLECTION(16,160); +ACE_EXPLOSION_REFLECTION(16,170); +ACE_EXPLOSION_REFLECTION(16,180); +ACE_EXPLOSION_REFLECTION(16,190); +ACE_EXPLOSION_REFLECTION(16,200); +ACE_EXPLOSION_REFLECTION(16,210); +ACE_EXPLOSION_REFLECTION(16,220); +ACE_EXPLOSION_REFLECTION(16,230); +ACE_EXPLOSION_REFLECTION(16,240); +ACE_EXPLOSION_REFLECTION(16,250); +ACE_EXPLOSION_REFLECTION(16,260); +ACE_EXPLOSION_REFLECTION(16,270); +ACE_EXPLOSION_REFLECTION(16,280); +ACE_EXPLOSION_REFLECTION(16,290); +ACE_EXPLOSION_REFLECTION(16,300); +ACE_EXPLOSION_REFLECTION(16,310); +ACE_EXPLOSION_REFLECTION(16,320); +ACE_EXPLOSION_REFLECTION(16,330); +ACE_EXPLOSION_REFLECTION(16,340); +ACE_EXPLOSION_REFLECTION(16,350); +ACE_EXPLOSION_REFLECTION(16,360); +ACE_EXPLOSION_REFLECTION(16,370); +ACE_EXPLOSION_REFLECTION(16,380); +ACE_EXPLOSION_REFLECTION(16,390); +ACE_EXPLOSION_REFLECTION(16,400); +ACE_EXPLOSION_REFLECTION(16,410); +ACE_EXPLOSION_REFLECTION(16,420); +ACE_EXPLOSION_REFLECTION(16,430); +ACE_EXPLOSION_REFLECTION(16,440); +ACE_EXPLOSION_REFLECTION(16,450); +ACE_EXPLOSION_REFLECTION(16,460); +ACE_EXPLOSION_REFLECTION(16,470); +ACE_EXPLOSION_REFLECTION(16,480); +ACE_EXPLOSION_REFLECTION(16,490); +ACE_EXPLOSION_REFLECTION(16,500); +ACE_EXPLOSION_REFLECTION(18,10); +ACE_EXPLOSION_REFLECTION(18,20); +ACE_EXPLOSION_REFLECTION(18,30); +ACE_EXPLOSION_REFLECTION(18,40); +ACE_EXPLOSION_REFLECTION(18,50); +ACE_EXPLOSION_REFLECTION(18,60); +ACE_EXPLOSION_REFLECTION(18,70); +ACE_EXPLOSION_REFLECTION(18,80); +ACE_EXPLOSION_REFLECTION(18,90); +ACE_EXPLOSION_REFLECTION(18,100); +ACE_EXPLOSION_REFLECTION(18,110); +ACE_EXPLOSION_REFLECTION(18,120); +ACE_EXPLOSION_REFLECTION(18,130); +ACE_EXPLOSION_REFLECTION(18,140); +ACE_EXPLOSION_REFLECTION(18,150); +ACE_EXPLOSION_REFLECTION(18,160); +ACE_EXPLOSION_REFLECTION(18,170); +ACE_EXPLOSION_REFLECTION(18,180); +ACE_EXPLOSION_REFLECTION(18,190); +ACE_EXPLOSION_REFLECTION(18,200); +ACE_EXPLOSION_REFLECTION(18,210); +ACE_EXPLOSION_REFLECTION(18,220); +ACE_EXPLOSION_REFLECTION(18,230); +ACE_EXPLOSION_REFLECTION(18,240); +ACE_EXPLOSION_REFLECTION(18,250); +ACE_EXPLOSION_REFLECTION(18,260); +ACE_EXPLOSION_REFLECTION(18,270); +ACE_EXPLOSION_REFLECTION(18,280); +ACE_EXPLOSION_REFLECTION(18,290); +ACE_EXPLOSION_REFLECTION(18,300); +ACE_EXPLOSION_REFLECTION(18,310); +ACE_EXPLOSION_REFLECTION(18,320); +ACE_EXPLOSION_REFLECTION(18,330); +ACE_EXPLOSION_REFLECTION(18,340); +ACE_EXPLOSION_REFLECTION(18,350); +ACE_EXPLOSION_REFLECTION(18,360); +ACE_EXPLOSION_REFLECTION(18,370); +ACE_EXPLOSION_REFLECTION(18,380); +ACE_EXPLOSION_REFLECTION(18,390); +ACE_EXPLOSION_REFLECTION(18,400); +ACE_EXPLOSION_REFLECTION(18,410); +ACE_EXPLOSION_REFLECTION(18,420); +ACE_EXPLOSION_REFLECTION(18,430); +ACE_EXPLOSION_REFLECTION(18,440); +ACE_EXPLOSION_REFLECTION(18,450); +ACE_EXPLOSION_REFLECTION(18,460); +ACE_EXPLOSION_REFLECTION(18,470); +ACE_EXPLOSION_REFLECTION(18,480); +ACE_EXPLOSION_REFLECTION(18,490); +ACE_EXPLOSION_REFLECTION(18,500); +ACE_EXPLOSION_REFLECTION(20,10); +ACE_EXPLOSION_REFLECTION(20,20); +ACE_EXPLOSION_REFLECTION(20,30); +ACE_EXPLOSION_REFLECTION(20,40); +ACE_EXPLOSION_REFLECTION(20,50); +ACE_EXPLOSION_REFLECTION(20,60); +ACE_EXPLOSION_REFLECTION(20,70); +ACE_EXPLOSION_REFLECTION(20,80); +ACE_EXPLOSION_REFLECTION(20,90); +ACE_EXPLOSION_REFLECTION(20,100); +ACE_EXPLOSION_REFLECTION(20,110); +ACE_EXPLOSION_REFLECTION(20,120); +ACE_EXPLOSION_REFLECTION(20,130); +ACE_EXPLOSION_REFLECTION(20,140); +ACE_EXPLOSION_REFLECTION(20,150); +ACE_EXPLOSION_REFLECTION(20,160); +ACE_EXPLOSION_REFLECTION(20,170); +ACE_EXPLOSION_REFLECTION(20,180); +ACE_EXPLOSION_REFLECTION(20,190); +ACE_EXPLOSION_REFLECTION(20,200); +ACE_EXPLOSION_REFLECTION(20,210); +ACE_EXPLOSION_REFLECTION(20,220); +ACE_EXPLOSION_REFLECTION(20,230); +ACE_EXPLOSION_REFLECTION(20,240); +ACE_EXPLOSION_REFLECTION(20,250); +ACE_EXPLOSION_REFLECTION(20,260); +ACE_EXPLOSION_REFLECTION(20,270); +ACE_EXPLOSION_REFLECTION(20,280); +ACE_EXPLOSION_REFLECTION(20,290); +ACE_EXPLOSION_REFLECTION(20,300); +ACE_EXPLOSION_REFLECTION(20,310); +ACE_EXPLOSION_REFLECTION(20,320); +ACE_EXPLOSION_REFLECTION(20,330); +ACE_EXPLOSION_REFLECTION(20,340); +ACE_EXPLOSION_REFLECTION(20,350); +ACE_EXPLOSION_REFLECTION(20,360); +ACE_EXPLOSION_REFLECTION(20,370); +ACE_EXPLOSION_REFLECTION(20,380); +ACE_EXPLOSION_REFLECTION(20,390); +ACE_EXPLOSION_REFLECTION(20,400); +ACE_EXPLOSION_REFLECTION(20,410); +ACE_EXPLOSION_REFLECTION(20,420); +ACE_EXPLOSION_REFLECTION(20,430); +ACE_EXPLOSION_REFLECTION(20,440); +ACE_EXPLOSION_REFLECTION(20,450); +ACE_EXPLOSION_REFLECTION(20,460); +ACE_EXPLOSION_REFLECTION(20,470); +ACE_EXPLOSION_REFLECTION(20,480); +ACE_EXPLOSION_REFLECTION(20,490); +ACE_EXPLOSION_REFLECTION(20,500); +ACE_EXPLOSION_REFLECTION(22,10); +ACE_EXPLOSION_REFLECTION(22,20); +ACE_EXPLOSION_REFLECTION(22,30); +ACE_EXPLOSION_REFLECTION(22,40); +ACE_EXPLOSION_REFLECTION(22,50); +ACE_EXPLOSION_REFLECTION(22,60); +ACE_EXPLOSION_REFLECTION(22,70); +ACE_EXPLOSION_REFLECTION(22,80); +ACE_EXPLOSION_REFLECTION(22,90); +ACE_EXPLOSION_REFLECTION(22,100); +ACE_EXPLOSION_REFLECTION(22,110); +ACE_EXPLOSION_REFLECTION(22,120); +ACE_EXPLOSION_REFLECTION(22,130); +ACE_EXPLOSION_REFLECTION(22,140); +ACE_EXPLOSION_REFLECTION(22,150); +ACE_EXPLOSION_REFLECTION(22,160); +ACE_EXPLOSION_REFLECTION(22,170); +ACE_EXPLOSION_REFLECTION(22,180); +ACE_EXPLOSION_REFLECTION(22,190); +ACE_EXPLOSION_REFLECTION(22,200); +ACE_EXPLOSION_REFLECTION(22,210); +ACE_EXPLOSION_REFLECTION(22,220); +ACE_EXPLOSION_REFLECTION(22,230); +ACE_EXPLOSION_REFLECTION(22,240); +ACE_EXPLOSION_REFLECTION(22,250); +ACE_EXPLOSION_REFLECTION(22,260); +ACE_EXPLOSION_REFLECTION(22,270); +ACE_EXPLOSION_REFLECTION(22,280); +ACE_EXPLOSION_REFLECTION(22,290); +ACE_EXPLOSION_REFLECTION(22,300); +ACE_EXPLOSION_REFLECTION(22,310); +ACE_EXPLOSION_REFLECTION(22,320); +ACE_EXPLOSION_REFLECTION(22,330); +ACE_EXPLOSION_REFLECTION(22,340); +ACE_EXPLOSION_REFLECTION(22,350); +ACE_EXPLOSION_REFLECTION(22,360); +ACE_EXPLOSION_REFLECTION(22,370); +ACE_EXPLOSION_REFLECTION(22,380); +ACE_EXPLOSION_REFLECTION(22,390); +ACE_EXPLOSION_REFLECTION(22,400); +ACE_EXPLOSION_REFLECTION(22,410); +ACE_EXPLOSION_REFLECTION(22,420); +ACE_EXPLOSION_REFLECTION(22,430); +ACE_EXPLOSION_REFLECTION(22,440); +ACE_EXPLOSION_REFLECTION(22,450); +ACE_EXPLOSION_REFLECTION(22,460); +ACE_EXPLOSION_REFLECTION(22,470); +ACE_EXPLOSION_REFLECTION(22,480); +ACE_EXPLOSION_REFLECTION(22,490); +ACE_EXPLOSION_REFLECTION(22,500); +ACE_EXPLOSION_REFLECTION(24,10); +ACE_EXPLOSION_REFLECTION(24,20); +ACE_EXPLOSION_REFLECTION(24,30); +ACE_EXPLOSION_REFLECTION(24,40); +ACE_EXPLOSION_REFLECTION(24,50); +ACE_EXPLOSION_REFLECTION(24,60); +ACE_EXPLOSION_REFLECTION(24,70); +ACE_EXPLOSION_REFLECTION(24,80); +ACE_EXPLOSION_REFLECTION(24,90); +ACE_EXPLOSION_REFLECTION(24,100); +ACE_EXPLOSION_REFLECTION(24,110); +ACE_EXPLOSION_REFLECTION(24,120); +ACE_EXPLOSION_REFLECTION(24,130); +ACE_EXPLOSION_REFLECTION(24,140); +ACE_EXPLOSION_REFLECTION(24,150); +ACE_EXPLOSION_REFLECTION(24,160); +ACE_EXPLOSION_REFLECTION(24,170); +ACE_EXPLOSION_REFLECTION(24,180); +ACE_EXPLOSION_REFLECTION(24,190); +ACE_EXPLOSION_REFLECTION(24,200); +ACE_EXPLOSION_REFLECTION(24,210); +ACE_EXPLOSION_REFLECTION(24,220); +ACE_EXPLOSION_REFLECTION(24,230); +ACE_EXPLOSION_REFLECTION(24,240); +ACE_EXPLOSION_REFLECTION(24,250); +ACE_EXPLOSION_REFLECTION(24,260); +ACE_EXPLOSION_REFLECTION(24,270); +ACE_EXPLOSION_REFLECTION(24,280); +ACE_EXPLOSION_REFLECTION(24,290); +ACE_EXPLOSION_REFLECTION(24,300); +ACE_EXPLOSION_REFLECTION(24,310); +ACE_EXPLOSION_REFLECTION(24,320); +ACE_EXPLOSION_REFLECTION(24,330); +ACE_EXPLOSION_REFLECTION(24,340); +ACE_EXPLOSION_REFLECTION(24,350); +ACE_EXPLOSION_REFLECTION(24,360); +ACE_EXPLOSION_REFLECTION(24,370); +ACE_EXPLOSION_REFLECTION(24,380); +ACE_EXPLOSION_REFLECTION(24,390); +ACE_EXPLOSION_REFLECTION(24,400); +ACE_EXPLOSION_REFLECTION(24,410); +ACE_EXPLOSION_REFLECTION(24,420); +ACE_EXPLOSION_REFLECTION(24,430); +ACE_EXPLOSION_REFLECTION(24,440); +ACE_EXPLOSION_REFLECTION(24,450); +ACE_EXPLOSION_REFLECTION(24,460); +ACE_EXPLOSION_REFLECTION(24,470); +ACE_EXPLOSION_REFLECTION(24,480); +ACE_EXPLOSION_REFLECTION(24,490); +ACE_EXPLOSION_REFLECTION(24,500); +ACE_EXPLOSION_REFLECTION(26,10); +ACE_EXPLOSION_REFLECTION(26,20); +ACE_EXPLOSION_REFLECTION(26,30); +ACE_EXPLOSION_REFLECTION(26,40); +ACE_EXPLOSION_REFLECTION(26,50); +ACE_EXPLOSION_REFLECTION(26,60); +ACE_EXPLOSION_REFLECTION(26,70); +ACE_EXPLOSION_REFLECTION(26,80); +ACE_EXPLOSION_REFLECTION(26,90); +ACE_EXPLOSION_REFLECTION(26,100); +ACE_EXPLOSION_REFLECTION(26,110); +ACE_EXPLOSION_REFLECTION(26,120); +ACE_EXPLOSION_REFLECTION(26,130); +ACE_EXPLOSION_REFLECTION(26,140); +ACE_EXPLOSION_REFLECTION(26,150); +ACE_EXPLOSION_REFLECTION(26,160); +ACE_EXPLOSION_REFLECTION(26,170); +ACE_EXPLOSION_REFLECTION(26,180); +ACE_EXPLOSION_REFLECTION(26,190); +ACE_EXPLOSION_REFLECTION(26,200); +ACE_EXPLOSION_REFLECTION(26,210); +ACE_EXPLOSION_REFLECTION(26,220); +ACE_EXPLOSION_REFLECTION(26,230); +ACE_EXPLOSION_REFLECTION(26,240); +ACE_EXPLOSION_REFLECTION(26,250); +ACE_EXPLOSION_REFLECTION(26,260); +ACE_EXPLOSION_REFLECTION(26,270); +ACE_EXPLOSION_REFLECTION(26,280); +ACE_EXPLOSION_REFLECTION(26,290); +ACE_EXPLOSION_REFLECTION(26,300); +ACE_EXPLOSION_REFLECTION(26,310); +ACE_EXPLOSION_REFLECTION(26,320); +ACE_EXPLOSION_REFLECTION(26,330); +ACE_EXPLOSION_REFLECTION(26,340); +ACE_EXPLOSION_REFLECTION(26,350); +ACE_EXPLOSION_REFLECTION(26,360); +ACE_EXPLOSION_REFLECTION(26,370); +ACE_EXPLOSION_REFLECTION(26,380); +ACE_EXPLOSION_REFLECTION(26,390); +ACE_EXPLOSION_REFLECTION(26,400); +ACE_EXPLOSION_REFLECTION(26,410); +ACE_EXPLOSION_REFLECTION(26,420); +ACE_EXPLOSION_REFLECTION(26,430); +ACE_EXPLOSION_REFLECTION(26,440); +ACE_EXPLOSION_REFLECTION(26,450); +ACE_EXPLOSION_REFLECTION(26,460); +ACE_EXPLOSION_REFLECTION(26,470); +ACE_EXPLOSION_REFLECTION(26,480); +ACE_EXPLOSION_REFLECTION(26,490); +ACE_EXPLOSION_REFLECTION(26,500); +ACE_EXPLOSION_REFLECTION(28,10); +ACE_EXPLOSION_REFLECTION(28,20); +ACE_EXPLOSION_REFLECTION(28,30); +ACE_EXPLOSION_REFLECTION(28,40); +ACE_EXPLOSION_REFLECTION(28,50); +ACE_EXPLOSION_REFLECTION(28,60); +ACE_EXPLOSION_REFLECTION(28,70); +ACE_EXPLOSION_REFLECTION(28,80); +ACE_EXPLOSION_REFLECTION(28,90); +ACE_EXPLOSION_REFLECTION(28,100); +ACE_EXPLOSION_REFLECTION(28,110); +ACE_EXPLOSION_REFLECTION(28,120); +ACE_EXPLOSION_REFLECTION(28,130); +ACE_EXPLOSION_REFLECTION(28,140); +ACE_EXPLOSION_REFLECTION(28,150); +ACE_EXPLOSION_REFLECTION(28,160); +ACE_EXPLOSION_REFLECTION(28,170); +ACE_EXPLOSION_REFLECTION(28,180); +ACE_EXPLOSION_REFLECTION(28,190); +ACE_EXPLOSION_REFLECTION(28,200); +ACE_EXPLOSION_REFLECTION(28,210); +ACE_EXPLOSION_REFLECTION(28,220); +ACE_EXPLOSION_REFLECTION(28,230); +ACE_EXPLOSION_REFLECTION(28,240); +ACE_EXPLOSION_REFLECTION(28,250); +ACE_EXPLOSION_REFLECTION(28,260); +ACE_EXPLOSION_REFLECTION(28,270); +ACE_EXPLOSION_REFLECTION(28,280); +ACE_EXPLOSION_REFLECTION(28,290); +ACE_EXPLOSION_REFLECTION(28,300); +ACE_EXPLOSION_REFLECTION(28,310); +ACE_EXPLOSION_REFLECTION(28,320); +ACE_EXPLOSION_REFLECTION(28,330); +ACE_EXPLOSION_REFLECTION(28,340); +ACE_EXPLOSION_REFLECTION(28,350); +ACE_EXPLOSION_REFLECTION(28,360); +ACE_EXPLOSION_REFLECTION(28,370); +ACE_EXPLOSION_REFLECTION(28,380); +ACE_EXPLOSION_REFLECTION(28,390); +ACE_EXPLOSION_REFLECTION(28,400); +ACE_EXPLOSION_REFLECTION(28,410); +ACE_EXPLOSION_REFLECTION(28,420); +ACE_EXPLOSION_REFLECTION(28,430); +ACE_EXPLOSION_REFLECTION(28,440); +ACE_EXPLOSION_REFLECTION(28,450); +ACE_EXPLOSION_REFLECTION(28,460); +ACE_EXPLOSION_REFLECTION(28,470); +ACE_EXPLOSION_REFLECTION(28,480); +ACE_EXPLOSION_REFLECTION(28,490); +ACE_EXPLOSION_REFLECTION(28,500); +ACE_EXPLOSION_REFLECTION(30,10); +ACE_EXPLOSION_REFLECTION(30,20); +ACE_EXPLOSION_REFLECTION(30,30); +ACE_EXPLOSION_REFLECTION(30,40); +ACE_EXPLOSION_REFLECTION(30,50); +ACE_EXPLOSION_REFLECTION(30,60); +ACE_EXPLOSION_REFLECTION(30,70); +ACE_EXPLOSION_REFLECTION(30,80); +ACE_EXPLOSION_REFLECTION(30,90); +ACE_EXPLOSION_REFLECTION(30,100); +ACE_EXPLOSION_REFLECTION(30,110); +ACE_EXPLOSION_REFLECTION(30,120); +ACE_EXPLOSION_REFLECTION(30,130); +ACE_EXPLOSION_REFLECTION(30,140); +ACE_EXPLOSION_REFLECTION(30,150); +ACE_EXPLOSION_REFLECTION(30,160); +ACE_EXPLOSION_REFLECTION(30,170); +ACE_EXPLOSION_REFLECTION(30,180); +ACE_EXPLOSION_REFLECTION(30,190); +ACE_EXPLOSION_REFLECTION(30,200); +ACE_EXPLOSION_REFLECTION(30,210); +ACE_EXPLOSION_REFLECTION(30,220); +ACE_EXPLOSION_REFLECTION(30,230); +ACE_EXPLOSION_REFLECTION(30,240); +ACE_EXPLOSION_REFLECTION(30,250); +ACE_EXPLOSION_REFLECTION(30,260); +ACE_EXPLOSION_REFLECTION(30,270); +ACE_EXPLOSION_REFLECTION(30,280); +ACE_EXPLOSION_REFLECTION(30,290); +ACE_EXPLOSION_REFLECTION(30,300); +ACE_EXPLOSION_REFLECTION(30,310); +ACE_EXPLOSION_REFLECTION(30,320); +ACE_EXPLOSION_REFLECTION(30,330); +ACE_EXPLOSION_REFLECTION(30,340); +ACE_EXPLOSION_REFLECTION(30,350); +ACE_EXPLOSION_REFLECTION(30,360); +ACE_EXPLOSION_REFLECTION(30,370); +ACE_EXPLOSION_REFLECTION(30,380); +ACE_EXPLOSION_REFLECTION(30,390); +ACE_EXPLOSION_REFLECTION(30,400); +ACE_EXPLOSION_REFLECTION(30,410); +ACE_EXPLOSION_REFLECTION(30,420); +ACE_EXPLOSION_REFLECTION(30,430); +ACE_EXPLOSION_REFLECTION(30,440); +ACE_EXPLOSION_REFLECTION(30,450); +ACE_EXPLOSION_REFLECTION(30,460); +ACE_EXPLOSION_REFLECTION(30,470); +ACE_EXPLOSION_REFLECTION(30,480); +ACE_EXPLOSION_REFLECTION(30,490); +ACE_EXPLOSION_REFLECTION(30,500); +ACE_EXPLOSION_REFLECTION(32,10); +ACE_EXPLOSION_REFLECTION(32,20); +ACE_EXPLOSION_REFLECTION(32,30); +ACE_EXPLOSION_REFLECTION(32,40); +ACE_EXPLOSION_REFLECTION(32,50); +ACE_EXPLOSION_REFLECTION(32,60); +ACE_EXPLOSION_REFLECTION(32,70); +ACE_EXPLOSION_REFLECTION(32,80); +ACE_EXPLOSION_REFLECTION(32,90); +ACE_EXPLOSION_REFLECTION(32,100); +ACE_EXPLOSION_REFLECTION(32,110); +ACE_EXPLOSION_REFLECTION(32,120); +ACE_EXPLOSION_REFLECTION(32,130); +ACE_EXPLOSION_REFLECTION(32,140); +ACE_EXPLOSION_REFLECTION(32,150); +ACE_EXPLOSION_REFLECTION(32,160); +ACE_EXPLOSION_REFLECTION(32,170); +ACE_EXPLOSION_REFLECTION(32,180); +ACE_EXPLOSION_REFLECTION(32,190); +ACE_EXPLOSION_REFLECTION(32,200); +ACE_EXPLOSION_REFLECTION(32,210); +ACE_EXPLOSION_REFLECTION(32,220); +ACE_EXPLOSION_REFLECTION(32,230); +ACE_EXPLOSION_REFLECTION(32,240); +ACE_EXPLOSION_REFLECTION(32,250); +ACE_EXPLOSION_REFLECTION(32,260); +ACE_EXPLOSION_REFLECTION(32,270); +ACE_EXPLOSION_REFLECTION(32,280); +ACE_EXPLOSION_REFLECTION(32,290); +ACE_EXPLOSION_REFLECTION(32,300); +ACE_EXPLOSION_REFLECTION(32,310); +ACE_EXPLOSION_REFLECTION(32,320); +ACE_EXPLOSION_REFLECTION(32,330); +ACE_EXPLOSION_REFLECTION(32,340); +ACE_EXPLOSION_REFLECTION(32,350); +ACE_EXPLOSION_REFLECTION(32,360); +ACE_EXPLOSION_REFLECTION(32,370); +ACE_EXPLOSION_REFLECTION(32,380); +ACE_EXPLOSION_REFLECTION(32,390); +ACE_EXPLOSION_REFLECTION(32,400); +ACE_EXPLOSION_REFLECTION(32,410); +ACE_EXPLOSION_REFLECTION(32,420); +ACE_EXPLOSION_REFLECTION(32,430); +ACE_EXPLOSION_REFLECTION(32,440); +ACE_EXPLOSION_REFLECTION(32,450); +ACE_EXPLOSION_REFLECTION(32,460); +ACE_EXPLOSION_REFLECTION(32,470); +ACE_EXPLOSION_REFLECTION(32,480); +ACE_EXPLOSION_REFLECTION(32,490); +ACE_EXPLOSION_REFLECTION(32,500); +ACE_EXPLOSION_REFLECTION(34,10); +ACE_EXPLOSION_REFLECTION(34,20); +ACE_EXPLOSION_REFLECTION(34,30); +ACE_EXPLOSION_REFLECTION(34,40); +ACE_EXPLOSION_REFLECTION(34,50); +ACE_EXPLOSION_REFLECTION(34,60); +ACE_EXPLOSION_REFLECTION(34,70); +ACE_EXPLOSION_REFLECTION(34,80); +ACE_EXPLOSION_REFLECTION(34,90); +ACE_EXPLOSION_REFLECTION(34,100); +ACE_EXPLOSION_REFLECTION(34,110); +ACE_EXPLOSION_REFLECTION(34,120); +ACE_EXPLOSION_REFLECTION(34,130); +ACE_EXPLOSION_REFLECTION(34,140); +ACE_EXPLOSION_REFLECTION(34,150); +ACE_EXPLOSION_REFLECTION(34,160); +ACE_EXPLOSION_REFLECTION(34,170); +ACE_EXPLOSION_REFLECTION(34,180); +ACE_EXPLOSION_REFLECTION(34,190); +ACE_EXPLOSION_REFLECTION(34,200); +ACE_EXPLOSION_REFLECTION(34,210); +ACE_EXPLOSION_REFLECTION(34,220); +ACE_EXPLOSION_REFLECTION(34,230); +ACE_EXPLOSION_REFLECTION(34,240); +ACE_EXPLOSION_REFLECTION(34,250); +ACE_EXPLOSION_REFLECTION(34,260); +ACE_EXPLOSION_REFLECTION(34,270); +ACE_EXPLOSION_REFLECTION(34,280); +ACE_EXPLOSION_REFLECTION(34,290); +ACE_EXPLOSION_REFLECTION(34,300); +ACE_EXPLOSION_REFLECTION(34,310); +ACE_EXPLOSION_REFLECTION(34,320); +ACE_EXPLOSION_REFLECTION(34,330); +ACE_EXPLOSION_REFLECTION(34,340); +ACE_EXPLOSION_REFLECTION(34,350); +ACE_EXPLOSION_REFLECTION(34,360); +ACE_EXPLOSION_REFLECTION(34,370); +ACE_EXPLOSION_REFLECTION(34,380); +ACE_EXPLOSION_REFLECTION(34,390); +ACE_EXPLOSION_REFLECTION(34,400); +ACE_EXPLOSION_REFLECTION(34,410); +ACE_EXPLOSION_REFLECTION(34,420); +ACE_EXPLOSION_REFLECTION(34,430); +ACE_EXPLOSION_REFLECTION(34,440); +ACE_EXPLOSION_REFLECTION(34,450); +ACE_EXPLOSION_REFLECTION(34,460); +ACE_EXPLOSION_REFLECTION(34,470); +ACE_EXPLOSION_REFLECTION(34,480); +ACE_EXPLOSION_REFLECTION(34,490); +ACE_EXPLOSION_REFLECTION(34,500); +ACE_EXPLOSION_REFLECTION(36,10); +ACE_EXPLOSION_REFLECTION(36,20); +ACE_EXPLOSION_REFLECTION(36,30); +ACE_EXPLOSION_REFLECTION(36,40); +ACE_EXPLOSION_REFLECTION(36,50); +ACE_EXPLOSION_REFLECTION(36,60); +ACE_EXPLOSION_REFLECTION(36,70); +ACE_EXPLOSION_REFLECTION(36,80); +ACE_EXPLOSION_REFLECTION(36,90); +ACE_EXPLOSION_REFLECTION(36,100); +ACE_EXPLOSION_REFLECTION(36,110); +ACE_EXPLOSION_REFLECTION(36,120); +ACE_EXPLOSION_REFLECTION(36,130); +ACE_EXPLOSION_REFLECTION(36,140); +ACE_EXPLOSION_REFLECTION(36,150); +ACE_EXPLOSION_REFLECTION(36,160); +ACE_EXPLOSION_REFLECTION(36,170); +ACE_EXPLOSION_REFLECTION(36,180); +ACE_EXPLOSION_REFLECTION(36,190); +ACE_EXPLOSION_REFLECTION(36,200); +ACE_EXPLOSION_REFLECTION(36,210); +ACE_EXPLOSION_REFLECTION(36,220); +ACE_EXPLOSION_REFLECTION(36,230); +ACE_EXPLOSION_REFLECTION(36,240); +ACE_EXPLOSION_REFLECTION(36,250); +ACE_EXPLOSION_REFLECTION(36,260); +ACE_EXPLOSION_REFLECTION(36,270); +ACE_EXPLOSION_REFLECTION(36,280); +ACE_EXPLOSION_REFLECTION(36,290); +ACE_EXPLOSION_REFLECTION(36,300); +ACE_EXPLOSION_REFLECTION(36,310); +ACE_EXPLOSION_REFLECTION(36,320); +ACE_EXPLOSION_REFLECTION(36,330); +ACE_EXPLOSION_REFLECTION(36,340); +ACE_EXPLOSION_REFLECTION(36,350); +ACE_EXPLOSION_REFLECTION(36,360); +ACE_EXPLOSION_REFLECTION(36,370); +ACE_EXPLOSION_REFLECTION(36,380); +ACE_EXPLOSION_REFLECTION(36,390); +ACE_EXPLOSION_REFLECTION(36,400); +ACE_EXPLOSION_REFLECTION(36,410); +ACE_EXPLOSION_REFLECTION(36,420); +ACE_EXPLOSION_REFLECTION(36,430); +ACE_EXPLOSION_REFLECTION(36,440); +ACE_EXPLOSION_REFLECTION(36,450); +ACE_EXPLOSION_REFLECTION(36,460); +ACE_EXPLOSION_REFLECTION(36,470); +ACE_EXPLOSION_REFLECTION(36,480); +ACE_EXPLOSION_REFLECTION(36,490); +ACE_EXPLOSION_REFLECTION(36,500); +ACE_EXPLOSION_REFLECTION(38,10); +ACE_EXPLOSION_REFLECTION(38,20); +ACE_EXPLOSION_REFLECTION(38,30); +ACE_EXPLOSION_REFLECTION(38,40); +ACE_EXPLOSION_REFLECTION(38,50); +ACE_EXPLOSION_REFLECTION(38,60); +ACE_EXPLOSION_REFLECTION(38,70); +ACE_EXPLOSION_REFLECTION(38,80); +ACE_EXPLOSION_REFLECTION(38,90); +ACE_EXPLOSION_REFLECTION(38,100); +ACE_EXPLOSION_REFLECTION(38,110); +ACE_EXPLOSION_REFLECTION(38,120); +ACE_EXPLOSION_REFLECTION(38,130); +ACE_EXPLOSION_REFLECTION(38,140); +ACE_EXPLOSION_REFLECTION(38,150); +ACE_EXPLOSION_REFLECTION(38,160); +ACE_EXPLOSION_REFLECTION(38,170); +ACE_EXPLOSION_REFLECTION(38,180); +ACE_EXPLOSION_REFLECTION(38,190); +ACE_EXPLOSION_REFLECTION(38,200); +ACE_EXPLOSION_REFLECTION(38,210); +ACE_EXPLOSION_REFLECTION(38,220); +ACE_EXPLOSION_REFLECTION(38,230); +ACE_EXPLOSION_REFLECTION(38,240); +ACE_EXPLOSION_REFLECTION(38,250); +ACE_EXPLOSION_REFLECTION(38,260); +ACE_EXPLOSION_REFLECTION(38,270); +ACE_EXPLOSION_REFLECTION(38,280); +ACE_EXPLOSION_REFLECTION(38,290); +ACE_EXPLOSION_REFLECTION(38,300); +ACE_EXPLOSION_REFLECTION(38,310); +ACE_EXPLOSION_REFLECTION(38,320); +ACE_EXPLOSION_REFLECTION(38,330); +ACE_EXPLOSION_REFLECTION(38,340); +ACE_EXPLOSION_REFLECTION(38,350); +ACE_EXPLOSION_REFLECTION(38,360); +ACE_EXPLOSION_REFLECTION(38,370); +ACE_EXPLOSION_REFLECTION(38,380); +ACE_EXPLOSION_REFLECTION(38,390); +ACE_EXPLOSION_REFLECTION(38,400); +ACE_EXPLOSION_REFLECTION(38,410); +ACE_EXPLOSION_REFLECTION(38,420); +ACE_EXPLOSION_REFLECTION(38,430); +ACE_EXPLOSION_REFLECTION(38,440); +ACE_EXPLOSION_REFLECTION(38,450); +ACE_EXPLOSION_REFLECTION(38,460); +ACE_EXPLOSION_REFLECTION(38,470); +ACE_EXPLOSION_REFLECTION(38,480); +ACE_EXPLOSION_REFLECTION(38,490); +ACE_EXPLOSION_REFLECTION(38,500); +ACE_EXPLOSION_REFLECTION(40,10); +ACE_EXPLOSION_REFLECTION(40,20); +ACE_EXPLOSION_REFLECTION(40,30); +ACE_EXPLOSION_REFLECTION(40,40); +ACE_EXPLOSION_REFLECTION(40,50); +ACE_EXPLOSION_REFLECTION(40,60); +ACE_EXPLOSION_REFLECTION(40,70); +ACE_EXPLOSION_REFLECTION(40,80); +ACE_EXPLOSION_REFLECTION(40,90); +ACE_EXPLOSION_REFLECTION(40,100); +ACE_EXPLOSION_REFLECTION(40,110); +ACE_EXPLOSION_REFLECTION(40,120); +ACE_EXPLOSION_REFLECTION(40,130); +ACE_EXPLOSION_REFLECTION(40,140); +ACE_EXPLOSION_REFLECTION(40,150); +ACE_EXPLOSION_REFLECTION(40,160); +ACE_EXPLOSION_REFLECTION(40,170); +ACE_EXPLOSION_REFLECTION(40,180); +ACE_EXPLOSION_REFLECTION(40,190); +ACE_EXPLOSION_REFLECTION(40,200); +ACE_EXPLOSION_REFLECTION(40,210); +ACE_EXPLOSION_REFLECTION(40,220); +ACE_EXPLOSION_REFLECTION(40,230); +ACE_EXPLOSION_REFLECTION(40,240); +ACE_EXPLOSION_REFLECTION(40,250); +ACE_EXPLOSION_REFLECTION(40,260); +ACE_EXPLOSION_REFLECTION(40,270); +ACE_EXPLOSION_REFLECTION(40,280); +ACE_EXPLOSION_REFLECTION(40,290); +ACE_EXPLOSION_REFLECTION(40,300); +ACE_EXPLOSION_REFLECTION(40,310); +ACE_EXPLOSION_REFLECTION(40,320); +ACE_EXPLOSION_REFLECTION(40,330); +ACE_EXPLOSION_REFLECTION(40,340); +ACE_EXPLOSION_REFLECTION(40,350); +ACE_EXPLOSION_REFLECTION(40,360); +ACE_EXPLOSION_REFLECTION(40,370); +ACE_EXPLOSION_REFLECTION(40,380); +ACE_EXPLOSION_REFLECTION(40,390); +ACE_EXPLOSION_REFLECTION(40,400); +ACE_EXPLOSION_REFLECTION(40,410); +ACE_EXPLOSION_REFLECTION(40,420); +ACE_EXPLOSION_REFLECTION(40,430); +ACE_EXPLOSION_REFLECTION(40,440); +ACE_EXPLOSION_REFLECTION(40,450); +ACE_EXPLOSION_REFLECTION(40,460); +ACE_EXPLOSION_REFLECTION(40,470); +ACE_EXPLOSION_REFLECTION(40,480); +ACE_EXPLOSION_REFLECTION(40,490); +ACE_EXPLOSION_REFLECTION(40,500); +ACE_EXPLOSION_REFLECTION(42,10); +ACE_EXPLOSION_REFLECTION(42,20); +ACE_EXPLOSION_REFLECTION(42,30); +ACE_EXPLOSION_REFLECTION(42,40); +ACE_EXPLOSION_REFLECTION(42,50); +ACE_EXPLOSION_REFLECTION(42,60); +ACE_EXPLOSION_REFLECTION(42,70); +ACE_EXPLOSION_REFLECTION(42,80); +ACE_EXPLOSION_REFLECTION(42,90); +ACE_EXPLOSION_REFLECTION(42,100); +ACE_EXPLOSION_REFLECTION(42,110); +ACE_EXPLOSION_REFLECTION(42,120); +ACE_EXPLOSION_REFLECTION(42,130); +ACE_EXPLOSION_REFLECTION(42,140); +ACE_EXPLOSION_REFLECTION(42,150); +ACE_EXPLOSION_REFLECTION(42,160); +ACE_EXPLOSION_REFLECTION(42,170); +ACE_EXPLOSION_REFLECTION(42,180); +ACE_EXPLOSION_REFLECTION(42,190); +ACE_EXPLOSION_REFLECTION(42,200); +ACE_EXPLOSION_REFLECTION(42,210); +ACE_EXPLOSION_REFLECTION(42,220); +ACE_EXPLOSION_REFLECTION(42,230); +ACE_EXPLOSION_REFLECTION(42,240); +ACE_EXPLOSION_REFLECTION(42,250); +ACE_EXPLOSION_REFLECTION(42,260); +ACE_EXPLOSION_REFLECTION(42,270); +ACE_EXPLOSION_REFLECTION(42,280); +ACE_EXPLOSION_REFLECTION(42,290); +ACE_EXPLOSION_REFLECTION(42,300); +ACE_EXPLOSION_REFLECTION(42,310); +ACE_EXPLOSION_REFLECTION(42,320); +ACE_EXPLOSION_REFLECTION(42,330); +ACE_EXPLOSION_REFLECTION(42,340); +ACE_EXPLOSION_REFLECTION(42,350); +ACE_EXPLOSION_REFLECTION(42,360); +ACE_EXPLOSION_REFLECTION(42,370); +ACE_EXPLOSION_REFLECTION(42,380); +ACE_EXPLOSION_REFLECTION(42,390); +ACE_EXPLOSION_REFLECTION(42,400); +ACE_EXPLOSION_REFLECTION(42,410); +ACE_EXPLOSION_REFLECTION(42,420); +ACE_EXPLOSION_REFLECTION(42,430); +ACE_EXPLOSION_REFLECTION(42,440); +ACE_EXPLOSION_REFLECTION(42,450); +ACE_EXPLOSION_REFLECTION(42,460); +ACE_EXPLOSION_REFLECTION(42,470); +ACE_EXPLOSION_REFLECTION(42,480); +ACE_EXPLOSION_REFLECTION(42,490); +ACE_EXPLOSION_REFLECTION(42,500); +ACE_EXPLOSION_REFLECTION(44,10); +ACE_EXPLOSION_REFLECTION(44,20); +ACE_EXPLOSION_REFLECTION(44,30); +ACE_EXPLOSION_REFLECTION(44,40); +ACE_EXPLOSION_REFLECTION(44,50); +ACE_EXPLOSION_REFLECTION(44,60); +ACE_EXPLOSION_REFLECTION(44,70); +ACE_EXPLOSION_REFLECTION(44,80); +ACE_EXPLOSION_REFLECTION(44,90); +ACE_EXPLOSION_REFLECTION(44,100); +ACE_EXPLOSION_REFLECTION(44,110); +ACE_EXPLOSION_REFLECTION(44,120); +ACE_EXPLOSION_REFLECTION(44,130); +ACE_EXPLOSION_REFLECTION(44,140); +ACE_EXPLOSION_REFLECTION(44,150); +ACE_EXPLOSION_REFLECTION(44,160); +ACE_EXPLOSION_REFLECTION(44,170); +ACE_EXPLOSION_REFLECTION(44,180); +ACE_EXPLOSION_REFLECTION(44,190); +ACE_EXPLOSION_REFLECTION(44,200); +ACE_EXPLOSION_REFLECTION(44,210); +ACE_EXPLOSION_REFLECTION(44,220); +ACE_EXPLOSION_REFLECTION(44,230); +ACE_EXPLOSION_REFLECTION(44,240); +ACE_EXPLOSION_REFLECTION(44,250); +ACE_EXPLOSION_REFLECTION(44,260); +ACE_EXPLOSION_REFLECTION(44,270); +ACE_EXPLOSION_REFLECTION(44,280); +ACE_EXPLOSION_REFLECTION(44,290); +ACE_EXPLOSION_REFLECTION(44,300); +ACE_EXPLOSION_REFLECTION(44,310); +ACE_EXPLOSION_REFLECTION(44,320); +ACE_EXPLOSION_REFLECTION(44,330); +ACE_EXPLOSION_REFLECTION(44,340); +ACE_EXPLOSION_REFLECTION(44,350); +ACE_EXPLOSION_REFLECTION(44,360); +ACE_EXPLOSION_REFLECTION(44,370); +ACE_EXPLOSION_REFLECTION(44,380); +ACE_EXPLOSION_REFLECTION(44,390); +ACE_EXPLOSION_REFLECTION(44,400); +ACE_EXPLOSION_REFLECTION(44,410); +ACE_EXPLOSION_REFLECTION(44,420); +ACE_EXPLOSION_REFLECTION(44,430); +ACE_EXPLOSION_REFLECTION(44,440); +ACE_EXPLOSION_REFLECTION(44,450); +ACE_EXPLOSION_REFLECTION(44,460); +ACE_EXPLOSION_REFLECTION(44,470); +ACE_EXPLOSION_REFLECTION(44,480); +ACE_EXPLOSION_REFLECTION(44,490); +ACE_EXPLOSION_REFLECTION(44,500); +ACE_EXPLOSION_REFLECTION(46,10); +ACE_EXPLOSION_REFLECTION(46,20); +ACE_EXPLOSION_REFLECTION(46,30); +ACE_EXPLOSION_REFLECTION(46,40); +ACE_EXPLOSION_REFLECTION(46,50); +ACE_EXPLOSION_REFLECTION(46,60); +ACE_EXPLOSION_REFLECTION(46,70); +ACE_EXPLOSION_REFLECTION(46,80); +ACE_EXPLOSION_REFLECTION(46,90); +ACE_EXPLOSION_REFLECTION(46,100); +ACE_EXPLOSION_REFLECTION(46,110); +ACE_EXPLOSION_REFLECTION(46,120); +ACE_EXPLOSION_REFLECTION(46,130); +ACE_EXPLOSION_REFLECTION(46,140); +ACE_EXPLOSION_REFLECTION(46,150); +ACE_EXPLOSION_REFLECTION(46,160); +ACE_EXPLOSION_REFLECTION(46,170); +ACE_EXPLOSION_REFLECTION(46,180); +ACE_EXPLOSION_REFLECTION(46,190); +ACE_EXPLOSION_REFLECTION(46,200); +ACE_EXPLOSION_REFLECTION(46,210); +ACE_EXPLOSION_REFLECTION(46,220); +ACE_EXPLOSION_REFLECTION(46,230); +ACE_EXPLOSION_REFLECTION(46,240); +ACE_EXPLOSION_REFLECTION(46,250); +ACE_EXPLOSION_REFLECTION(46,260); +ACE_EXPLOSION_REFLECTION(46,270); +ACE_EXPLOSION_REFLECTION(46,280); +ACE_EXPLOSION_REFLECTION(46,290); +ACE_EXPLOSION_REFLECTION(46,300); +ACE_EXPLOSION_REFLECTION(46,310); +ACE_EXPLOSION_REFLECTION(46,320); +ACE_EXPLOSION_REFLECTION(46,330); +ACE_EXPLOSION_REFLECTION(46,340); +ACE_EXPLOSION_REFLECTION(46,350); +ACE_EXPLOSION_REFLECTION(46,360); +ACE_EXPLOSION_REFLECTION(46,370); +ACE_EXPLOSION_REFLECTION(46,380); +ACE_EXPLOSION_REFLECTION(46,390); +ACE_EXPLOSION_REFLECTION(46,400); +ACE_EXPLOSION_REFLECTION(46,410); +ACE_EXPLOSION_REFLECTION(46,420); +ACE_EXPLOSION_REFLECTION(46,430); +ACE_EXPLOSION_REFLECTION(46,440); +ACE_EXPLOSION_REFLECTION(46,450); +ACE_EXPLOSION_REFLECTION(46,460); +ACE_EXPLOSION_REFLECTION(46,470); +ACE_EXPLOSION_REFLECTION(46,480); +ACE_EXPLOSION_REFLECTION(46,490); +ACE_EXPLOSION_REFLECTION(46,500); +ACE_EXPLOSION_REFLECTION(48,10); +ACE_EXPLOSION_REFLECTION(48,20); +ACE_EXPLOSION_REFLECTION(48,30); +ACE_EXPLOSION_REFLECTION(48,40); +ACE_EXPLOSION_REFLECTION(48,50); +ACE_EXPLOSION_REFLECTION(48,60); +ACE_EXPLOSION_REFLECTION(48,70); +ACE_EXPLOSION_REFLECTION(48,80); +ACE_EXPLOSION_REFLECTION(48,90); +ACE_EXPLOSION_REFLECTION(48,100); +ACE_EXPLOSION_REFLECTION(48,110); +ACE_EXPLOSION_REFLECTION(48,120); +ACE_EXPLOSION_REFLECTION(48,130); +ACE_EXPLOSION_REFLECTION(48,140); +ACE_EXPLOSION_REFLECTION(48,150); +ACE_EXPLOSION_REFLECTION(48,160); +ACE_EXPLOSION_REFLECTION(48,170); +ACE_EXPLOSION_REFLECTION(48,180); +ACE_EXPLOSION_REFLECTION(48,190); +ACE_EXPLOSION_REFLECTION(48,200); +ACE_EXPLOSION_REFLECTION(48,210); +ACE_EXPLOSION_REFLECTION(48,220); +ACE_EXPLOSION_REFLECTION(48,230); +ACE_EXPLOSION_REFLECTION(48,240); +ACE_EXPLOSION_REFLECTION(48,250); +ACE_EXPLOSION_REFLECTION(48,260); +ACE_EXPLOSION_REFLECTION(48,270); +ACE_EXPLOSION_REFLECTION(48,280); +ACE_EXPLOSION_REFLECTION(48,290); +ACE_EXPLOSION_REFLECTION(48,300); +ACE_EXPLOSION_REFLECTION(48,310); +ACE_EXPLOSION_REFLECTION(48,320); +ACE_EXPLOSION_REFLECTION(48,330); +ACE_EXPLOSION_REFLECTION(48,340); +ACE_EXPLOSION_REFLECTION(48,350); +ACE_EXPLOSION_REFLECTION(48,360); +ACE_EXPLOSION_REFLECTION(48,370); +ACE_EXPLOSION_REFLECTION(48,380); +ACE_EXPLOSION_REFLECTION(48,390); +ACE_EXPLOSION_REFLECTION(48,400); +ACE_EXPLOSION_REFLECTION(48,410); +ACE_EXPLOSION_REFLECTION(48,420); +ACE_EXPLOSION_REFLECTION(48,430); +ACE_EXPLOSION_REFLECTION(48,440); +ACE_EXPLOSION_REFLECTION(48,450); +ACE_EXPLOSION_REFLECTION(48,460); +ACE_EXPLOSION_REFLECTION(48,470); +ACE_EXPLOSION_REFLECTION(48,480); +ACE_EXPLOSION_REFLECTION(48,490); +ACE_EXPLOSION_REFLECTION(48,500); +ACE_EXPLOSION_REFLECTION(50,10); +ACE_EXPLOSION_REFLECTION(50,20); +ACE_EXPLOSION_REFLECTION(50,30); +ACE_EXPLOSION_REFLECTION(50,40); +ACE_EXPLOSION_REFLECTION(50,50); +ACE_EXPLOSION_REFLECTION(50,60); +ACE_EXPLOSION_REFLECTION(50,70); +ACE_EXPLOSION_REFLECTION(50,80); +ACE_EXPLOSION_REFLECTION(50,90); +ACE_EXPLOSION_REFLECTION(50,100); +ACE_EXPLOSION_REFLECTION(50,110); +ACE_EXPLOSION_REFLECTION(50,120); +ACE_EXPLOSION_REFLECTION(50,130); +ACE_EXPLOSION_REFLECTION(50,140); +ACE_EXPLOSION_REFLECTION(50,150); +ACE_EXPLOSION_REFLECTION(50,160); +ACE_EXPLOSION_REFLECTION(50,170); +ACE_EXPLOSION_REFLECTION(50,180); +ACE_EXPLOSION_REFLECTION(50,190); +ACE_EXPLOSION_REFLECTION(50,200); +ACE_EXPLOSION_REFLECTION(50,210); +ACE_EXPLOSION_REFLECTION(50,220); +ACE_EXPLOSION_REFLECTION(50,230); +ACE_EXPLOSION_REFLECTION(50,240); +ACE_EXPLOSION_REFLECTION(50,250); +ACE_EXPLOSION_REFLECTION(50,260); +ACE_EXPLOSION_REFLECTION(50,270); +ACE_EXPLOSION_REFLECTION(50,280); +ACE_EXPLOSION_REFLECTION(50,290); +ACE_EXPLOSION_REFLECTION(50,300); +ACE_EXPLOSION_REFLECTION(50,310); +ACE_EXPLOSION_REFLECTION(50,320); +ACE_EXPLOSION_REFLECTION(50,330); +ACE_EXPLOSION_REFLECTION(50,340); +ACE_EXPLOSION_REFLECTION(50,350); +ACE_EXPLOSION_REFLECTION(50,360); +ACE_EXPLOSION_REFLECTION(50,370); +ACE_EXPLOSION_REFLECTION(50,380); +ACE_EXPLOSION_REFLECTION(50,390); +ACE_EXPLOSION_REFLECTION(50,400); +ACE_EXPLOSION_REFLECTION(50,410); +ACE_EXPLOSION_REFLECTION(50,420); +ACE_EXPLOSION_REFLECTION(50,430); +ACE_EXPLOSION_REFLECTION(50,440); +ACE_EXPLOSION_REFLECTION(50,450); +ACE_EXPLOSION_REFLECTION(50,460); +ACE_EXPLOSION_REFLECTION(50,470); +ACE_EXPLOSION_REFLECTION(50,480); +ACE_EXPLOSION_REFLECTION(50,490); +ACE_EXPLOSION_REFLECTION(50,500); +ACE_EXPLOSION_REFLECTION(52,10); +ACE_EXPLOSION_REFLECTION(52,20); +ACE_EXPLOSION_REFLECTION(52,30); +ACE_EXPLOSION_REFLECTION(52,40); +ACE_EXPLOSION_REFLECTION(52,50); +ACE_EXPLOSION_REFLECTION(52,60); +ACE_EXPLOSION_REFLECTION(52,70); +ACE_EXPLOSION_REFLECTION(52,80); +ACE_EXPLOSION_REFLECTION(52,90); +ACE_EXPLOSION_REFLECTION(52,100); +ACE_EXPLOSION_REFLECTION(52,110); +ACE_EXPLOSION_REFLECTION(52,120); +ACE_EXPLOSION_REFLECTION(52,130); +ACE_EXPLOSION_REFLECTION(52,140); +ACE_EXPLOSION_REFLECTION(52,150); +ACE_EXPLOSION_REFLECTION(52,160); +ACE_EXPLOSION_REFLECTION(52,170); +ACE_EXPLOSION_REFLECTION(52,180); +ACE_EXPLOSION_REFLECTION(52,190); +ACE_EXPLOSION_REFLECTION(52,200); +ACE_EXPLOSION_REFLECTION(52,210); +ACE_EXPLOSION_REFLECTION(52,220); +ACE_EXPLOSION_REFLECTION(52,230); +ACE_EXPLOSION_REFLECTION(52,240); +ACE_EXPLOSION_REFLECTION(52,250); +ACE_EXPLOSION_REFLECTION(52,260); +ACE_EXPLOSION_REFLECTION(52,270); +ACE_EXPLOSION_REFLECTION(52,280); +ACE_EXPLOSION_REFLECTION(52,290); +ACE_EXPLOSION_REFLECTION(52,300); +ACE_EXPLOSION_REFLECTION(52,310); +ACE_EXPLOSION_REFLECTION(52,320); +ACE_EXPLOSION_REFLECTION(52,330); +ACE_EXPLOSION_REFLECTION(52,340); +ACE_EXPLOSION_REFLECTION(52,350); +ACE_EXPLOSION_REFLECTION(52,360); +ACE_EXPLOSION_REFLECTION(52,370); +ACE_EXPLOSION_REFLECTION(52,380); +ACE_EXPLOSION_REFLECTION(52,390); +ACE_EXPLOSION_REFLECTION(52,400); +ACE_EXPLOSION_REFLECTION(52,410); +ACE_EXPLOSION_REFLECTION(52,420); +ACE_EXPLOSION_REFLECTION(52,430); +ACE_EXPLOSION_REFLECTION(52,440); +ACE_EXPLOSION_REFLECTION(52,450); +ACE_EXPLOSION_REFLECTION(52,460); +ACE_EXPLOSION_REFLECTION(52,470); +ACE_EXPLOSION_REFLECTION(52,480); +ACE_EXPLOSION_REFLECTION(52,490); +ACE_EXPLOSION_REFLECTION(52,500); +ACE_EXPLOSION_REFLECTION(54,10); +ACE_EXPLOSION_REFLECTION(54,20); +ACE_EXPLOSION_REFLECTION(54,30); +ACE_EXPLOSION_REFLECTION(54,40); +ACE_EXPLOSION_REFLECTION(54,50); +ACE_EXPLOSION_REFLECTION(54,60); +ACE_EXPLOSION_REFLECTION(54,70); +ACE_EXPLOSION_REFLECTION(54,80); +ACE_EXPLOSION_REFLECTION(54,90); +ACE_EXPLOSION_REFLECTION(54,100); +ACE_EXPLOSION_REFLECTION(54,110); +ACE_EXPLOSION_REFLECTION(54,120); +ACE_EXPLOSION_REFLECTION(54,130); +ACE_EXPLOSION_REFLECTION(54,140); +ACE_EXPLOSION_REFLECTION(54,150); +ACE_EXPLOSION_REFLECTION(54,160); +ACE_EXPLOSION_REFLECTION(54,170); +ACE_EXPLOSION_REFLECTION(54,180); +ACE_EXPLOSION_REFLECTION(54,190); +ACE_EXPLOSION_REFLECTION(54,200); +ACE_EXPLOSION_REFLECTION(54,210); +ACE_EXPLOSION_REFLECTION(54,220); +ACE_EXPLOSION_REFLECTION(54,230); +ACE_EXPLOSION_REFLECTION(54,240); +ACE_EXPLOSION_REFLECTION(54,250); +ACE_EXPLOSION_REFLECTION(54,260); +ACE_EXPLOSION_REFLECTION(54,270); +ACE_EXPLOSION_REFLECTION(54,280); +ACE_EXPLOSION_REFLECTION(54,290); +ACE_EXPLOSION_REFLECTION(54,300); +ACE_EXPLOSION_REFLECTION(54,310); +ACE_EXPLOSION_REFLECTION(54,320); +ACE_EXPLOSION_REFLECTION(54,330); +ACE_EXPLOSION_REFLECTION(54,340); +ACE_EXPLOSION_REFLECTION(54,350); +ACE_EXPLOSION_REFLECTION(54,360); +ACE_EXPLOSION_REFLECTION(54,370); +ACE_EXPLOSION_REFLECTION(54,380); +ACE_EXPLOSION_REFLECTION(54,390); +ACE_EXPLOSION_REFLECTION(54,400); +ACE_EXPLOSION_REFLECTION(54,410); +ACE_EXPLOSION_REFLECTION(54,420); +ACE_EXPLOSION_REFLECTION(54,430); +ACE_EXPLOSION_REFLECTION(54,440); +ACE_EXPLOSION_REFLECTION(54,450); +ACE_EXPLOSION_REFLECTION(54,460); +ACE_EXPLOSION_REFLECTION(54,470); +ACE_EXPLOSION_REFLECTION(54,480); +ACE_EXPLOSION_REFLECTION(54,490); +ACE_EXPLOSION_REFLECTION(54,500); +ACE_EXPLOSION_REFLECTION(56,10); +ACE_EXPLOSION_REFLECTION(56,20); +ACE_EXPLOSION_REFLECTION(56,30); +ACE_EXPLOSION_REFLECTION(56,40); +ACE_EXPLOSION_REFLECTION(56,50); +ACE_EXPLOSION_REFLECTION(56,60); +ACE_EXPLOSION_REFLECTION(56,70); +ACE_EXPLOSION_REFLECTION(56,80); +ACE_EXPLOSION_REFLECTION(56,90); +ACE_EXPLOSION_REFLECTION(56,100); +ACE_EXPLOSION_REFLECTION(56,110); +ACE_EXPLOSION_REFLECTION(56,120); +ACE_EXPLOSION_REFLECTION(56,130); +ACE_EXPLOSION_REFLECTION(56,140); +ACE_EXPLOSION_REFLECTION(56,150); +ACE_EXPLOSION_REFLECTION(56,160); +ACE_EXPLOSION_REFLECTION(56,170); +ACE_EXPLOSION_REFLECTION(56,180); +ACE_EXPLOSION_REFLECTION(56,190); +ACE_EXPLOSION_REFLECTION(56,200); +ACE_EXPLOSION_REFLECTION(56,210); +ACE_EXPLOSION_REFLECTION(56,220); +ACE_EXPLOSION_REFLECTION(56,230); +ACE_EXPLOSION_REFLECTION(56,240); +ACE_EXPLOSION_REFLECTION(56,250); +ACE_EXPLOSION_REFLECTION(56,260); +ACE_EXPLOSION_REFLECTION(56,270); +ACE_EXPLOSION_REFLECTION(56,280); +ACE_EXPLOSION_REFLECTION(56,290); +ACE_EXPLOSION_REFLECTION(56,300); +ACE_EXPLOSION_REFLECTION(56,310); +ACE_EXPLOSION_REFLECTION(56,320); +ACE_EXPLOSION_REFLECTION(56,330); +ACE_EXPLOSION_REFLECTION(56,340); +ACE_EXPLOSION_REFLECTION(56,350); +ACE_EXPLOSION_REFLECTION(56,360); +ACE_EXPLOSION_REFLECTION(56,370); +ACE_EXPLOSION_REFLECTION(56,380); +ACE_EXPLOSION_REFLECTION(56,390); +ACE_EXPLOSION_REFLECTION(56,400); +ACE_EXPLOSION_REFLECTION(56,410); +ACE_EXPLOSION_REFLECTION(56,420); +ACE_EXPLOSION_REFLECTION(56,430); +ACE_EXPLOSION_REFLECTION(56,440); +ACE_EXPLOSION_REFLECTION(56,450); +ACE_EXPLOSION_REFLECTION(56,460); +ACE_EXPLOSION_REFLECTION(56,470); +ACE_EXPLOSION_REFLECTION(56,480); +ACE_EXPLOSION_REFLECTION(56,490); +ACE_EXPLOSION_REFLECTION(56,500); +ACE_EXPLOSION_REFLECTION(58,10); +ACE_EXPLOSION_REFLECTION(58,20); +ACE_EXPLOSION_REFLECTION(58,30); +ACE_EXPLOSION_REFLECTION(58,40); +ACE_EXPLOSION_REFLECTION(58,50); +ACE_EXPLOSION_REFLECTION(58,60); +ACE_EXPLOSION_REFLECTION(58,70); +ACE_EXPLOSION_REFLECTION(58,80); +ACE_EXPLOSION_REFLECTION(58,90); +ACE_EXPLOSION_REFLECTION(58,100); +ACE_EXPLOSION_REFLECTION(58,110); +ACE_EXPLOSION_REFLECTION(58,120); +ACE_EXPLOSION_REFLECTION(58,130); +ACE_EXPLOSION_REFLECTION(58,140); +ACE_EXPLOSION_REFLECTION(58,150); +ACE_EXPLOSION_REFLECTION(58,160); +ACE_EXPLOSION_REFLECTION(58,170); +ACE_EXPLOSION_REFLECTION(58,180); +ACE_EXPLOSION_REFLECTION(58,190); +ACE_EXPLOSION_REFLECTION(58,200); +ACE_EXPLOSION_REFLECTION(58,210); +ACE_EXPLOSION_REFLECTION(58,220); +ACE_EXPLOSION_REFLECTION(58,230); +ACE_EXPLOSION_REFLECTION(58,240); +ACE_EXPLOSION_REFLECTION(58,250); +ACE_EXPLOSION_REFLECTION(58,260); +ACE_EXPLOSION_REFLECTION(58,270); +ACE_EXPLOSION_REFLECTION(58,280); +ACE_EXPLOSION_REFLECTION(58,290); +ACE_EXPLOSION_REFLECTION(58,300); +ACE_EXPLOSION_REFLECTION(58,310); +ACE_EXPLOSION_REFLECTION(58,320); +ACE_EXPLOSION_REFLECTION(58,330); +ACE_EXPLOSION_REFLECTION(58,340); +ACE_EXPLOSION_REFLECTION(58,350); +ACE_EXPLOSION_REFLECTION(58,360); +ACE_EXPLOSION_REFLECTION(58,370); +ACE_EXPLOSION_REFLECTION(58,380); +ACE_EXPLOSION_REFLECTION(58,390); +ACE_EXPLOSION_REFLECTION(58,400); +ACE_EXPLOSION_REFLECTION(58,410); +ACE_EXPLOSION_REFLECTION(58,420); +ACE_EXPLOSION_REFLECTION(58,430); +ACE_EXPLOSION_REFLECTION(58,440); +ACE_EXPLOSION_REFLECTION(58,450); +ACE_EXPLOSION_REFLECTION(58,460); +ACE_EXPLOSION_REFLECTION(58,470); +ACE_EXPLOSION_REFLECTION(58,480); +ACE_EXPLOSION_REFLECTION(58,490); +ACE_EXPLOSION_REFLECTION(58,500); +ACE_EXPLOSION_REFLECTION(60,10); +ACE_EXPLOSION_REFLECTION(60,20); +ACE_EXPLOSION_REFLECTION(60,30); +ACE_EXPLOSION_REFLECTION(60,40); +ACE_EXPLOSION_REFLECTION(60,50); +ACE_EXPLOSION_REFLECTION(60,60); +ACE_EXPLOSION_REFLECTION(60,70); +ACE_EXPLOSION_REFLECTION(60,80); +ACE_EXPLOSION_REFLECTION(60,90); +ACE_EXPLOSION_REFLECTION(60,100); +ACE_EXPLOSION_REFLECTION(60,110); +ACE_EXPLOSION_REFLECTION(60,120); +ACE_EXPLOSION_REFLECTION(60,130); +ACE_EXPLOSION_REFLECTION(60,140); +ACE_EXPLOSION_REFLECTION(60,150); +ACE_EXPLOSION_REFLECTION(60,160); +ACE_EXPLOSION_REFLECTION(60,170); +ACE_EXPLOSION_REFLECTION(60,180); +ACE_EXPLOSION_REFLECTION(60,190); +ACE_EXPLOSION_REFLECTION(60,200); +ACE_EXPLOSION_REFLECTION(60,210); +ACE_EXPLOSION_REFLECTION(60,220); +ACE_EXPLOSION_REFLECTION(60,230); +ACE_EXPLOSION_REFLECTION(60,240); +ACE_EXPLOSION_REFLECTION(60,250); +ACE_EXPLOSION_REFLECTION(60,260); +ACE_EXPLOSION_REFLECTION(60,270); +ACE_EXPLOSION_REFLECTION(60,280); +ACE_EXPLOSION_REFLECTION(60,290); +ACE_EXPLOSION_REFLECTION(60,300); +ACE_EXPLOSION_REFLECTION(60,310); +ACE_EXPLOSION_REFLECTION(60,320); +ACE_EXPLOSION_REFLECTION(60,330); +ACE_EXPLOSION_REFLECTION(60,340); +ACE_EXPLOSION_REFLECTION(60,350); +ACE_EXPLOSION_REFLECTION(60,360); +ACE_EXPLOSION_REFLECTION(60,370); +ACE_EXPLOSION_REFLECTION(60,380); +ACE_EXPLOSION_REFLECTION(60,390); +ACE_EXPLOSION_REFLECTION(60,400); +ACE_EXPLOSION_REFLECTION(60,410); +ACE_EXPLOSION_REFLECTION(60,420); +ACE_EXPLOSION_REFLECTION(60,430); +ACE_EXPLOSION_REFLECTION(60,440); +ACE_EXPLOSION_REFLECTION(60,450); +ACE_EXPLOSION_REFLECTION(60,460); +ACE_EXPLOSION_REFLECTION(60,470); +ACE_EXPLOSION_REFLECTION(60,480); +ACE_EXPLOSION_REFLECTION(60,490); +ACE_EXPLOSION_REFLECTION(60,500); +ACE_EXPLOSION_REFLECTION(62,10); +ACE_EXPLOSION_REFLECTION(62,20); +ACE_EXPLOSION_REFLECTION(62,30); +ACE_EXPLOSION_REFLECTION(62,40); +ACE_EXPLOSION_REFLECTION(62,50); +ACE_EXPLOSION_REFLECTION(62,60); +ACE_EXPLOSION_REFLECTION(62,70); +ACE_EXPLOSION_REFLECTION(62,80); +ACE_EXPLOSION_REFLECTION(62,90); +ACE_EXPLOSION_REFLECTION(62,100); +ACE_EXPLOSION_REFLECTION(62,110); +ACE_EXPLOSION_REFLECTION(62,120); +ACE_EXPLOSION_REFLECTION(62,130); +ACE_EXPLOSION_REFLECTION(62,140); +ACE_EXPLOSION_REFLECTION(62,150); +ACE_EXPLOSION_REFLECTION(62,160); +ACE_EXPLOSION_REFLECTION(62,170); +ACE_EXPLOSION_REFLECTION(62,180); +ACE_EXPLOSION_REFLECTION(62,190); +ACE_EXPLOSION_REFLECTION(62,200); +ACE_EXPLOSION_REFLECTION(62,210); +ACE_EXPLOSION_REFLECTION(62,220); +ACE_EXPLOSION_REFLECTION(62,230); +ACE_EXPLOSION_REFLECTION(62,240); +ACE_EXPLOSION_REFLECTION(62,250); +ACE_EXPLOSION_REFLECTION(62,260); +ACE_EXPLOSION_REFLECTION(62,270); +ACE_EXPLOSION_REFLECTION(62,280); +ACE_EXPLOSION_REFLECTION(62,290); +ACE_EXPLOSION_REFLECTION(62,300); +ACE_EXPLOSION_REFLECTION(62,310); +ACE_EXPLOSION_REFLECTION(62,320); +ACE_EXPLOSION_REFLECTION(62,330); +ACE_EXPLOSION_REFLECTION(62,340); +ACE_EXPLOSION_REFLECTION(62,350); +ACE_EXPLOSION_REFLECTION(62,360); +ACE_EXPLOSION_REFLECTION(62,370); +ACE_EXPLOSION_REFLECTION(62,380); +ACE_EXPLOSION_REFLECTION(62,390); +ACE_EXPLOSION_REFLECTION(62,400); +ACE_EXPLOSION_REFLECTION(62,410); +ACE_EXPLOSION_REFLECTION(62,420); +ACE_EXPLOSION_REFLECTION(62,430); +ACE_EXPLOSION_REFLECTION(62,440); +ACE_EXPLOSION_REFLECTION(62,450); +ACE_EXPLOSION_REFLECTION(62,460); +ACE_EXPLOSION_REFLECTION(62,470); +ACE_EXPLOSION_REFLECTION(62,480); +ACE_EXPLOSION_REFLECTION(62,490); +ACE_EXPLOSION_REFLECTION(62,500); +ACE_EXPLOSION_REFLECTION(64,10); +ACE_EXPLOSION_REFLECTION(64,20); +ACE_EXPLOSION_REFLECTION(64,30); +ACE_EXPLOSION_REFLECTION(64,40); +ACE_EXPLOSION_REFLECTION(64,50); +ACE_EXPLOSION_REFLECTION(64,60); +ACE_EXPLOSION_REFLECTION(64,70); +ACE_EXPLOSION_REFLECTION(64,80); +ACE_EXPLOSION_REFLECTION(64,90); +ACE_EXPLOSION_REFLECTION(64,100); +ACE_EXPLOSION_REFLECTION(64,110); +ACE_EXPLOSION_REFLECTION(64,120); +ACE_EXPLOSION_REFLECTION(64,130); +ACE_EXPLOSION_REFLECTION(64,140); +ACE_EXPLOSION_REFLECTION(64,150); +ACE_EXPLOSION_REFLECTION(64,160); +ACE_EXPLOSION_REFLECTION(64,170); +ACE_EXPLOSION_REFLECTION(64,180); +ACE_EXPLOSION_REFLECTION(64,190); +ACE_EXPLOSION_REFLECTION(64,200); +ACE_EXPLOSION_REFLECTION(64,210); +ACE_EXPLOSION_REFLECTION(64,220); +ACE_EXPLOSION_REFLECTION(64,230); +ACE_EXPLOSION_REFLECTION(64,240); +ACE_EXPLOSION_REFLECTION(64,250); +ACE_EXPLOSION_REFLECTION(64,260); +ACE_EXPLOSION_REFLECTION(64,270); +ACE_EXPLOSION_REFLECTION(64,280); +ACE_EXPLOSION_REFLECTION(64,290); +ACE_EXPLOSION_REFLECTION(64,300); +ACE_EXPLOSION_REFLECTION(64,310); +ACE_EXPLOSION_REFLECTION(64,320); +ACE_EXPLOSION_REFLECTION(64,330); +ACE_EXPLOSION_REFLECTION(64,340); +ACE_EXPLOSION_REFLECTION(64,350); +ACE_EXPLOSION_REFLECTION(64,360); +ACE_EXPLOSION_REFLECTION(64,370); +ACE_EXPLOSION_REFLECTION(64,380); +ACE_EXPLOSION_REFLECTION(64,390); +ACE_EXPLOSION_REFLECTION(64,400); +ACE_EXPLOSION_REFLECTION(64,410); +ACE_EXPLOSION_REFLECTION(64,420); +ACE_EXPLOSION_REFLECTION(64,430); +ACE_EXPLOSION_REFLECTION(64,440); +ACE_EXPLOSION_REFLECTION(64,450); +ACE_EXPLOSION_REFLECTION(64,460); +ACE_EXPLOSION_REFLECTION(64,470); +ACE_EXPLOSION_REFLECTION(64,480); +ACE_EXPLOSION_REFLECTION(64,490); +ACE_EXPLOSION_REFLECTION(64,500); +ACE_EXPLOSION_REFLECTION(66,10); +ACE_EXPLOSION_REFLECTION(66,20); +ACE_EXPLOSION_REFLECTION(66,30); +ACE_EXPLOSION_REFLECTION(66,40); +ACE_EXPLOSION_REFLECTION(66,50); +ACE_EXPLOSION_REFLECTION(66,60); +ACE_EXPLOSION_REFLECTION(66,70); +ACE_EXPLOSION_REFLECTION(66,80); +ACE_EXPLOSION_REFLECTION(66,90); +ACE_EXPLOSION_REFLECTION(66,100); +ACE_EXPLOSION_REFLECTION(66,110); +ACE_EXPLOSION_REFLECTION(66,120); +ACE_EXPLOSION_REFLECTION(66,130); +ACE_EXPLOSION_REFLECTION(66,140); +ACE_EXPLOSION_REFLECTION(66,150); +ACE_EXPLOSION_REFLECTION(66,160); +ACE_EXPLOSION_REFLECTION(66,170); +ACE_EXPLOSION_REFLECTION(66,180); +ACE_EXPLOSION_REFLECTION(66,190); +ACE_EXPLOSION_REFLECTION(66,200); +ACE_EXPLOSION_REFLECTION(66,210); +ACE_EXPLOSION_REFLECTION(66,220); +ACE_EXPLOSION_REFLECTION(66,230); +ACE_EXPLOSION_REFLECTION(66,240); +ACE_EXPLOSION_REFLECTION(66,250); +ACE_EXPLOSION_REFLECTION(66,260); +ACE_EXPLOSION_REFLECTION(66,270); +ACE_EXPLOSION_REFLECTION(66,280); +ACE_EXPLOSION_REFLECTION(66,290); +ACE_EXPLOSION_REFLECTION(66,300); +ACE_EXPLOSION_REFLECTION(66,310); +ACE_EXPLOSION_REFLECTION(66,320); +ACE_EXPLOSION_REFLECTION(66,330); +ACE_EXPLOSION_REFLECTION(66,340); +ACE_EXPLOSION_REFLECTION(66,350); +ACE_EXPLOSION_REFLECTION(66,360); +ACE_EXPLOSION_REFLECTION(66,370); +ACE_EXPLOSION_REFLECTION(66,380); +ACE_EXPLOSION_REFLECTION(66,390); +ACE_EXPLOSION_REFLECTION(66,400); +ACE_EXPLOSION_REFLECTION(66,410); +ACE_EXPLOSION_REFLECTION(66,420); +ACE_EXPLOSION_REFLECTION(66,430); +ACE_EXPLOSION_REFLECTION(66,440); +ACE_EXPLOSION_REFLECTION(66,450); +ACE_EXPLOSION_REFLECTION(66,460); +ACE_EXPLOSION_REFLECTION(66,470); +ACE_EXPLOSION_REFLECTION(66,480); +ACE_EXPLOSION_REFLECTION(66,490); +ACE_EXPLOSION_REFLECTION(66,500); +ACE_EXPLOSION_REFLECTION(68,10); +ACE_EXPLOSION_REFLECTION(68,20); +ACE_EXPLOSION_REFLECTION(68,30); +ACE_EXPLOSION_REFLECTION(68,40); +ACE_EXPLOSION_REFLECTION(68,50); +ACE_EXPLOSION_REFLECTION(68,60); +ACE_EXPLOSION_REFLECTION(68,70); +ACE_EXPLOSION_REFLECTION(68,80); +ACE_EXPLOSION_REFLECTION(68,90); +ACE_EXPLOSION_REFLECTION(68,100); +ACE_EXPLOSION_REFLECTION(68,110); +ACE_EXPLOSION_REFLECTION(68,120); +ACE_EXPLOSION_REFLECTION(68,130); +ACE_EXPLOSION_REFLECTION(68,140); +ACE_EXPLOSION_REFLECTION(68,150); +ACE_EXPLOSION_REFLECTION(68,160); +ACE_EXPLOSION_REFLECTION(68,170); +ACE_EXPLOSION_REFLECTION(68,180); +ACE_EXPLOSION_REFLECTION(68,190); +ACE_EXPLOSION_REFLECTION(68,200); +ACE_EXPLOSION_REFLECTION(68,210); +ACE_EXPLOSION_REFLECTION(68,220); +ACE_EXPLOSION_REFLECTION(68,230); +ACE_EXPLOSION_REFLECTION(68,240); +ACE_EXPLOSION_REFLECTION(68,250); +ACE_EXPLOSION_REFLECTION(68,260); +ACE_EXPLOSION_REFLECTION(68,270); +ACE_EXPLOSION_REFLECTION(68,280); +ACE_EXPLOSION_REFLECTION(68,290); +ACE_EXPLOSION_REFLECTION(68,300); +ACE_EXPLOSION_REFLECTION(68,310); +ACE_EXPLOSION_REFLECTION(68,320); +ACE_EXPLOSION_REFLECTION(68,330); +ACE_EXPLOSION_REFLECTION(68,340); +ACE_EXPLOSION_REFLECTION(68,350); +ACE_EXPLOSION_REFLECTION(68,360); +ACE_EXPLOSION_REFLECTION(68,370); +ACE_EXPLOSION_REFLECTION(68,380); +ACE_EXPLOSION_REFLECTION(68,390); +ACE_EXPLOSION_REFLECTION(68,400); +ACE_EXPLOSION_REFLECTION(68,410); +ACE_EXPLOSION_REFLECTION(68,420); +ACE_EXPLOSION_REFLECTION(68,430); +ACE_EXPLOSION_REFLECTION(68,440); +ACE_EXPLOSION_REFLECTION(68,450); +ACE_EXPLOSION_REFLECTION(68,460); +ACE_EXPLOSION_REFLECTION(68,470); +ACE_EXPLOSION_REFLECTION(68,480); +ACE_EXPLOSION_REFLECTION(68,490); +ACE_EXPLOSION_REFLECTION(68,500); +ACE_EXPLOSION_REFLECTION(70,10); +ACE_EXPLOSION_REFLECTION(70,20); +ACE_EXPLOSION_REFLECTION(70,30); +ACE_EXPLOSION_REFLECTION(70,40); +ACE_EXPLOSION_REFLECTION(70,50); +ACE_EXPLOSION_REFLECTION(70,60); +ACE_EXPLOSION_REFLECTION(70,70); +ACE_EXPLOSION_REFLECTION(70,80); +ACE_EXPLOSION_REFLECTION(70,90); +ACE_EXPLOSION_REFLECTION(70,100); +ACE_EXPLOSION_REFLECTION(70,110); +ACE_EXPLOSION_REFLECTION(70,120); +ACE_EXPLOSION_REFLECTION(70,130); +ACE_EXPLOSION_REFLECTION(70,140); +ACE_EXPLOSION_REFLECTION(70,150); +ACE_EXPLOSION_REFLECTION(70,160); +ACE_EXPLOSION_REFLECTION(70,170); +ACE_EXPLOSION_REFLECTION(70,180); +ACE_EXPLOSION_REFLECTION(70,190); +ACE_EXPLOSION_REFLECTION(70,200); +ACE_EXPLOSION_REFLECTION(70,210); +ACE_EXPLOSION_REFLECTION(70,220); +ACE_EXPLOSION_REFLECTION(70,230); +ACE_EXPLOSION_REFLECTION(70,240); +ACE_EXPLOSION_REFLECTION(70,250); +ACE_EXPLOSION_REFLECTION(70,260); +ACE_EXPLOSION_REFLECTION(70,270); +ACE_EXPLOSION_REFLECTION(70,280); +ACE_EXPLOSION_REFLECTION(70,290); +ACE_EXPLOSION_REFLECTION(70,300); +ACE_EXPLOSION_REFLECTION(70,310); +ACE_EXPLOSION_REFLECTION(70,320); +ACE_EXPLOSION_REFLECTION(70,330); +ACE_EXPLOSION_REFLECTION(70,340); +ACE_EXPLOSION_REFLECTION(70,350); +ACE_EXPLOSION_REFLECTION(70,360); +ACE_EXPLOSION_REFLECTION(70,370); +ACE_EXPLOSION_REFLECTION(70,380); +ACE_EXPLOSION_REFLECTION(70,390); +ACE_EXPLOSION_REFLECTION(70,400); +ACE_EXPLOSION_REFLECTION(70,410); +ACE_EXPLOSION_REFLECTION(70,420); +ACE_EXPLOSION_REFLECTION(70,430); +ACE_EXPLOSION_REFLECTION(70,440); +ACE_EXPLOSION_REFLECTION(70,450); +ACE_EXPLOSION_REFLECTION(70,460); +ACE_EXPLOSION_REFLECTION(70,470); +ACE_EXPLOSION_REFLECTION(70,480); +ACE_EXPLOSION_REFLECTION(70,490); +ACE_EXPLOSION_REFLECTION(70,500); +ACE_EXPLOSION_REFLECTION(72,10); +ACE_EXPLOSION_REFLECTION(72,20); +ACE_EXPLOSION_REFLECTION(72,30); +ACE_EXPLOSION_REFLECTION(72,40); +ACE_EXPLOSION_REFLECTION(72,50); +ACE_EXPLOSION_REFLECTION(72,60); +ACE_EXPLOSION_REFLECTION(72,70); +ACE_EXPLOSION_REFLECTION(72,80); +ACE_EXPLOSION_REFLECTION(72,90); +ACE_EXPLOSION_REFLECTION(72,100); +ACE_EXPLOSION_REFLECTION(72,110); +ACE_EXPLOSION_REFLECTION(72,120); +ACE_EXPLOSION_REFLECTION(72,130); +ACE_EXPLOSION_REFLECTION(72,140); +ACE_EXPLOSION_REFLECTION(72,150); +ACE_EXPLOSION_REFLECTION(72,160); +ACE_EXPLOSION_REFLECTION(72,170); +ACE_EXPLOSION_REFLECTION(72,180); +ACE_EXPLOSION_REFLECTION(72,190); +ACE_EXPLOSION_REFLECTION(72,200); +ACE_EXPLOSION_REFLECTION(72,210); +ACE_EXPLOSION_REFLECTION(72,220); +ACE_EXPLOSION_REFLECTION(72,230); +ACE_EXPLOSION_REFLECTION(72,240); +ACE_EXPLOSION_REFLECTION(72,250); +ACE_EXPLOSION_REFLECTION(72,260); +ACE_EXPLOSION_REFLECTION(72,270); +ACE_EXPLOSION_REFLECTION(72,280); +ACE_EXPLOSION_REFLECTION(72,290); +ACE_EXPLOSION_REFLECTION(72,300); +ACE_EXPLOSION_REFLECTION(72,310); +ACE_EXPLOSION_REFLECTION(72,320); +ACE_EXPLOSION_REFLECTION(72,330); +ACE_EXPLOSION_REFLECTION(72,340); +ACE_EXPLOSION_REFLECTION(72,350); +ACE_EXPLOSION_REFLECTION(72,360); +ACE_EXPLOSION_REFLECTION(72,370); +ACE_EXPLOSION_REFLECTION(72,380); +ACE_EXPLOSION_REFLECTION(72,390); +ACE_EXPLOSION_REFLECTION(72,400); +ACE_EXPLOSION_REFLECTION(72,410); +ACE_EXPLOSION_REFLECTION(72,420); +ACE_EXPLOSION_REFLECTION(72,430); +ACE_EXPLOSION_REFLECTION(72,440); +ACE_EXPLOSION_REFLECTION(72,450); +ACE_EXPLOSION_REFLECTION(72,460); +ACE_EXPLOSION_REFLECTION(72,470); +ACE_EXPLOSION_REFLECTION(72,480); +ACE_EXPLOSION_REFLECTION(72,490); +ACE_EXPLOSION_REFLECTION(72,500); +ACE_EXPLOSION_REFLECTION(74,10); +ACE_EXPLOSION_REFLECTION(74,20); +ACE_EXPLOSION_REFLECTION(74,30); +ACE_EXPLOSION_REFLECTION(74,40); +ACE_EXPLOSION_REFLECTION(74,50); +ACE_EXPLOSION_REFLECTION(74,60); +ACE_EXPLOSION_REFLECTION(74,70); +ACE_EXPLOSION_REFLECTION(74,80); +ACE_EXPLOSION_REFLECTION(74,90); +ACE_EXPLOSION_REFLECTION(74,100); +ACE_EXPLOSION_REFLECTION(74,110); +ACE_EXPLOSION_REFLECTION(74,120); +ACE_EXPLOSION_REFLECTION(74,130); +ACE_EXPLOSION_REFLECTION(74,140); +ACE_EXPLOSION_REFLECTION(74,150); +ACE_EXPLOSION_REFLECTION(74,160); +ACE_EXPLOSION_REFLECTION(74,170); +ACE_EXPLOSION_REFLECTION(74,180); +ACE_EXPLOSION_REFLECTION(74,190); +ACE_EXPLOSION_REFLECTION(74,200); +ACE_EXPLOSION_REFLECTION(74,210); +ACE_EXPLOSION_REFLECTION(74,220); +ACE_EXPLOSION_REFLECTION(74,230); +ACE_EXPLOSION_REFLECTION(74,240); +ACE_EXPLOSION_REFLECTION(74,250); +ACE_EXPLOSION_REFLECTION(74,260); +ACE_EXPLOSION_REFLECTION(74,270); +ACE_EXPLOSION_REFLECTION(74,280); +ACE_EXPLOSION_REFLECTION(74,290); +ACE_EXPLOSION_REFLECTION(74,300); +ACE_EXPLOSION_REFLECTION(74,310); +ACE_EXPLOSION_REFLECTION(74,320); +ACE_EXPLOSION_REFLECTION(74,330); +ACE_EXPLOSION_REFLECTION(74,340); +ACE_EXPLOSION_REFLECTION(74,350); +ACE_EXPLOSION_REFLECTION(74,360); +ACE_EXPLOSION_REFLECTION(74,370); +ACE_EXPLOSION_REFLECTION(74,380); +ACE_EXPLOSION_REFLECTION(74,390); +ACE_EXPLOSION_REFLECTION(74,400); +ACE_EXPLOSION_REFLECTION(74,410); +ACE_EXPLOSION_REFLECTION(74,420); +ACE_EXPLOSION_REFLECTION(74,430); +ACE_EXPLOSION_REFLECTION(74,440); +ACE_EXPLOSION_REFLECTION(74,450); +ACE_EXPLOSION_REFLECTION(74,460); +ACE_EXPLOSION_REFLECTION(74,470); +ACE_EXPLOSION_REFLECTION(74,480); +ACE_EXPLOSION_REFLECTION(74,490); +ACE_EXPLOSION_REFLECTION(74,500); +ACE_EXPLOSION_REFLECTION(76,10); +ACE_EXPLOSION_REFLECTION(76,20); +ACE_EXPLOSION_REFLECTION(76,30); +ACE_EXPLOSION_REFLECTION(76,40); +ACE_EXPLOSION_REFLECTION(76,50); +ACE_EXPLOSION_REFLECTION(76,60); +ACE_EXPLOSION_REFLECTION(76,70); +ACE_EXPLOSION_REFLECTION(76,80); +ACE_EXPLOSION_REFLECTION(76,90); +ACE_EXPLOSION_REFLECTION(76,100); +ACE_EXPLOSION_REFLECTION(76,110); +ACE_EXPLOSION_REFLECTION(76,120); +ACE_EXPLOSION_REFLECTION(76,130); +ACE_EXPLOSION_REFLECTION(76,140); +ACE_EXPLOSION_REFLECTION(76,150); +ACE_EXPLOSION_REFLECTION(76,160); +ACE_EXPLOSION_REFLECTION(76,170); +ACE_EXPLOSION_REFLECTION(76,180); +ACE_EXPLOSION_REFLECTION(76,190); +ACE_EXPLOSION_REFLECTION(76,200); +ACE_EXPLOSION_REFLECTION(76,210); +ACE_EXPLOSION_REFLECTION(76,220); +ACE_EXPLOSION_REFLECTION(76,230); +ACE_EXPLOSION_REFLECTION(76,240); +ACE_EXPLOSION_REFLECTION(76,250); +ACE_EXPLOSION_REFLECTION(76,260); +ACE_EXPLOSION_REFLECTION(76,270); +ACE_EXPLOSION_REFLECTION(76,280); +ACE_EXPLOSION_REFLECTION(76,290); +ACE_EXPLOSION_REFLECTION(76,300); +ACE_EXPLOSION_REFLECTION(76,310); +ACE_EXPLOSION_REFLECTION(76,320); +ACE_EXPLOSION_REFLECTION(76,330); +ACE_EXPLOSION_REFLECTION(76,340); +ACE_EXPLOSION_REFLECTION(76,350); +ACE_EXPLOSION_REFLECTION(76,360); +ACE_EXPLOSION_REFLECTION(76,370); +ACE_EXPLOSION_REFLECTION(76,380); +ACE_EXPLOSION_REFLECTION(76,390); +ACE_EXPLOSION_REFLECTION(76,400); +ACE_EXPLOSION_REFLECTION(76,410); +ACE_EXPLOSION_REFLECTION(76,420); +ACE_EXPLOSION_REFLECTION(76,430); +ACE_EXPLOSION_REFLECTION(76,440); +ACE_EXPLOSION_REFLECTION(76,450); +ACE_EXPLOSION_REFLECTION(76,460); +ACE_EXPLOSION_REFLECTION(76,470); +ACE_EXPLOSION_REFLECTION(76,480); +ACE_EXPLOSION_REFLECTION(76,490); +ACE_EXPLOSION_REFLECTION(76,500); +ACE_EXPLOSION_REFLECTION(78,10); +ACE_EXPLOSION_REFLECTION(78,20); +ACE_EXPLOSION_REFLECTION(78,30); +ACE_EXPLOSION_REFLECTION(78,40); +ACE_EXPLOSION_REFLECTION(78,50); +ACE_EXPLOSION_REFLECTION(78,60); +ACE_EXPLOSION_REFLECTION(78,70); +ACE_EXPLOSION_REFLECTION(78,80); +ACE_EXPLOSION_REFLECTION(78,90); +ACE_EXPLOSION_REFLECTION(78,100); +ACE_EXPLOSION_REFLECTION(78,110); +ACE_EXPLOSION_REFLECTION(78,120); +ACE_EXPLOSION_REFLECTION(78,130); +ACE_EXPLOSION_REFLECTION(78,140); +ACE_EXPLOSION_REFLECTION(78,150); +ACE_EXPLOSION_REFLECTION(78,160); +ACE_EXPLOSION_REFLECTION(78,170); +ACE_EXPLOSION_REFLECTION(78,180); +ACE_EXPLOSION_REFLECTION(78,190); +ACE_EXPLOSION_REFLECTION(78,200); +ACE_EXPLOSION_REFLECTION(78,210); +ACE_EXPLOSION_REFLECTION(78,220); +ACE_EXPLOSION_REFLECTION(78,230); +ACE_EXPLOSION_REFLECTION(78,240); +ACE_EXPLOSION_REFLECTION(78,250); +ACE_EXPLOSION_REFLECTION(78,260); +ACE_EXPLOSION_REFLECTION(78,270); +ACE_EXPLOSION_REFLECTION(78,280); +ACE_EXPLOSION_REFLECTION(78,290); +ACE_EXPLOSION_REFLECTION(78,300); +ACE_EXPLOSION_REFLECTION(78,310); +ACE_EXPLOSION_REFLECTION(78,320); +ACE_EXPLOSION_REFLECTION(78,330); +ACE_EXPLOSION_REFLECTION(78,340); +ACE_EXPLOSION_REFLECTION(78,350); +ACE_EXPLOSION_REFLECTION(78,360); +ACE_EXPLOSION_REFLECTION(78,370); +ACE_EXPLOSION_REFLECTION(78,380); +ACE_EXPLOSION_REFLECTION(78,390); +ACE_EXPLOSION_REFLECTION(78,400); +ACE_EXPLOSION_REFLECTION(78,410); +ACE_EXPLOSION_REFLECTION(78,420); +ACE_EXPLOSION_REFLECTION(78,430); +ACE_EXPLOSION_REFLECTION(78,440); +ACE_EXPLOSION_REFLECTION(78,450); +ACE_EXPLOSION_REFLECTION(78,460); +ACE_EXPLOSION_REFLECTION(78,470); +ACE_EXPLOSION_REFLECTION(78,480); +ACE_EXPLOSION_REFLECTION(78,490); +ACE_EXPLOSION_REFLECTION(78,500); +ACE_EXPLOSION_REFLECTION(80,10); +ACE_EXPLOSION_REFLECTION(80,20); +ACE_EXPLOSION_REFLECTION(80,30); +ACE_EXPLOSION_REFLECTION(80,40); +ACE_EXPLOSION_REFLECTION(80,50); +ACE_EXPLOSION_REFLECTION(80,60); +ACE_EXPLOSION_REFLECTION(80,70); +ACE_EXPLOSION_REFLECTION(80,80); +ACE_EXPLOSION_REFLECTION(80,90); +ACE_EXPLOSION_REFLECTION(80,100); +ACE_EXPLOSION_REFLECTION(80,110); +ACE_EXPLOSION_REFLECTION(80,120); +ACE_EXPLOSION_REFLECTION(80,130); +ACE_EXPLOSION_REFLECTION(80,140); +ACE_EXPLOSION_REFLECTION(80,150); +ACE_EXPLOSION_REFLECTION(80,160); +ACE_EXPLOSION_REFLECTION(80,170); +ACE_EXPLOSION_REFLECTION(80,180); +ACE_EXPLOSION_REFLECTION(80,190); +ACE_EXPLOSION_REFLECTION(80,200); +ACE_EXPLOSION_REFLECTION(80,210); +ACE_EXPLOSION_REFLECTION(80,220); +ACE_EXPLOSION_REFLECTION(80,230); +ACE_EXPLOSION_REFLECTION(80,240); +ACE_EXPLOSION_REFLECTION(80,250); +ACE_EXPLOSION_REFLECTION(80,260); +ACE_EXPLOSION_REFLECTION(80,270); +ACE_EXPLOSION_REFLECTION(80,280); +ACE_EXPLOSION_REFLECTION(80,290); +ACE_EXPLOSION_REFLECTION(80,300); +ACE_EXPLOSION_REFLECTION(80,310); +ACE_EXPLOSION_REFLECTION(80,320); +ACE_EXPLOSION_REFLECTION(80,330); +ACE_EXPLOSION_REFLECTION(80,340); +ACE_EXPLOSION_REFLECTION(80,350); +ACE_EXPLOSION_REFLECTION(80,360); +ACE_EXPLOSION_REFLECTION(80,370); +ACE_EXPLOSION_REFLECTION(80,380); +ACE_EXPLOSION_REFLECTION(80,390); +ACE_EXPLOSION_REFLECTION(80,400); +ACE_EXPLOSION_REFLECTION(80,410); +ACE_EXPLOSION_REFLECTION(80,420); +ACE_EXPLOSION_REFLECTION(80,430); +ACE_EXPLOSION_REFLECTION(80,440); +ACE_EXPLOSION_REFLECTION(80,450); +ACE_EXPLOSION_REFLECTION(80,460); +ACE_EXPLOSION_REFLECTION(80,470); +ACE_EXPLOSION_REFLECTION(80,480); +ACE_EXPLOSION_REFLECTION(80,490); +ACE_EXPLOSION_REFLECTION(80,500); +ACE_EXPLOSION_REFLECTION(82,10); +ACE_EXPLOSION_REFLECTION(82,20); +ACE_EXPLOSION_REFLECTION(82,30); +ACE_EXPLOSION_REFLECTION(82,40); +ACE_EXPLOSION_REFLECTION(82,50); +ACE_EXPLOSION_REFLECTION(82,60); +ACE_EXPLOSION_REFLECTION(82,70); +ACE_EXPLOSION_REFLECTION(82,80); +ACE_EXPLOSION_REFLECTION(82,90); +ACE_EXPLOSION_REFLECTION(82,100); +ACE_EXPLOSION_REFLECTION(82,110); +ACE_EXPLOSION_REFLECTION(82,120); +ACE_EXPLOSION_REFLECTION(82,130); +ACE_EXPLOSION_REFLECTION(82,140); +ACE_EXPLOSION_REFLECTION(82,150); +ACE_EXPLOSION_REFLECTION(82,160); +ACE_EXPLOSION_REFLECTION(82,170); +ACE_EXPLOSION_REFLECTION(82,180); +ACE_EXPLOSION_REFLECTION(82,190); +ACE_EXPLOSION_REFLECTION(82,200); +ACE_EXPLOSION_REFLECTION(82,210); +ACE_EXPLOSION_REFLECTION(82,220); +ACE_EXPLOSION_REFLECTION(82,230); +ACE_EXPLOSION_REFLECTION(82,240); +ACE_EXPLOSION_REFLECTION(82,250); +ACE_EXPLOSION_REFLECTION(82,260); +ACE_EXPLOSION_REFLECTION(82,270); +ACE_EXPLOSION_REFLECTION(82,280); +ACE_EXPLOSION_REFLECTION(82,290); +ACE_EXPLOSION_REFLECTION(82,300); +ACE_EXPLOSION_REFLECTION(82,310); +ACE_EXPLOSION_REFLECTION(82,320); +ACE_EXPLOSION_REFLECTION(82,330); +ACE_EXPLOSION_REFLECTION(82,340); +ACE_EXPLOSION_REFLECTION(82,350); +ACE_EXPLOSION_REFLECTION(82,360); +ACE_EXPLOSION_REFLECTION(82,370); +ACE_EXPLOSION_REFLECTION(82,380); +ACE_EXPLOSION_REFLECTION(82,390); +ACE_EXPLOSION_REFLECTION(82,400); +ACE_EXPLOSION_REFLECTION(82,410); +ACE_EXPLOSION_REFLECTION(82,420); +ACE_EXPLOSION_REFLECTION(82,430); +ACE_EXPLOSION_REFLECTION(82,440); +ACE_EXPLOSION_REFLECTION(82,450); +ACE_EXPLOSION_REFLECTION(82,460); +ACE_EXPLOSION_REFLECTION(82,470); +ACE_EXPLOSION_REFLECTION(82,480); +ACE_EXPLOSION_REFLECTION(82,490); +ACE_EXPLOSION_REFLECTION(82,500); +ACE_EXPLOSION_REFLECTION(84,10); +ACE_EXPLOSION_REFLECTION(84,20); +ACE_EXPLOSION_REFLECTION(84,30); +ACE_EXPLOSION_REFLECTION(84,40); +ACE_EXPLOSION_REFLECTION(84,50); +ACE_EXPLOSION_REFLECTION(84,60); +ACE_EXPLOSION_REFLECTION(84,70); +ACE_EXPLOSION_REFLECTION(84,80); +ACE_EXPLOSION_REFLECTION(84,90); +ACE_EXPLOSION_REFLECTION(84,100); +ACE_EXPLOSION_REFLECTION(84,110); +ACE_EXPLOSION_REFLECTION(84,120); +ACE_EXPLOSION_REFLECTION(84,130); +ACE_EXPLOSION_REFLECTION(84,140); +ACE_EXPLOSION_REFLECTION(84,150); +ACE_EXPLOSION_REFLECTION(84,160); +ACE_EXPLOSION_REFLECTION(84,170); +ACE_EXPLOSION_REFLECTION(84,180); +ACE_EXPLOSION_REFLECTION(84,190); +ACE_EXPLOSION_REFLECTION(84,200); +ACE_EXPLOSION_REFLECTION(84,210); +ACE_EXPLOSION_REFLECTION(84,220); +ACE_EXPLOSION_REFLECTION(84,230); +ACE_EXPLOSION_REFLECTION(84,240); +ACE_EXPLOSION_REFLECTION(84,250); +ACE_EXPLOSION_REFLECTION(84,260); +ACE_EXPLOSION_REFLECTION(84,270); +ACE_EXPLOSION_REFLECTION(84,280); +ACE_EXPLOSION_REFLECTION(84,290); +ACE_EXPLOSION_REFLECTION(84,300); +ACE_EXPLOSION_REFLECTION(84,310); +ACE_EXPLOSION_REFLECTION(84,320); +ACE_EXPLOSION_REFLECTION(84,330); +ACE_EXPLOSION_REFLECTION(84,340); +ACE_EXPLOSION_REFLECTION(84,350); +ACE_EXPLOSION_REFLECTION(84,360); +ACE_EXPLOSION_REFLECTION(84,370); +ACE_EXPLOSION_REFLECTION(84,380); +ACE_EXPLOSION_REFLECTION(84,390); +ACE_EXPLOSION_REFLECTION(84,400); +ACE_EXPLOSION_REFLECTION(84,410); +ACE_EXPLOSION_REFLECTION(84,420); +ACE_EXPLOSION_REFLECTION(84,430); +ACE_EXPLOSION_REFLECTION(84,440); +ACE_EXPLOSION_REFLECTION(84,450); +ACE_EXPLOSION_REFLECTION(84,460); +ACE_EXPLOSION_REFLECTION(84,470); +ACE_EXPLOSION_REFLECTION(84,480); +ACE_EXPLOSION_REFLECTION(84,490); +ACE_EXPLOSION_REFLECTION(84,500); +ACE_EXPLOSION_REFLECTION(86,10); +ACE_EXPLOSION_REFLECTION(86,20); +ACE_EXPLOSION_REFLECTION(86,30); +ACE_EXPLOSION_REFLECTION(86,40); +ACE_EXPLOSION_REFLECTION(86,50); +ACE_EXPLOSION_REFLECTION(86,60); +ACE_EXPLOSION_REFLECTION(86,70); +ACE_EXPLOSION_REFLECTION(86,80); +ACE_EXPLOSION_REFLECTION(86,90); +ACE_EXPLOSION_REFLECTION(86,100); +ACE_EXPLOSION_REFLECTION(86,110); +ACE_EXPLOSION_REFLECTION(86,120); +ACE_EXPLOSION_REFLECTION(86,130); +ACE_EXPLOSION_REFLECTION(86,140); +ACE_EXPLOSION_REFLECTION(86,150); +ACE_EXPLOSION_REFLECTION(86,160); +ACE_EXPLOSION_REFLECTION(86,170); +ACE_EXPLOSION_REFLECTION(86,180); +ACE_EXPLOSION_REFLECTION(86,190); +ACE_EXPLOSION_REFLECTION(86,200); +ACE_EXPLOSION_REFLECTION(86,210); +ACE_EXPLOSION_REFLECTION(86,220); +ACE_EXPLOSION_REFLECTION(86,230); +ACE_EXPLOSION_REFLECTION(86,240); +ACE_EXPLOSION_REFLECTION(86,250); +ACE_EXPLOSION_REFLECTION(86,260); +ACE_EXPLOSION_REFLECTION(86,270); +ACE_EXPLOSION_REFLECTION(86,280); +ACE_EXPLOSION_REFLECTION(86,290); +ACE_EXPLOSION_REFLECTION(86,300); +ACE_EXPLOSION_REFLECTION(86,310); +ACE_EXPLOSION_REFLECTION(86,320); +ACE_EXPLOSION_REFLECTION(86,330); +ACE_EXPLOSION_REFLECTION(86,340); +ACE_EXPLOSION_REFLECTION(86,350); +ACE_EXPLOSION_REFLECTION(86,360); +ACE_EXPLOSION_REFLECTION(86,370); +ACE_EXPLOSION_REFLECTION(86,380); +ACE_EXPLOSION_REFLECTION(86,390); +ACE_EXPLOSION_REFLECTION(86,400); +ACE_EXPLOSION_REFLECTION(86,410); +ACE_EXPLOSION_REFLECTION(86,420); +ACE_EXPLOSION_REFLECTION(86,430); +ACE_EXPLOSION_REFLECTION(86,440); +ACE_EXPLOSION_REFLECTION(86,450); +ACE_EXPLOSION_REFLECTION(86,460); +ACE_EXPLOSION_REFLECTION(86,470); +ACE_EXPLOSION_REFLECTION(86,480); +ACE_EXPLOSION_REFLECTION(86,490); +ACE_EXPLOSION_REFLECTION(86,500); +ACE_EXPLOSION_REFLECTION(88,10); +ACE_EXPLOSION_REFLECTION(88,20); +ACE_EXPLOSION_REFLECTION(88,30); +ACE_EXPLOSION_REFLECTION(88,40); +ACE_EXPLOSION_REFLECTION(88,50); +ACE_EXPLOSION_REFLECTION(88,60); +ACE_EXPLOSION_REFLECTION(88,70); +ACE_EXPLOSION_REFLECTION(88,80); +ACE_EXPLOSION_REFLECTION(88,90); +ACE_EXPLOSION_REFLECTION(88,100); +ACE_EXPLOSION_REFLECTION(88,110); +ACE_EXPLOSION_REFLECTION(88,120); +ACE_EXPLOSION_REFLECTION(88,130); +ACE_EXPLOSION_REFLECTION(88,140); +ACE_EXPLOSION_REFLECTION(88,150); +ACE_EXPLOSION_REFLECTION(88,160); +ACE_EXPLOSION_REFLECTION(88,170); +ACE_EXPLOSION_REFLECTION(88,180); +ACE_EXPLOSION_REFLECTION(88,190); +ACE_EXPLOSION_REFLECTION(88,200); +ACE_EXPLOSION_REFLECTION(88,210); +ACE_EXPLOSION_REFLECTION(88,220); +ACE_EXPLOSION_REFLECTION(88,230); +ACE_EXPLOSION_REFLECTION(88,240); +ACE_EXPLOSION_REFLECTION(88,250); +ACE_EXPLOSION_REFLECTION(88,260); +ACE_EXPLOSION_REFLECTION(88,270); +ACE_EXPLOSION_REFLECTION(88,280); +ACE_EXPLOSION_REFLECTION(88,290); +ACE_EXPLOSION_REFLECTION(88,300); +ACE_EXPLOSION_REFLECTION(88,310); +ACE_EXPLOSION_REFLECTION(88,320); +ACE_EXPLOSION_REFLECTION(88,330); +ACE_EXPLOSION_REFLECTION(88,340); +ACE_EXPLOSION_REFLECTION(88,350); +ACE_EXPLOSION_REFLECTION(88,360); +ACE_EXPLOSION_REFLECTION(88,370); +ACE_EXPLOSION_REFLECTION(88,380); +ACE_EXPLOSION_REFLECTION(88,390); +ACE_EXPLOSION_REFLECTION(88,400); +ACE_EXPLOSION_REFLECTION(88,410); +ACE_EXPLOSION_REFLECTION(88,420); +ACE_EXPLOSION_REFLECTION(88,430); +ACE_EXPLOSION_REFLECTION(88,440); +ACE_EXPLOSION_REFLECTION(88,450); +ACE_EXPLOSION_REFLECTION(88,460); +ACE_EXPLOSION_REFLECTION(88,470); +ACE_EXPLOSION_REFLECTION(88,480); +ACE_EXPLOSION_REFLECTION(88,490); +ACE_EXPLOSION_REFLECTION(88,500); +ACE_EXPLOSION_REFLECTION(90,10); +ACE_EXPLOSION_REFLECTION(90,20); +ACE_EXPLOSION_REFLECTION(90,30); +ACE_EXPLOSION_REFLECTION(90,40); +ACE_EXPLOSION_REFLECTION(90,50); +ACE_EXPLOSION_REFLECTION(90,60); +ACE_EXPLOSION_REFLECTION(90,70); +ACE_EXPLOSION_REFLECTION(90,80); +ACE_EXPLOSION_REFLECTION(90,90); +ACE_EXPLOSION_REFLECTION(90,100); +ACE_EXPLOSION_REFLECTION(90,110); +ACE_EXPLOSION_REFLECTION(90,120); +ACE_EXPLOSION_REFLECTION(90,130); +ACE_EXPLOSION_REFLECTION(90,140); +ACE_EXPLOSION_REFLECTION(90,150); +ACE_EXPLOSION_REFLECTION(90,160); +ACE_EXPLOSION_REFLECTION(90,170); +ACE_EXPLOSION_REFLECTION(90,180); +ACE_EXPLOSION_REFLECTION(90,190); +ACE_EXPLOSION_REFLECTION(90,200); +ACE_EXPLOSION_REFLECTION(90,210); +ACE_EXPLOSION_REFLECTION(90,220); +ACE_EXPLOSION_REFLECTION(90,230); +ACE_EXPLOSION_REFLECTION(90,240); +ACE_EXPLOSION_REFLECTION(90,250); +ACE_EXPLOSION_REFLECTION(90,260); +ACE_EXPLOSION_REFLECTION(90,270); +ACE_EXPLOSION_REFLECTION(90,280); +ACE_EXPLOSION_REFLECTION(90,290); +ACE_EXPLOSION_REFLECTION(90,300); +ACE_EXPLOSION_REFLECTION(90,310); +ACE_EXPLOSION_REFLECTION(90,320); +ACE_EXPLOSION_REFLECTION(90,330); +ACE_EXPLOSION_REFLECTION(90,340); +ACE_EXPLOSION_REFLECTION(90,350); +ACE_EXPLOSION_REFLECTION(90,360); +ACE_EXPLOSION_REFLECTION(90,370); +ACE_EXPLOSION_REFLECTION(90,380); +ACE_EXPLOSION_REFLECTION(90,390); +ACE_EXPLOSION_REFLECTION(90,400); +ACE_EXPLOSION_REFLECTION(90,410); +ACE_EXPLOSION_REFLECTION(90,420); +ACE_EXPLOSION_REFLECTION(90,430); +ACE_EXPLOSION_REFLECTION(90,440); +ACE_EXPLOSION_REFLECTION(90,450); +ACE_EXPLOSION_REFLECTION(90,460); +ACE_EXPLOSION_REFLECTION(90,470); +ACE_EXPLOSION_REFLECTION(90,480); +ACE_EXPLOSION_REFLECTION(90,490); +ACE_EXPLOSION_REFLECTION(90,500); +ACE_EXPLOSION_REFLECTION(92,10); +ACE_EXPLOSION_REFLECTION(92,20); +ACE_EXPLOSION_REFLECTION(92,30); +ACE_EXPLOSION_REFLECTION(92,40); +ACE_EXPLOSION_REFLECTION(92,50); +ACE_EXPLOSION_REFLECTION(92,60); +ACE_EXPLOSION_REFLECTION(92,70); +ACE_EXPLOSION_REFLECTION(92,80); +ACE_EXPLOSION_REFLECTION(92,90); +ACE_EXPLOSION_REFLECTION(92,100); +ACE_EXPLOSION_REFLECTION(92,110); +ACE_EXPLOSION_REFLECTION(92,120); +ACE_EXPLOSION_REFLECTION(92,130); +ACE_EXPLOSION_REFLECTION(92,140); +ACE_EXPLOSION_REFLECTION(92,150); +ACE_EXPLOSION_REFLECTION(92,160); +ACE_EXPLOSION_REFLECTION(92,170); +ACE_EXPLOSION_REFLECTION(92,180); +ACE_EXPLOSION_REFLECTION(92,190); +ACE_EXPLOSION_REFLECTION(92,200); +ACE_EXPLOSION_REFLECTION(92,210); +ACE_EXPLOSION_REFLECTION(92,220); +ACE_EXPLOSION_REFLECTION(92,230); +ACE_EXPLOSION_REFLECTION(92,240); +ACE_EXPLOSION_REFLECTION(92,250); +ACE_EXPLOSION_REFLECTION(92,260); +ACE_EXPLOSION_REFLECTION(92,270); +ACE_EXPLOSION_REFLECTION(92,280); +ACE_EXPLOSION_REFLECTION(92,290); +ACE_EXPLOSION_REFLECTION(92,300); +ACE_EXPLOSION_REFLECTION(92,310); +ACE_EXPLOSION_REFLECTION(92,320); +ACE_EXPLOSION_REFLECTION(92,330); +ACE_EXPLOSION_REFLECTION(92,340); +ACE_EXPLOSION_REFLECTION(92,350); +ACE_EXPLOSION_REFLECTION(92,360); +ACE_EXPLOSION_REFLECTION(92,370); +ACE_EXPLOSION_REFLECTION(92,380); +ACE_EXPLOSION_REFLECTION(92,390); +ACE_EXPLOSION_REFLECTION(92,400); +ACE_EXPLOSION_REFLECTION(92,410); +ACE_EXPLOSION_REFLECTION(92,420); +ACE_EXPLOSION_REFLECTION(92,430); +ACE_EXPLOSION_REFLECTION(92,440); +ACE_EXPLOSION_REFLECTION(92,450); +ACE_EXPLOSION_REFLECTION(92,460); +ACE_EXPLOSION_REFLECTION(92,470); +ACE_EXPLOSION_REFLECTION(92,480); +ACE_EXPLOSION_REFLECTION(92,490); +ACE_EXPLOSION_REFLECTION(92,500); +ACE_EXPLOSION_REFLECTION(94,10); +ACE_EXPLOSION_REFLECTION(94,20); +ACE_EXPLOSION_REFLECTION(94,30); +ACE_EXPLOSION_REFLECTION(94,40); +ACE_EXPLOSION_REFLECTION(94,50); +ACE_EXPLOSION_REFLECTION(94,60); +ACE_EXPLOSION_REFLECTION(94,70); +ACE_EXPLOSION_REFLECTION(94,80); +ACE_EXPLOSION_REFLECTION(94,90); +ACE_EXPLOSION_REFLECTION(94,100); +ACE_EXPLOSION_REFLECTION(94,110); +ACE_EXPLOSION_REFLECTION(94,120); +ACE_EXPLOSION_REFLECTION(94,130); +ACE_EXPLOSION_REFLECTION(94,140); +ACE_EXPLOSION_REFLECTION(94,150); +ACE_EXPLOSION_REFLECTION(94,160); +ACE_EXPLOSION_REFLECTION(94,170); +ACE_EXPLOSION_REFLECTION(94,180); +ACE_EXPLOSION_REFLECTION(94,190); +ACE_EXPLOSION_REFLECTION(94,200); +ACE_EXPLOSION_REFLECTION(94,210); +ACE_EXPLOSION_REFLECTION(94,220); +ACE_EXPLOSION_REFLECTION(94,230); +ACE_EXPLOSION_REFLECTION(94,240); +ACE_EXPLOSION_REFLECTION(94,250); +ACE_EXPLOSION_REFLECTION(94,260); +ACE_EXPLOSION_REFLECTION(94,270); +ACE_EXPLOSION_REFLECTION(94,280); +ACE_EXPLOSION_REFLECTION(94,290); +ACE_EXPLOSION_REFLECTION(94,300); +ACE_EXPLOSION_REFLECTION(94,310); +ACE_EXPLOSION_REFLECTION(94,320); +ACE_EXPLOSION_REFLECTION(94,330); +ACE_EXPLOSION_REFLECTION(94,340); +ACE_EXPLOSION_REFLECTION(94,350); +ACE_EXPLOSION_REFLECTION(94,360); +ACE_EXPLOSION_REFLECTION(94,370); +ACE_EXPLOSION_REFLECTION(94,380); +ACE_EXPLOSION_REFLECTION(94,390); +ACE_EXPLOSION_REFLECTION(94,400); +ACE_EXPLOSION_REFLECTION(94,410); +ACE_EXPLOSION_REFLECTION(94,420); +ACE_EXPLOSION_REFLECTION(94,430); +ACE_EXPLOSION_REFLECTION(94,440); +ACE_EXPLOSION_REFLECTION(94,450); +ACE_EXPLOSION_REFLECTION(94,460); +ACE_EXPLOSION_REFLECTION(94,470); +ACE_EXPLOSION_REFLECTION(94,480); +ACE_EXPLOSION_REFLECTION(94,490); +ACE_EXPLOSION_REFLECTION(94,500); +ACE_EXPLOSION_REFLECTION(96,10); +ACE_EXPLOSION_REFLECTION(96,20); +ACE_EXPLOSION_REFLECTION(96,30); +ACE_EXPLOSION_REFLECTION(96,40); +ACE_EXPLOSION_REFLECTION(96,50); +ACE_EXPLOSION_REFLECTION(96,60); +ACE_EXPLOSION_REFLECTION(96,70); +ACE_EXPLOSION_REFLECTION(96,80); +ACE_EXPLOSION_REFLECTION(96,90); +ACE_EXPLOSION_REFLECTION(96,100); +ACE_EXPLOSION_REFLECTION(96,110); +ACE_EXPLOSION_REFLECTION(96,120); +ACE_EXPLOSION_REFLECTION(96,130); +ACE_EXPLOSION_REFLECTION(96,140); +ACE_EXPLOSION_REFLECTION(96,150); +ACE_EXPLOSION_REFLECTION(96,160); +ACE_EXPLOSION_REFLECTION(96,170); +ACE_EXPLOSION_REFLECTION(96,180); +ACE_EXPLOSION_REFLECTION(96,190); +ACE_EXPLOSION_REFLECTION(96,200); +ACE_EXPLOSION_REFLECTION(96,210); +ACE_EXPLOSION_REFLECTION(96,220); +ACE_EXPLOSION_REFLECTION(96,230); +ACE_EXPLOSION_REFLECTION(96,240); +ACE_EXPLOSION_REFLECTION(96,250); +ACE_EXPLOSION_REFLECTION(96,260); +ACE_EXPLOSION_REFLECTION(96,270); +ACE_EXPLOSION_REFLECTION(96,280); +ACE_EXPLOSION_REFLECTION(96,290); +ACE_EXPLOSION_REFLECTION(96,300); +ACE_EXPLOSION_REFLECTION(96,310); +ACE_EXPLOSION_REFLECTION(96,320); +ACE_EXPLOSION_REFLECTION(96,330); +ACE_EXPLOSION_REFLECTION(96,340); +ACE_EXPLOSION_REFLECTION(96,350); +ACE_EXPLOSION_REFLECTION(96,360); +ACE_EXPLOSION_REFLECTION(96,370); +ACE_EXPLOSION_REFLECTION(96,380); +ACE_EXPLOSION_REFLECTION(96,390); +ACE_EXPLOSION_REFLECTION(96,400); +ACE_EXPLOSION_REFLECTION(96,410); +ACE_EXPLOSION_REFLECTION(96,420); +ACE_EXPLOSION_REFLECTION(96,430); +ACE_EXPLOSION_REFLECTION(96,440); +ACE_EXPLOSION_REFLECTION(96,450); +ACE_EXPLOSION_REFLECTION(96,460); +ACE_EXPLOSION_REFLECTION(96,470); +ACE_EXPLOSION_REFLECTION(96,480); +ACE_EXPLOSION_REFLECTION(96,490); +ACE_EXPLOSION_REFLECTION(96,500); +ACE_EXPLOSION_REFLECTION(98,10); +ACE_EXPLOSION_REFLECTION(98,20); +ACE_EXPLOSION_REFLECTION(98,30); +ACE_EXPLOSION_REFLECTION(98,40); +ACE_EXPLOSION_REFLECTION(98,50); +ACE_EXPLOSION_REFLECTION(98,60); +ACE_EXPLOSION_REFLECTION(98,70); +ACE_EXPLOSION_REFLECTION(98,80); +ACE_EXPLOSION_REFLECTION(98,90); +ACE_EXPLOSION_REFLECTION(98,100); +ACE_EXPLOSION_REFLECTION(98,110); +ACE_EXPLOSION_REFLECTION(98,120); +ACE_EXPLOSION_REFLECTION(98,130); +ACE_EXPLOSION_REFLECTION(98,140); +ACE_EXPLOSION_REFLECTION(98,150); +ACE_EXPLOSION_REFLECTION(98,160); +ACE_EXPLOSION_REFLECTION(98,170); +ACE_EXPLOSION_REFLECTION(98,180); +ACE_EXPLOSION_REFLECTION(98,190); +ACE_EXPLOSION_REFLECTION(98,200); +ACE_EXPLOSION_REFLECTION(98,210); +ACE_EXPLOSION_REFLECTION(98,220); +ACE_EXPLOSION_REFLECTION(98,230); +ACE_EXPLOSION_REFLECTION(98,240); +ACE_EXPLOSION_REFLECTION(98,250); +ACE_EXPLOSION_REFLECTION(98,260); +ACE_EXPLOSION_REFLECTION(98,270); +ACE_EXPLOSION_REFLECTION(98,280); +ACE_EXPLOSION_REFLECTION(98,290); +ACE_EXPLOSION_REFLECTION(98,300); +ACE_EXPLOSION_REFLECTION(98,310); +ACE_EXPLOSION_REFLECTION(98,320); +ACE_EXPLOSION_REFLECTION(98,330); +ACE_EXPLOSION_REFLECTION(98,340); +ACE_EXPLOSION_REFLECTION(98,350); +ACE_EXPLOSION_REFLECTION(98,360); +ACE_EXPLOSION_REFLECTION(98,370); +ACE_EXPLOSION_REFLECTION(98,380); +ACE_EXPLOSION_REFLECTION(98,390); +ACE_EXPLOSION_REFLECTION(98,400); +ACE_EXPLOSION_REFLECTION(98,410); +ACE_EXPLOSION_REFLECTION(98,420); +ACE_EXPLOSION_REFLECTION(98,430); +ACE_EXPLOSION_REFLECTION(98,440); +ACE_EXPLOSION_REFLECTION(98,450); +ACE_EXPLOSION_REFLECTION(98,460); +ACE_EXPLOSION_REFLECTION(98,470); +ACE_EXPLOSION_REFLECTION(98,480); +ACE_EXPLOSION_REFLECTION(98,490); +ACE_EXPLOSION_REFLECTION(98,500); +ACE_EXPLOSION_REFLECTION(100,10); +ACE_EXPLOSION_REFLECTION(100,20); +ACE_EXPLOSION_REFLECTION(100,30); +ACE_EXPLOSION_REFLECTION(100,40); +ACE_EXPLOSION_REFLECTION(100,50); +ACE_EXPLOSION_REFLECTION(100,60); +ACE_EXPLOSION_REFLECTION(100,70); +ACE_EXPLOSION_REFLECTION(100,80); +ACE_EXPLOSION_REFLECTION(100,90); +ACE_EXPLOSION_REFLECTION(100,100); +ACE_EXPLOSION_REFLECTION(100,110); +ACE_EXPLOSION_REFLECTION(100,120); +ACE_EXPLOSION_REFLECTION(100,130); +ACE_EXPLOSION_REFLECTION(100,140); +ACE_EXPLOSION_REFLECTION(100,150); +ACE_EXPLOSION_REFLECTION(100,160); +ACE_EXPLOSION_REFLECTION(100,170); +ACE_EXPLOSION_REFLECTION(100,180); +ACE_EXPLOSION_REFLECTION(100,190); +ACE_EXPLOSION_REFLECTION(100,200); +ACE_EXPLOSION_REFLECTION(100,210); +ACE_EXPLOSION_REFLECTION(100,220); +ACE_EXPLOSION_REFLECTION(100,230); +ACE_EXPLOSION_REFLECTION(100,240); +ACE_EXPLOSION_REFLECTION(100,250); +ACE_EXPLOSION_REFLECTION(100,260); +ACE_EXPLOSION_REFLECTION(100,270); +ACE_EXPLOSION_REFLECTION(100,280); +ACE_EXPLOSION_REFLECTION(100,290); +ACE_EXPLOSION_REFLECTION(100,300); +ACE_EXPLOSION_REFLECTION(100,310); +ACE_EXPLOSION_REFLECTION(100,320); +ACE_EXPLOSION_REFLECTION(100,330); +ACE_EXPLOSION_REFLECTION(100,340); +ACE_EXPLOSION_REFLECTION(100,350); +ACE_EXPLOSION_REFLECTION(100,360); +ACE_EXPLOSION_REFLECTION(100,370); +ACE_EXPLOSION_REFLECTION(100,380); +ACE_EXPLOSION_REFLECTION(100,390); +ACE_EXPLOSION_REFLECTION(100,400); +ACE_EXPLOSION_REFLECTION(100,410); +ACE_EXPLOSION_REFLECTION(100,420); +ACE_EXPLOSION_REFLECTION(100,430); +ACE_EXPLOSION_REFLECTION(100,440); +ACE_EXPLOSION_REFLECTION(100,450); +ACE_EXPLOSION_REFLECTION(100,460); +ACE_EXPLOSION_REFLECTION(100,470); +ACE_EXPLOSION_REFLECTION(100,480); +ACE_EXPLOSION_REFLECTION(100,490); +ACE_EXPLOSION_REFLECTION(100,500); + diff --git a/addons/frag/XEH_pre_Init.sqf b/addons/frag/XEH_pre_Init.sqf index 5b3aa36b18..4ec70bbc3d 100644 --- a/addons/frag/XEH_pre_Init.sqf +++ b/addons/frag/XEH_pre_Init.sqf @@ -9,6 +9,10 @@ PREP(trackFragRound); PREP(spallTrack); PREP(doSpall); PREP(vectorDiffFast); +PREP(findReflections); +PREP(doExplosions); +PREP(doReflections); + GVAR(trackedObjects) = []; GVAR(blackList) = []; diff --git a/addons/frag/functions/fnc_doExplosions.sqf b/addons/frag/functions/fnc_doExplosions.sqf new file mode 100644 index 0000000000..f2c20c2f1e --- /dev/null +++ b/addons/frag/functions/fnc_doExplosions.sqf @@ -0,0 +1,26 @@ +//fnc_doExplosions.sqf +#include "script_component.hpp" + +private ["_params", "_explosions", "_index", "_i", "_exp", "_refExp", "_bpos", "_hit", "_distance", "_indirectHitRange", "_depth"]; +_params = _this select 0; +_explosions = _params select 0; +_index = _params select 1; +for "_i" from _index to ((_index+1) min (count _explosions)) do { + _exp = _explosions select _i; + _refExp = _exp select 0; + _bpos = _exp select 1; + _hit = _exp select 2; + _distance = _exp select 3; + _indirectHitRange = _exp select 4; + _depth = _exp select 5; + _refExp createVehicle (ASLtoATL _bpos); + // if(_hit >= 150 && _distance > _indirectHitRange) then { + // [_bpos, _refExp, _depth] call FUNC(doReflections); + // }; +}; +_index = _index + 1; +if(_index >= (count _explosions)) then { + [(_this select 1)] call cba_fnc_removePerFrameHandler; +} else { + _params set[1, _index]; +}; diff --git a/addons/frag/functions/fnc_doReflections.sqf b/addons/frag/functions/fnc_doReflections.sqf new file mode 100644 index 0000000000..844ccb4c9b --- /dev/null +++ b/addons/frag/functions/fnc_doReflections.sqf @@ -0,0 +1,22 @@ +//fnc_doReflections.sqf +#include "script_component.hpp" + +private ["_pos", "_ammo", "_depth", "_hit", "_range", "_hitFactor", "_indirectHitRange", "_indirectHit", "_testParams"]; + +_pos = _this select 0; +_ammo = _this select 1; +_depth = 1; +if(count _this > 2) then { + _depth = _this select 2; +}; +// TEST_ICONS pushBack [_pos, format["EXP!", _hit, _range, _hitFactor]]; +if(_depth <= 2) then { + _indirectHitRange = getNumber(configFile >> "CfgAmmo" >> _ammo >> "indirectHitRange"); + _indirectHit = getNumber(configFile >> "CfgAmmo" >> _ammo >> "indirectHit"); + + + + + _testParams = [_pos, [_indirectHitRange, _indirectHit], [], [], -4, _depth, 0]; + [DFUNC(findReflections), 0.005, _testParams] call cba_fnc_addPerFrameHandler; +}; diff --git a/addons/frag/functions/fnc_findReflections.sqf b/addons/frag/functions/fnc_findReflections.sqf new file mode 100644 index 0000000000..75c4ee2ae6 --- /dev/null +++ b/addons/frag/functions/fnc_findReflections.sqf @@ -0,0 +1,130 @@ +//fnc_findReflections.sqf +#include "script_component.hpp" + +private ["_split", "_radi", "_params", "_pos", "_explosiveInfo", "_los", "_nlos", "_zIndex", "_depth", "_indirectHitRange", + "_indirectHit", "_distanceCount", "_lastPos", "_test", "_vec", "_testPos", "_buckets", "_excludes", "_bucketIndex", "_bucketPos", + "_bucketList", "_c", "_index", "_blist", "_avgX", "_avgY", "_avgZ", "_bpos", "_distance", "_hitFactor", "_hit", "_range", "_refExp", + "_rand", "_i", "_x", "_res", "_forEachIndex", "_explosions", "_can", "_dirvec"]; + + +_params = _this select 0; +_pos = _params select 0; +_explosiveInfo = _params select 1; +_los = _params select 2; +_nlos = _params select 3; +_zIndex = _params select 4; +_depth = _params select 5; +_rand = _params select 6; + +_split = 15; +_radi = (360/_split*_depth); + +// player sideChat format["p: %1", _explosiveInfo]; +_indirectHitRange = _explosiveInfo select 0; +_indirectHit = _explosiveInfo select 1; +_distanceCount = (floor _indirectHitRange*4) min 100; + +if(_zIndex < 5) then { + _lastPos = _pos; + _zAng = _zIndex*20+2; + if(_zAng > 80) then { + _radi = 1; + _zAng = 90; + }; + for "_i" from 0 to _radi do { + _test = true; + _vec = [1, ((_i*_split)+_rand) mod 360, _zAng] call cba_fnc_polar2vect; + for "_x" from 1 to _distanceCount do { + _testPos = _pos vectorAdd (_vec vectorMultiply _x); + // drop ["\a3\data_f\Cl_basic","","Billboard",1,15,ASLtoATL _testPos,[0,0,0],1,1.275,1.0,0.0,[1],[[1,0,0,1]],[0],0.0,2.0,"","",""]; + _res = lineIntersectsWith [_pos, _testPos]; + if(count _res > 0) exitWith { + _test = false; + _nlos pushBack _lastPos; + // { + // _x addEventHandler ["HandleDamage", { diag_log text format["this: %1", _this]; }]; + // } forEach _res; + // drop ["\a3\data_f\Cl_basic","","Billboard",1,15,ASLtoATL _testPos,[0,0,0],1,1.275,1.0,0.0,[1],[[1,0,0,1]],[0],0.0,2.0,"","",""]; + // TEST_PAIRS pushBack [_pos, _lastPos, [1,0,0,1]]; + + }; + // if(terrainIntersectASL [_pos, _testPos]) exitWith {}; + _lastPos = _testPos; + }; + }; + _params set[4, _zIndex+1]; +} else { + _depth = _depth + 1; + _buckets = []; + _excludes = []; + _bucketIndex = 0; + _bucketPos = nil; + _bucketList = nil; + _c = 0; + while { count(_nlos) != count(_excludes) && _c < (count _nlos) } do { + scopeName "mainSearch"; + { + if(!(_forEachIndex in _excludes)) then { + _index = _buckets pushBack [_x, [_x]]; + _excludes pushBack _forEachIndex; + _bucketPos = _x; + _bucketList = (_buckets select _index) select 1; + breakTo "mainSearch"; + }; + } forEach _nlos; + { + if(!(_forEachIndex in _excludes)) then { + _testPos = _x; + if(_testPos vectorDistanceSqr _bucketPos <= 30) then { + _bucketList pushBack _x; + _excludes pushBack _forEachIndex; + }; + }; + } forEach _nlos; + _c = _c + 1; + }; + + // player sideChat format["c: %1", count _buckets]; + _explosions = []; + { + _blist = _x select 1; + _avgX = 0; + _avgY = 0; + _avgZ = 0; + + { + _avgX = _avgX + (_x select 0); + _avgY = _avgY + (_x select 1); + _avgZ = _avgZ + (_x select 2); + } forEach _blist; + _c = count _blist; + _bpos = [_avgX/_c, _avgY/_c, _avgZ/_c]; + + _distance = _pos vectorDistance _bpos; + _hitFactor = 1-(((_distance/(_indirectHitRange*4)) min 1) max 0); + // _hitFactor = 1/(_distance^2); + _hit = _indirectHit*_hitFactor; + _hit = (floor (_hit/4)) min 500; + _hit = _hit - (_hit%10); + _range = (floor (_indirectHitRange-(_distance/4))) min 100; + _range = _range - (_range%2); + + if(_hit >= 10 && _range > 0) then { + // TEST_ICONS pushBack [_bpos, format["h: %1, r: %2, hf: %3 d: %4 ihr: %5", _hit, _range, _hitFactor, _distance, _indirectHitRange*4]]; + // TEST_PAIRS pushBack [_pos, _bpos, [1,0,0,1]]; + _refExp = format["ace_explosion_reflection_%1_%2", _range, _hit]; + // _refExp createVehicle (ASLtoATL _bpos); + // drop ["\a3\data_f\Cl_basic","","Billboard",1,15,ASLtoATL _bpos,[0,0,0],1,1.275,1.0,0.0,[1],[[1,0,0,1]],[0],0.0,2.0,"","",""]; + + _explosions pushBack [_refExp, _bpos, _hit, _distance, _indirectHitRange/4, _depth]; + + }; + if(count _explosions > (_radi*2)/_depth) exitWith {}; + } forEach _buckets; + // _can = "Land_Bricks_V4_F" createVehicle (ASLtoATL _pos); + // _dirvec = _pos vectorFromTo ((ATLtoASL (player modelToWorldVisual (player selectionPosition "Spine3")))); + // _dirvec = _dirvec vectorMultiply 100; + // _can setVelocity _dirvec; + [DFUNC(doExplosions), 0, [_explosions, 0]] call cba_fnc_addPerFrameHandler; + [(_this select 1)] call cba_fnc_removePerFrameHandler; +}; diff --git a/addons/frag/functions/fnc_frago.sqf b/addons/frag/functions/fnc_frago.sqf index 1b737dc70d..8c97baa209 100644 --- a/addons/frag/functions/fnc_frago.sqf +++ b/addons/frag/functions/fnc_frago.sqf @@ -111,8 +111,9 @@ _fragArcs set[360, 0]; player sideChat format["_fragRange: %1", _fragRange]; player sideChat format["_objects: %1", _objects]; #endif -_doRandom = false; +_doRandom = true; if(_isArmed && (count _objects) > 0) then { + [_lastPos, _shellType] call FUNC(doReflections); { //if(random(1) > 0.5) then { _target = _x; @@ -189,7 +190,7 @@ if(_isArmed && (count _objects) > 0) then { if(_fragCount > MAX_FRAG_COUNT) exitWith {}; } forEach _objects; if(_fragCount > MAX_FRAG_COUNT) exitWith {}; - _randomCount = (ceil((MAX_FRAG_COUNT-_fragCount)*0.1)) max 0; + _randomCount = ((ceil((MAX_FRAG_COUNT-_fragCount)*0.1)) max 0)+20; _sectorSize = 360 / (_randomCount max 1); // _doRandom = false; if(_doRandom) then { @@ -222,6 +223,7 @@ if(_isArmed && (count _objects) > 0) then { _fragCount = _fragCount + 1; }; }; + }; // #ifdef DEBUG_MODE_FULL // player sideChat format["total frags: %1", GVAR(TOTALFRAGS)]; From 114d66af7e375fc248c92bb769ebb22e3a2b5e86 Mon Sep 17 00:00:00 2001 From: Nou Date: Tue, 14 Apr 2015 13:00:57 -0700 Subject: [PATCH 002/140] Do it every frame, no need for delay. --- addons/frag/functions/fnc_doReflections.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/frag/functions/fnc_doReflections.sqf b/addons/frag/functions/fnc_doReflections.sqf index 844ccb4c9b..911203dc5f 100644 --- a/addons/frag/functions/fnc_doReflections.sqf +++ b/addons/frag/functions/fnc_doReflections.sqf @@ -18,5 +18,5 @@ if(_depth <= 2) then { _testParams = [_pos, [_indirectHitRange, _indirectHit], [], [], -4, _depth, 0]; - [DFUNC(findReflections), 0.005, _testParams] call cba_fnc_addPerFrameHandler; + [DFUNC(findReflections), 0, _testParams] call cba_fnc_addPerFrameHandler; }; From 15ac5ec7b8ad71dff640c0164c7453c068472605 Mon Sep 17 00:00:00 2001 From: Nou Date: Tue, 14 Apr 2015 16:33:47 -0700 Subject: [PATCH 003/140] Two explosions processed per-frame. --- addons/frag/functions/fnc_doExplosions.sqf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/frag/functions/fnc_doExplosions.sqf b/addons/frag/functions/fnc_doExplosions.sqf index f2c20c2f1e..749c4bd2ec 100644 --- a/addons/frag/functions/fnc_doExplosions.sqf +++ b/addons/frag/functions/fnc_doExplosions.sqf @@ -5,7 +5,7 @@ private ["_params", "_explosions", "_index", "_i", "_exp", "_refExp", "_bpos", " _params = _this select 0; _explosions = _params select 0; _index = _params select 1; -for "_i" from _index to ((_index+1) min (count _explosions)) do { +for "_i" from _index to ((_index+2) min (count _explosions)) do { _exp = _explosions select _i; _refExp = _exp select 0; _bpos = _exp select 1; @@ -18,7 +18,7 @@ for "_i" from _index to ((_index+1) min (count _explosions)) do { // [_bpos, _refExp, _depth] call FUNC(doReflections); // }; }; -_index = _index + 1; +_index = _index + 2; if(_index >= (count _explosions)) then { [(_this select 1)] call cba_fnc_removePerFrameHandler; } else { From 54dcbb9ef4287fc1814b2556028021f769151369 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Tue, 12 May 2015 22:15:52 -0500 Subject: [PATCH 004/140] FCS - Privates --- addons/fcs/functions/fnc_getAngle.sqf | 4 ++-- addons/fcs/functions/fnc_handleAirBurstAmmunitionPFH.sqf | 3 +++ addons/fcs/functions/fnc_keyUp.sqf | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/fcs/functions/fnc_getAngle.sqf b/addons/fcs/functions/fnc_getAngle.sqf index 03024d8b98..91150c110d 100644 --- a/addons/fcs/functions/fnc_getAngle.sqf +++ b/addons/fcs/functions/fnc_getAngle.sqf @@ -19,7 +19,7 @@ #include "script_component.hpp" #define PRECISION 0.1 -private ["_distance","_angleTarget","_maxElev","_initSpeed","_airFriction","_timeToLive","_timeToLive","_simulationStep","_angle","_posTargetX","_posTargetY","_posX","_posY","_velocityX","_velocityY","_velocityMagnitude"]; +private ["_distance", "_angleTarget", "_maxElev", "_initSpeed", "_airFriction", "_timeToLive", "_simulationStep", "_angle1", "_angle2", "_it2", "_f1", "_f2", "_temp", "_it1", "_angle"]; _distance = _this select 0; _angleTarget = _this select 1; @@ -32,7 +32,7 @@ _simulationStep = _this select 6; if (_simulationStep == 0) exitWith {_angleTarget}; FUNC(traceBullet) = { - private ["_distance", "_angleTarget", "_maxElev", "_initSpeed", "_airFriction", "_timeToLive", "_simulationStep", "_angle", "_posTargetX", "_posTargetY", "_posX", "_posY", "_velocityX", "_velocityY", "_velocityMagnitude"]; + private ["_distance", "_angleTarget", "_maxElev", "_initSpeed", "_airFriction", "_timeToLive", "_simulationStep", "_angle", "_posTargetX", "_posTargetY", "_posX", "_posY", "_velocityX", "_velocityY", "_velocityMagnitude", "_i"]; _distance = _this select 0; _angleTarget = _this select 1; diff --git a/addons/fcs/functions/fnc_handleAirBurstAmmunitionPFH.sqf b/addons/fcs/functions/fnc_handleAirBurstAmmunitionPFH.sqf index 31c2540790..899cf0da76 100644 --- a/addons/fcs/functions/fnc_handleAirBurstAmmunitionPFH.sqf +++ b/addons/fcs/functions/fnc_handleAirBurstAmmunitionPFH.sqf @@ -1,4 +1,7 @@ // by commy2 +#include "script_component.hpp" + +private ["_vehicle", "_projectile", "_zeroing", "_position", "_subMunition"]; _vehicle = _this select 0 select 0; _projectile = _this select 0 select 1; diff --git a/addons/fcs/functions/fnc_keyUp.sqf b/addons/fcs/functions/fnc_keyUp.sqf index a7bf8defe5..4e28f26a20 100644 --- a/addons/fcs/functions/fnc_keyUp.sqf +++ b/addons/fcs/functions/fnc_keyUp.sqf @@ -12,7 +12,7 @@ #include "script_component.hpp" -private ["_vehicle", "_turret", "_turretConfig", "_distance", "_weapons", "_magazines", "_showHint", "_playSound"]; +private ["_vehicle", "_turret", "_turretConfig", "_distance", "_weapons", "_magazines", "_showHint", "_playSound", "_i"]; _vehicle = _this select 0; _turret = _this select 1; From 553942bbc7b523b93b3c580183d0f2517192303b Mon Sep 17 00:00:00 2001 From: jaynus Date: Wed, 13 May 2015 14:33:14 -0700 Subject: [PATCH 005/140] Initial commit of frag/spalling optimization rewrite. Now tracks in single PFH, with index-based referencing instead of searches. TODO: Break spall calculation up to multiple frames. Needs testing. --- addons/frag/ACE_Settings.hpp | 11 ++- addons/frag/XEH_postInit.sqf | 4 +- addons/frag/XEH_preInit.sqf | 12 +++- addons/frag/functions/fnc_addPfhRound.sqf | 71 +++++++++++++++++++ addons/frag/functions/fnc_doSpall.sqf | 2 + addons/frag/functions/fnc_fired.sqf | 53 +------------- addons/frag/functions/fnc_masterPFH.sqf | 46 ++++++++++++ ...nc_trackFragRound.sqf => fnc_pfhRound.sqf} | 23 +++--- addons/frag/functions/fnc_removePfhRound.sqf | 9 +++ addons/frag/stringtable.xml | 26 ++++--- 10 files changed, 175 insertions(+), 82 deletions(-) create mode 100644 addons/frag/functions/fnc_addPfhRound.sqf create mode 100644 addons/frag/functions/fnc_masterPFH.sqf rename addons/frag/functions/{fnc_trackFragRound.sqf => fnc_pfhRound.sqf} (54%) create mode 100644 addons/frag/functions/fnc_removePfhRound.sqf diff --git a/addons/frag/ACE_Settings.hpp b/addons/frag/ACE_Settings.hpp index b160a127f3..6a782de2f9 100644 --- a/addons/frag/ACE_Settings.hpp +++ b/addons/frag/ACE_Settings.hpp @@ -1,7 +1,14 @@ class ACE_Settings { class GVAR(enabled) { - displayName = "Frag System"; - description = "Enables the shrapnel system for explosives"; + displayName = "$STR_ACE_frag_EnableFrag"; + description = "$STR_ACE_frag_EnableFrag_Desc"; + typeName = "BOOL"; + value = 1; + }; + + class GVAR(spallEnabled) { + displayName = "$STR_ACE_frag_EnableSpall"; + description = "$STR_ACE_frag_EnableSpall_Desc"; typeName = "BOOL"; value = 1; }; diff --git a/addons/frag/XEH_postInit.sqf b/addons/frag/XEH_postInit.sqf index 6c8d64d1fb..0c6a1845b6 100644 --- a/addons/frag/XEH_postInit.sqf +++ b/addons/frag/XEH_postInit.sqf @@ -2,4 +2,6 @@ if(isServer) then { [QGVAR(frag_eh), { _this call FUNC(frago); }] call ace_common_fnc_addEventHandler; -}; \ No newline at end of file +}; + +[FUNC(masterPFH), 0, []] call CBA_fnc_addPerFrameHandler; \ No newline at end of file diff --git a/addons/frag/XEH_preInit.sqf b/addons/frag/XEH_preInit.sqf index 906a696ebf..4d1afcc385 100644 --- a/addons/frag/XEH_preInit.sqf +++ b/addons/frag/XEH_preInit.sqf @@ -6,11 +6,9 @@ PREP(doSpall); PREP(fired); PREP(frago); PREP(spallTrack); -PREP(trackFragRound); GVAR(blackList) = []; GVAR(traceFrags) = false; -GVAR(trackedObjects) = []; GVAR(TOTALFRAGS) = 0; @@ -32,4 +30,14 @@ PREP(startTracing); PREP(stopTracing); PREP(trackTrace); +// New tracking mechanisms +PREP(masterPFH); +PREP(pfhRound); +PREP(addPfhRound); +PREP(removePfhRound); // THIS SHOULD ABE USED SPARINGLY + +GVAR(objects) = []; +GVAR(objectTypes) = []; +GVAR(arguments) = []; + ADDON = true; diff --git a/addons/frag/functions/fnc_addPfhRound.sqf b/addons/frag/functions/fnc_addPfhRound.sqf new file mode 100644 index 0000000000..81454edf97 --- /dev/null +++ b/addons/frag/functions/fnc_addPfhRound.sqf @@ -0,0 +1,71 @@ +#include "script_component.hpp" + +private ["_enabled", "_gun", "_type", "_round", "_doFragTrack", "_doSpall", "_spallTrack", "_spallTrackID"]; + +if (!GVAR(enabled)) exitWith {}; + +_gun = _this select 0; +_type = _this select 1; +_round = _this select 2; + +_enabled = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(enabled)); +if(_enabled < 1) exitWith {}; + +if(_round in GVAR(blackList)) exitWith { + GVAR(blackList) = GVAR(blackList) - [_round]; +}; + +_doFragTrack = false; +if(_gun == ACE_player) then { + _doFragTrack = true; +} else { + if((gunner _gun) == ACE_player) then { + _doFragTrack = true; + } else { + if(local _gun && {!(isPlayer (gunner _gun))} && {!(isPlayer _gun)}) then { + _doFragTrack = true; + }; + }; +}; +if(GVAR(spallEnabled)) then { + if(GVAR(spallIsTrackingCount) <= 0) then { + GVAR(spallHPData) = []; + }; + if(GVAR(spallIsTrackingCount) > 5) then { + // ACE_player sideChat "LIMT!"; + _doSpall = false; + } else { + GVAR(spallIsTrackingCount) = GVAR(spallIsTrackingCount) + 1; + }; +}; +// ACE_player sideChat format["c: %1", GVAR(spallIsTrackingCount)]; + +#ifdef DEBUG_MODE_FULL +[ACE_player, _round, [1,0,0,1]] call FUNC(addTrack); +#endif + +// We only do the single track object check here. +if(_doFragTrack && alive _round && {!(_round in GVAR(objects))} ) then { + _spallTrack = []; + _spallTrackID = []; + + private["_args"]; + _args = [_round, (getPosASL _round), (velocity _round), _type, time, _gun, _doSpall, _spallTrack, _spallTrackID, + (getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(skip))), + (getNumber (configFile >> "CfgAmmo" >> _type >> "explosive")), + (getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange")), + (getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(force))), + (getNumber(configFile >> "CfgAmmo" >> _type >> "indirecthit")*(sqrt((getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange"))))) + ]; + + GVAR(objects) pushBack _round; + GVAR(arguments) pushBack _args; + + if(_doSpall) then { + [_round, 2, _spallTrack, _spallTrackID] call FUNC(spallTrack); + }; + // ACE_player sideChat "WTF2"; +}; + + + diff --git a/addons/frag/functions/fnc_doSpall.sqf b/addons/frag/functions/fnc_doSpall.sqf index d2e64dbbfb..717b629e53 100644 --- a/addons/frag/functions/fnc_doSpall.sqf +++ b/addons/frag/functions/fnc_doSpall.sqf @@ -124,6 +124,7 @@ if(_alive || {_caliber >= 2.5} || {(_explosive > 0 && {_idh >= 1})}) then { _fragment = (_fragTypes select _fragType) createVehicleLocal [0,0,10000]; _fragment setPosASL _spallPos; _fragment setVelocity _spallFragVect; + if(GVAR(traceFrags)) then { [ACE_player, _fragment, [1,0.5,0,1]] call FUNC(addTrack); }; @@ -145,6 +146,7 @@ if(_alive || {_caliber >= 2.5} || {(_explosive > 0 && {_idh >= 1})}) then { _fragment = (_fragTypes select _fragType) createVehicleLocal [0,0,10000]; _fragment setPosASL _spallPos; _fragment setVelocity _spallFragVect; + if(GVAR(traceFrags)) then { [ACE_player, _fragment, [1,0,0,1]] call FUNC(addTrack); }; diff --git a/addons/frag/functions/fnc_fired.sqf b/addons/frag/functions/fnc_fired.sqf index 9b89e40897..15a878d112 100644 --- a/addons/frag/functions/fnc_fired.sqf +++ b/addons/frag/functions/fnc_fired.sqf @@ -1,58 +1,9 @@ #include "script_component.hpp" - -private ["_enabled", "_gun", "_type", "_round", "_doFragTrack", "_doSpall", "_spallTrack", "_spallTrackID"]; - -if (!GVAR(enabled)) exitWith {}; +private["_gun", "_type", "_round"]; _gun = _this select 0; _type = _this select 4; _round = _this select 6; -_enabled = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(enabled)); -if(_enabled < 1) exitWith {}; +[_gun, _type, _round] call FUNC(addPfhRound); -if(_round in GVAR(blackList)) exitWith { - GVAR(blackList) = GVAR(blackList) - [_round]; -}; - - -_doFragTrack = false; -if(_gun == ACE_player) then { - _doFragTrack = true; -} else { - if((gunner _gun) == ACE_player) then { - _doFragTrack = true; - } else { - if(local _gun && {!(isPlayer (gunner _gun))} && {!(isPlayer _gun)}) then { - _doFragTrack = true; - }; - }; -}; -_doSpall = false; -if(_doSpall) then { - if(GVAR(spallIsTrackingCount) <= 0) then { - GVAR(spallHPData) = []; - }; - if(GVAR(spallIsTrackingCount) > 5) then { - // ACE_player sideChat "LIMT!"; - _doSpall = false; - } else { - GVAR(spallIsTrackingCount) = GVAR(spallIsTrackingCount) + 1; - }; -}; -// ACE_player sideChat format["c: %1", GVAR(spallIsTrackingCount)]; - -#ifdef DEBUG_MODE_FULL -[ACE_player, _round, [1,0,0,1]] call FUNC(addTrack); -#endif - -if(_doFragTrack && alive _round) then { - GVAR(trackedObjects) pushBack _round; - _spallTrack = []; - _spallTrackID = []; - [DFUNC(trackFragRound), 0, [_round, (getPosASL _round), (velocity _round), _type, time, _gun, _doSpall, _spallTrack, _spallTrackID]] call cba_fnc_addPerFrameHandler; - if(_doSpall) then { - [_round, 2, _spallTrack, _spallTrackID] call FUNC(spallTrack); - }; - // ACE_player sideChat "WTF2"; -}; diff --git a/addons/frag/functions/fnc_masterPFH.sqf b/addons/frag/functions/fnc_masterPFH.sqf new file mode 100644 index 0000000000..d511325e15 --- /dev/null +++ b/addons/frag/functions/fnc_masterPFH.sqf @@ -0,0 +1,46 @@ +/* + * Author: jaynus + * + * Master single PFH abstraction for all rounds being tracked by frag/spall + * + * Arguments: + * + * + * Return Value: + * None + */ +#include "script_component.hpp" +PARAMS_2(_pfhArgs,_handle); + +if (!GVAR(enabled)) exitWith {}; + +private["_gcIndex"]; +_gcIndex = []; +{ + private["_object", "_args"]; + _object = _x; + if(!isNil "_object") then { + if(isNull _object) then { + _gcIndex pushBack _forEachIndex; + } else { + _args = GVAR(arguments) select _forEachIndex; + + _args call FUNC(pfhRound); + }; + + if(!alive _object) then { + _gcIndex pushBack _forEachIndex; + }; + }; +} forEach GVAR(objects); + +// clean up dead object references +private["_deletionCount", "_deleteIndex"]; +_deletionCount = 0; +{ + _deleteIndex = _gcIndex - _deletionCount; + GVAR(objects) deleteAt _deleteIndex; + GVAR(arguments) deleteAt _deleteIndex; + + _deletionCount = _deletionCount + 1; +} forEach _gcIndex; \ No newline at end of file diff --git a/addons/frag/functions/fnc_trackFragRound.sqf b/addons/frag/functions/fnc_pfhRound.sqf similarity index 54% rename from addons/frag/functions/fnc_trackFragRound.sqf rename to addons/frag/functions/fnc_pfhRound.sqf index 8db68c99e8..df6f618ac5 100644 --- a/addons/frag/functions/fnc_trackFragRound.sqf +++ b/addons/frag/functions/fnc_pfhRound.sqf @@ -1,4 +1,3 @@ -//fnc_trackFragRound.sqf #include "script_component.hpp" private ["_params", "_round", "_lastPos", "_lastVel", "_type", "_time", "_doSpall", "_spallTrack", "_foundObjectHPIds", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"]; _params = _this select 0; @@ -10,20 +9,17 @@ _time = _params select 4; _doSpall = _params select 6; _spallTrack = _params select 7; _foundObjectHPIds = _params select 8; +_skip = _params select 9; +_explosive = _params select 10; +_indirectRange = _params select 11; +_force = _params select 12; +_fragPower = _params select 13; if (!alive _round) then { - [_this select 1] call cba_fnc_removePerFrameHandler; - if(_time != time && {_round in GVAR(trackedObjects)} && {!(_round in GVAR(blackList))}) then { - GVAR(trackedObjects) = GVAR(trackedObjects) - [_round]; - _skip = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(skip)); + if(_time != time && {!(_round in GVAR(blackList))}) then { if(_skip == 0) then { - _explosive = getNumber (configFile >> "CfgAmmo" >> _type >> "explosive"); - _indirectRange = getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange"); - _force = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(force)); - _fragPower = getNumber(configFile >> "CfgAmmo" >> _type >> "indirecthit")*(sqrt(_indirectRange)); if((_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}) || {_force == 1} ) then { [QGVAR(frag_eh), _params] call ace_common_fnc_serverEvent; - GVAR(trackedObjects) = GVAR(trackedObjects) - [_round]; }; }; }; @@ -37,11 +33,8 @@ if (!alive _round) then { } forEach _spallTrack; }; } else { - if(!(_round in GVAR(trackedObjects)) || {_round in GVAR(blackList)}) then { - [_this select 1] call cba_fnc_removePerFrameHandler; - if(_round in GVAR(blackList)) then { - GVAR(blackList) = GVAR(blackList) - [_round]; - }; + if(_round in GVAR(blackList)) exitWith { + [_round] call FUNC(removePfhRound); }; _params set[1, (getPosASL _round)]; diff --git a/addons/frag/functions/fnc_removePfhRound.sqf b/addons/frag/functions/fnc_removePfhRound.sqf new file mode 100644 index 0000000000..7fe3994d55 --- /dev/null +++ b/addons/frag/functions/fnc_removePfhRound.sqf @@ -0,0 +1,9 @@ +#include "script_component.hpp" + +// THIS FUNCTION SHOULD NOT BE USED BECAUSE IT CAUSES AN SEARCH AND REBUILD + +if(_round in GVAR(blackList)) then { + GVAR(blackList) = GVAR(blackList) - [_round]; +}; + +GVAR(objects) = GVAR(objects) - [_round]; \ No newline at end of file diff --git a/addons/frag/stringtable.xml b/addons/frag/stringtable.xml index e7ebb7c1bf..e267685869 100644 --- a/addons/frag/stringtable.xml +++ b/addons/frag/stringtable.xml @@ -1,17 +1,21 @@  - - Disable Fragmentation - Keine Schrapnelle - Zakázat fragmentaci granátů - Desactivar fragmentación - Wyłącz fragmentację odłamków - Выключить разлёт осколков - Désactive la fragmentation - Repeszek letiltása - Disattiva la frammentazione - Desabilitar Fragmentação + + Fragmentation Simulation + + + + Enable the ACE Fragmentation Simulation + + + + Spalling Simulation + + + + Enable the ACE Spalling Simulation + From 58a55313cdc89fb481d9146995312ffa7bb5fd11 Mon Sep 17 00:00:00 2001 From: jaynus Date: Wed, 13 May 2015 17:06:10 -0700 Subject: [PATCH 006/140] Changed: Entire frag system re-optimized to a single tracking/GC index-based PFH. Changed: Spalling calculations now throttled across frames and limited; accurate but performant Changed: All lookups are now index-based on a global projectiles array. This reduced runtime dramatically for all fragmentation. --- addons/frag/ACE_Settings.hpp | 24 ++++++++++-- addons/frag/CfgAmmo.hpp | 4 +- addons/frag/CfgAmmoReflections.hpp | 1 - addons/frag/XEH_postInit.sqf | 5 +++ addons/frag/XEH_preInit.sqf | 3 +- addons/frag/functions/fnc_addPfhRound.sqf | 32 ++++++++------- addons/frag/functions/fnc_doSpall.sqf | 4 -- addons/frag/functions/fnc_frago.sqf | 11 ++---- addons/frag/functions/fnc_masterPFH.sqf | 36 +++++++++++------ addons/frag/functions/fnc_pfhRound.sqf | 48 ++++++++++++----------- addons/frag/functions/fnc_spallTrack.sqf | 2 +- addons/frag/stringtable.xml | 22 +++++++++-- 12 files changed, 120 insertions(+), 72 deletions(-) diff --git a/addons/frag/ACE_Settings.hpp b/addons/frag/ACE_Settings.hpp index 6a782de2f9..bbf0398cfb 100644 --- a/addons/frag/ACE_Settings.hpp +++ b/addons/frag/ACE_Settings.hpp @@ -1,15 +1,33 @@ class ACE_Settings { - class GVAR(enabled) { + class GVAR(Enabled) { displayName = "$STR_ACE_frag_EnableFrag"; description = "$STR_ACE_frag_EnableFrag_Desc"; typeName = "BOOL"; value = 1; }; - - class GVAR(spallEnabled) { + class GVAR(SpallEnabled) { displayName = "$STR_ACE_frag_EnableSpall"; description = "$STR_ACE_frag_EnableSpall_Desc"; typeName = "BOOL"; value = 1; }; + class GVAR(maxTrack) { + displayName = "$STR_ACE_frag_MaxTrack"; + description = "$STR_ACE_frag_MaxTrack_Desc"; + typeName = "SCALAR"; + value = 500; + }; + class GVAR(MaxTrackPerFrame) { + displayName = "$STR_ACE_frag_MaxTrackPerFrame"; + description = "$STR_ACE_frag_MaxTrackPerFrame_Desc"; + typeName = "SCALAR"; + value = 50; + }; + + class GVAR(EnableDebugTrace) { + displayName = "$STR_ACE_frag_EnableDebugTrace"; + description = "$STR_ACE_frag_EnableDebugTrace_Desc"; + typeName = "BOOL"; + value = 0; + }; }; diff --git a/addons/frag/CfgAmmo.hpp b/addons/frag/CfgAmmo.hpp index 7f4c4b38b3..41734d2806 100644 --- a/addons/frag/CfgAmmo.hpp +++ b/addons/frag/CfgAmmo.hpp @@ -9,8 +9,6 @@ class CfgAmmo { // GVAR(skip) = 1; //}; - #include "CfgAmmoReflections.hpp" - class Bo_GBU12_LGB; class ACE_GBU12 : Bo_GBU12_LGB { GVAR(enabled) = 1; @@ -473,4 +471,6 @@ class CfgAmmo { class ACE_frag_spall_huge: ACE_frag_huge { timeToLive = 0.3; }; + + #include "CfgAmmoReflections.hpp" }; diff --git a/addons/frag/CfgAmmoReflections.hpp b/addons/frag/CfgAmmoReflections.hpp index 8e481a9cd0..f59d67f89a 100644 --- a/addons/frag/CfgAmmoReflections.hpp +++ b/addons/frag/CfgAmmoReflections.hpp @@ -1,7 +1,6 @@ //CfgAmmoReflections.hpp #define ACE_EXPLOSION_REFLECTION(range, hit) class ace_explosion_reflection_##range##_##hit : ace_explosion_reflection_base { indirectHitRange = range; indirectHit = hit; dangerRadiusHit = range*3; suppressionRadiusHit = range*2; }; -class Sh_120mm_HE; class ace_explosion_reflection_base : Sh_120mm_HE { CraterWaterEffects = ""; CraterEffects = ""; diff --git a/addons/frag/XEH_postInit.sqf b/addons/frag/XEH_postInit.sqf index 0c6a1845b6..95c921df64 100644 --- a/addons/frag/XEH_postInit.sqf +++ b/addons/frag/XEH_postInit.sqf @@ -1,5 +1,10 @@ #include "script_component.hpp" +if(GVAR(EnableDebugTrace) && !isMultiplayer) then { + GVAR(traceFrags) = true; + GVAR(autoTrace) = true; +}; + if(isServer) then { [QGVAR(frag_eh), { _this call FUNC(frago); }] call ace_common_fnc_addEventHandler; }; diff --git a/addons/frag/XEH_preInit.sqf b/addons/frag/XEH_preInit.sqf index a2d1e38c1b..cdd9342ffd 100644 --- a/addons/frag/XEH_preInit.sqf +++ b/addons/frag/XEH_preInit.sqf @@ -15,7 +15,7 @@ GVAR(TOTALFRAGS) = 0; GVAR(spallHPData) = []; GVAR(spallIsTrackingCount) = 0; -GVAR(autoTrace) = true; +GVAR(autoTrace) = false; GVAR(traceID) = -1; GVAR(traces) = []; GVAR(tracesStarted) = false; @@ -43,6 +43,7 @@ PREP(doExplosions); PREP(doReflections); +GVAR(lastIterationIndex) = 0; GVAR(objects) = []; GVAR(objectTypes) = []; GVAR(arguments) = []; diff --git a/addons/frag/functions/fnc_addPfhRound.sqf b/addons/frag/functions/fnc_addPfhRound.sqf index 81454edf97..7530b8f062 100644 --- a/addons/frag/functions/fnc_addPfhRound.sqf +++ b/addons/frag/functions/fnc_addPfhRound.sqf @@ -1,20 +1,21 @@ +//#define DEBUG_MODE_FULL #include "script_component.hpp" -private ["_enabled", "_gun", "_type", "_round", "_doFragTrack", "_doSpall", "_spallTrack", "_spallTrackID"]; +private ["_enabled","_doFragTrack", "_doSpall", "_spallTrack", "_spallTrackID"]; +PARAMS_3(_gun,_type,_round); if (!GVAR(enabled)) exitWith {}; -_gun = _this select 0; -_type = _this select 1; -_round = _this select 2; - -_enabled = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(enabled)); -if(_enabled < 1) exitWith {}; +//_enabled = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(enabled)); +//if(_enabled < 1) exitWith {}; if(_round in GVAR(blackList)) exitWith { GVAR(blackList) = GVAR(blackList) - [_round]; }; +// Exit on max track +if( (count GVAR(objects)) > GVAR(MaxTrack)) exitWith { }; + _doFragTrack = false; if(_gun == ACE_player) then { _doFragTrack = true; @@ -27,7 +28,7 @@ if(_gun == ACE_player) then { }; }; }; -if(GVAR(spallEnabled)) then { +if(GVAR(SpallEnabled)) then { if(GVAR(spallIsTrackingCount) <= 0) then { GVAR(spallHPData) = []; }; @@ -40,12 +41,15 @@ if(GVAR(spallEnabled)) then { }; // ACE_player sideChat format["c: %1", GVAR(spallIsTrackingCount)]; -#ifdef DEBUG_MODE_FULL -[ACE_player, _round, [1,0,0,1]] call FUNC(addTrack); -#endif +if(GVAR(autoTrace)) then { + [ACE_player, _round, [1,0,0,1]] call FUNC(addTrack); +}; // We only do the single track object check here. -if(_doFragTrack && alive _round && {!(_round in GVAR(objects))} ) then { +// We should do an {!(_round in GVAR(objects))} +// But we leave that out here for optimization. So this cannot be a framework function +// Otherwise, it should only be added once and from the FiredEH +if(_doFragTrack && alive _round) then { _spallTrack = []; _spallTrackID = []; @@ -57,12 +61,12 @@ if(_doFragTrack && alive _round && {!(_round in GVAR(objects))} ) then { (getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(force))), (getNumber(configFile >> "CfgAmmo" >> _type >> "indirecthit")*(sqrt((getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange"))))) ]; - + TRACE_1("Initializing track", _round); GVAR(objects) pushBack _round; GVAR(arguments) pushBack _args; if(_doSpall) then { - [_round, 2, _spallTrack, _spallTrackID] call FUNC(spallTrack); + [_round, 1, _spallTrack, _spallTrackID] call FUNC(spallTrack); }; // ACE_player sideChat "WTF2"; }; diff --git a/addons/frag/functions/fnc_doSpall.sqf b/addons/frag/functions/fnc_doSpall.sqf index 717b629e53..1e8e87bcb3 100644 --- a/addons/frag/functions/fnc_doSpall.sqf +++ b/addons/frag/functions/fnc_doSpall.sqf @@ -1,14 +1,10 @@ //fnc_doSpall.sqf #include "script_component.hpp" -#ifdef DEBUG_MODE_FULL - GVAR(traceFrags) = true; -#endif // ACE_player sideChat "WAAAAAAAAAAAAAAAAAAAAA"; private ["_params", "_hitData", "_initialData", "_hpData", "_object", "_foundObjects", "_index", "_foundObjecsts", "_roundType", "_round", "_caliber", "_explosive", "_idh", "_alive", "_exit", "_vm", "_velocity", "_oldVelocity", "_curVelocity", "_diff", "_polar", "_unitDir", "_spallPos", "_pos1", "_i", "_pos2", "_blah", "_data", "_spallPolar", "_warn", "_c", "_m", "_k", "_gC", "_fragPower", "_fragTypes", "_spread", "_spallCount", "_elev", "_dir", "_vel", "_spallFragVect", "_fragType", "_fragment", "_pos"]; _params = _this select 0; -[(_this select 1)] call cba_fnc_removePerFrameHandler; _hitData = _params select 0; _initialData = GVAR(spallHPData) select (_hitData select 0); _hpData = (_hitData select 1) select (_params select 1); diff --git a/addons/frag/functions/fnc_frago.sqf b/addons/frag/functions/fnc_frago.sqf index 415b75e790..5b5cf89bbe 100644 --- a/addons/frag/functions/fnc_frago.sqf +++ b/addons/frag/functions/fnc_frago.sqf @@ -163,11 +163,8 @@ if(_isArmed && (count _objects) > 0) then { _fragObj setPosASL _lastPos; _fragObj setVectorDir _vec; _fragObj setVelocity _vel; - #ifdef DEBUG_MODE_FULL - GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1; - GVAR(traceFrags) = true; - #endif if(GVAR(traceFrags)) then { + GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1; [ACE_player, _fragObj, [1,0,0,1]] call FUNC(addTrack); }; _fragCount = _fragCount + 1; @@ -200,11 +197,9 @@ if(_isArmed && (count _objects) > 0) then { _fragObj setPosASL _lastPos; _fragObj setVectorDir _vec; _fragObj setVelocity _vel; - #ifdef DEBUG_MODE_FULL - GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1; - GVAR(traceFrags) = true; - #endif + if(GVAR(traceFrags)) then { + GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1; [ACE_player, _fragObj, [1,0.5,0,1]] call FUNC(addTrack); }; _fragCount = _fragCount + 1; diff --git a/addons/frag/functions/fnc_masterPFH.sqf b/addons/frag/functions/fnc_masterPFH.sqf index d511325e15..4e81c4c609 100644 --- a/addons/frag/functions/fnc_masterPFH.sqf +++ b/addons/frag/functions/fnc_masterPFH.sqf @@ -9,36 +9,48 @@ * Return Value: * None */ +//#define DEBUG_MODE_FULL #include "script_component.hpp" -PARAMS_2(_pfhArgs,_handle); +//PARAMS_2(_pfhArgs,_handle); if (!GVAR(enabled)) exitWith {}; private["_gcIndex"]; _gcIndex = []; -{ + +_iter = 0; +while { (count GVAR(objects)) > 0 && { _iter < GVAR(MaxTrackPerFrame) } } do { private["_object", "_args"]; - _object = _x; + if(GVAR(lastIterationIndex) >= (count GVAR(objects))) then { + GVAR(lastIterationIndex) = 0; + }; + _object = GVAR(objects) select GVAR(lastIterationIndex); + if(!isNil "_object") then { if(isNull _object) then { - _gcIndex pushBack _forEachIndex; + _gcIndex pushBack GVAR(lastIterationIndex); } else { - _args = GVAR(arguments) select _forEachIndex; + _args = GVAR(arguments) select GVAR(lastIterationIndex); - _args call FUNC(pfhRound); - }; - - if(!alive _object) then { - _gcIndex pushBack _forEachIndex; + if(!(_args call FUNC(pfhRound))) then { + _gcIndex pushBack GVAR(lastIterationIndex); // Add it to the GC if it returns false + }; + // If its not alive anymore, remove it from the queue, it already ran once on dead + if(!alive _object) then { + _gcIndex pushBack GVAR(lastIterationIndex); + }; }; }; -} forEach GVAR(objects); + _iter = _iter + 1; + GVAR(lastIterationIndex) = GVAR(lastIterationIndex) + 1; +}; // clean up dead object references private["_deletionCount", "_deleteIndex"]; _deletionCount = 0; { - _deleteIndex = _gcIndex - _deletionCount; + TRACE_1("GC Projectile", _x); + _deleteIndex = _x - _deletionCount; GVAR(objects) deleteAt _deleteIndex; GVAR(arguments) deleteAt _deleteIndex; diff --git a/addons/frag/functions/fnc_pfhRound.sqf b/addons/frag/functions/fnc_pfhRound.sqf index df6f618ac5..8cc9457842 100644 --- a/addons/frag/functions/fnc_pfhRound.sqf +++ b/addons/frag/functions/fnc_pfhRound.sqf @@ -1,25 +1,28 @@ #include "script_component.hpp" -private ["_params", "_round", "_lastPos", "_lastVel", "_type", "_time", "_doSpall", "_spallTrack", "_foundObjectHPIds", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"]; -_params = _this select 0; -_round = _params select 0; -_lastPos = _params select 1; -_lastVel = _params select 2; -_type = _params select 3; -_time = _params select 4; -_doSpall = _params select 6; -_spallTrack = _params select 7; -_foundObjectHPIds = _params select 8; -_skip = _params select 9; -_explosive = _params select 10; -_indirectRange = _params select 11; -_force = _params select 12; -_fragPower = _params select 13; +private ["_round", "_lastPos", "_lastVel", "_type", "_time", "_doSpall", "_spallTrack", "_foundObjectHPIds", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"]; +_round = _this select 0; +_lastPos = _this select 1; +_lastVel = _this select 2; +_type = _this select 3; +_time = _this select 4; +_doSpall = _this select 6; +_spallTrack = _this select 7; +_foundObjectHPIds = _this select 8; +_skip = _this select 9; +_explosive = _this select 10; +_indirectRange = _this select 11; +_force = _this select 12; +_fragPower = _this select 13; + +if(_round in GVAR(blackList)) exitWith { + false +}; if (!alive _round) then { - if(_time != time && {!(_round in GVAR(blackList))}) then { + if(_time != time) then { if(_skip == 0) then { if((_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}) || {_force == 1} ) then { - [QGVAR(frag_eh), _params] call ace_common_fnc_serverEvent; + [QGVAR(frag_eh), _this] call ace_common_fnc_serverEvent; }; }; }; @@ -33,13 +36,14 @@ if (!alive _round) then { } forEach _spallTrack; }; } else { - if(_round in GVAR(blackList)) exitWith { - [_round] call FUNC(removePfhRound); - }; - + _params set[1, (getPosASL _round)]; _params set[2, (velocity _round)]; if(_doSpall) then { - [_round, 1, _spallTrack, _foundObjectHPIds] call FUNC(spallTrack); + private["_scale"]; + _scale = ( (count GVAR(objects)) / GVAR(MaxTrackPerFrame) ) max 0.1; + [_round, _scale, _spallTrack, _foundObjectHPIds] call FUNC(spallTrack); }; }; + +true \ No newline at end of file diff --git a/addons/frag/functions/fnc_spallTrack.sqf b/addons/frag/functions/fnc_spallTrack.sqf index 4b7a06bc65..afe4bc1931 100644 --- a/addons/frag/functions/fnc_spallTrack.sqf +++ b/addons/frag/functions/fnc_spallTrack.sqf @@ -22,7 +22,7 @@ if (count _intersectsWith > 0) then { if(!(_x in _foundObjects)) then { // diag_log text format["Adding HP: %1", _x]; _index = (count GVAR(spallHPData)); - _hpId = _x addEventHandler ["hitPart", format["[%1, _this] call " + QUOTE(FUNC(spallHP)), _index]]; + _hpId = _x addEventHandler ["hitPart", compile format["[%1, _this] call " + QUOTE(FUNC(spallHP)), _index]]; _foundObjects set[(count _foundObjects), _x]; _foundObjectHPIds set[(count _foundObjectHPIds), _hpId]; _data = [_hpId, _x, typeOf _round, _round, _curPos, _velocity, 0, _foundObjects, _foundObjectHPIds]; diff --git a/addons/frag/stringtable.xml b/addons/frag/stringtable.xml index e267685869..5b49b0e192 100644 --- a/addons/frag/stringtable.xml +++ b/addons/frag/stringtable.xml @@ -3,19 +3,33 @@ Fragmentation Simulation - Enable the ACE Fragmentation Simulation - Spalling Simulation - Enable the ACE Spalling Simulation - + + + Maximum Projectiles Tracked + + + This setting controls the maximum amount of projectiles the fragmentation & spalling system will track at any given time. If more projectiles are fired, they will not be tracked. Lower this setting if you do not want FPS drops at high-count projectile scenarios ( >200 rounds in the air at once) + + + Maximum Projectiles Per Frame + + + The number of spall track calculations to perform in any given frame. This helps spread the FPS impact of tracking spall rounds across multiple frames, limiting its impact even further. + + + (SP Only) Frag/Spall Debug Tracing + + + (SP Only) Requires a mission/editor restart. Enables visual tracing of fragmentation and spalling rounds in SP game mode only. From 035277aafcd817ef25ff9e9b5e8f0d3206074c3c Mon Sep 17 00:00:00 2001 From: jaynus Date: Thu, 14 May 2015 08:11:08 -0700 Subject: [PATCH 007/140] removed illegal character --- addons/frag/stringtable.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/frag/stringtable.xml b/addons/frag/stringtable.xml index 5b49b0e192..a3a91b92d9 100644 --- a/addons/frag/stringtable.xml +++ b/addons/frag/stringtable.xml @@ -17,7 +17,7 @@ Maximum Projectiles Tracked - This setting controls the maximum amount of projectiles the fragmentation & spalling system will track at any given time. If more projectiles are fired, they will not be tracked. Lower this setting if you do not want FPS drops at high-count projectile scenarios ( >200 rounds in the air at once) + This setting controls the maximum amount of projectiles the fragmentation and spalling system will track at any given time. If more projectiles are fired, they will not be tracked. Lower this setting if you do not want FPS drops at high-count projectile scenarios ( >200 rounds in the air at once) Maximum Projectiles Per Frame From 92799719b64ef05a9c516de86d43d5c22c12341a Mon Sep 17 00:00:00 2001 From: jaynus Date: Thu, 14 May 2015 08:30:06 -0700 Subject: [PATCH 008/140] Spall off by default. --- addons/frag/ACE_Settings.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/frag/ACE_Settings.hpp b/addons/frag/ACE_Settings.hpp index bbf0398cfb..5efba45057 100644 --- a/addons/frag/ACE_Settings.hpp +++ b/addons/frag/ACE_Settings.hpp @@ -9,7 +9,7 @@ class ACE_Settings { displayName = "$STR_ACE_frag_EnableSpall"; description = "$STR_ACE_frag_EnableSpall_Desc"; typeName = "BOOL"; - value = 1; + value = 0; }; class GVAR(maxTrack) { displayName = "$STR_ACE_frag_MaxTrack"; From b2639da28840e6eefbbd0ddd76469017546ff2fe Mon Sep 17 00:00:00 2001 From: BullHorn Date: Sat, 16 May 2015 21:46:17 +0300 Subject: [PATCH 009/140] Documentation: Weather - standardize --- documentation/feature/weather.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/feature/weather.md b/documentation/feature/weather.md index b8bcf306b8..cc08eeff06 100644 --- a/documentation/feature/weather.md +++ b/documentation/feature/weather.md @@ -6,11 +6,11 @@ group: feature parent: wiki --- -## Overview +## 1. Overview ACE Weather is enabled by default. This feature simulates realistic weather according to map location, time of day, date, etc. -## Dependencies +## 2. Dependencies `ace_common`, `ace_modules` From c05e7fb046ff874a545ad2b0c8cadbd8d396cf30 Mon Sep 17 00:00:00 2001 From: BullHorn Date: Sat, 16 May 2015 23:42:54 +0300 Subject: [PATCH 010/140] Documentation: Vehiclelock - 1st iteration Add feature\Vehiclelock.md and add relevant info for players Edit addons\Vehiclelock\readme.md for typos and errors Edit missionmaker\modules.md for additional info --- addons/vehiclelock/readme.md | 2 +- documentation/feature/vehiclelock.md | 23 +++++++++++++---------- documentation/missionmaker/modules.md | 11 ++++++++++- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/addons/vehiclelock/readme.md b/addons/vehiclelock/readme.md index dc013145aa..64ae01a99c 100644 --- a/addons/vehiclelock/readme.md +++ b/addons/vehiclelock/readme.md @@ -31,7 +31,7 @@ Two key modes (can be used together): * `ACE_vehicleLock_lockpickStrength` - NUMBER: secons, determines how long lockpicking with take, overrides ACE_VehicleLock_DefaultLockpickStrength #### Public Functions: -`[bob, car1, true] call ACE_VehicleLock_fnc_addKeyForVehicle;` - will add a `ACE_magazine_customKey` to bob and program it to work on car1 +`[bob, car1, true] call ACE_VehicleLock_fnc_addKeyForVehicle;` - will add a `ACE_key_customKeyMagazine` to bob and program it to work on car1 ## Maintainers diff --git a/documentation/feature/vehiclelock.md b/documentation/feature/vehiclelock.md index 5431dc1624..5cea00534d 100644 --- a/documentation/feature/vehiclelock.md +++ b/documentation/feature/vehiclelock.md @@ -1,26 +1,29 @@ --- layout: wiki title: Vehicle Lock -description: +description: The Vehiclelock module enables locking vehicles and their inventory group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +ACE Vehicle Lock is disabled by default. This feature adds the ability to lock and unlock vehicles and their inventory using a key. -### Sub-feature 2 -Short description of sub-feature 2. +### 1.1 Key modes +The mission maker can choose one or both methods: +- Side based keys - A key is responsible for locking and unlocking every vehicle specific to a side (BLUFOR, OPFOR, INDEP or Civilian). +- Custom keys - A key is responsible for locking and unclocking only one specific vehicle, determined by the mission maker. + +### 1.2 Lock picking +It is possible to pick a lock of a locked vehicle. -## Usage +## 2. Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. +Locking, unlocking and picking vehicle locks is possible via the ACE Interact menu. -## Dependencies +## 3. Dependencies `ace_interaction` diff --git a/documentation/missionmaker/modules.md b/documentation/missionmaker/modules.md index 2d7a7d80c1..dcba720c6b 100644 --- a/documentation/missionmaker/modules.md +++ b/documentation/missionmaker/modules.md @@ -280,8 +280,10 @@ The safe zone around players from a different team (in meters)
### 1.17 Vehicle Lock *Part of: ace_vehiclelock* +These modules allow you to lock and unlock vehicles and their inventory using a key. Players don't receive a key automatically; for key names, see [Classnames Wiki](http://ace3mod.com/wiki/missionmaker/classnames.html#vehicle-lock). + #### 1.17.1 Vehicle Key Assign -Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. Only valid for objects present at mission start. +Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. Only valid for objects present at mission start. #### 1.17.2 Vehicle Lock Setup Settings for lockpick strength and initial vehicle lock state. Removes ambiguous lock states. @@ -298,6 +300,13 @@ Set lock state for all vehicles (removes ambiguous lock states)
Default Time to lockpick (in seconds)
`Default value: 10` +#### 1.17.3 Vehicle setVariables: +* `ACE_VehicleLock_lockSide` - SIDE: overrides a vehicle's side, allowing locking and unlocking using a different side's key. For example: Unlocking INDEP vehicles with a BLUFOR key. +* `ACE_vehicleLock_lockpickStrength` - NUMBER: seconds, determines how long lockpicking with take, overrides the value set in the module for a specific vehicle of the mission maker's choice. + +#### 1.17.4 Public functions: +Example: `[bob, car1, true] call ACE_VehicleLock_fnc_addKeyForVehicle;` - will add a key to bob and program it to work only on car1 + ### 1.18 Weather *Part of: ace_weather* From 36782c29a5b2376a2708e44756f458b6dce4bead Mon Sep 17 00:00:00 2001 From: BullHorn Date: Sat, 16 May 2015 23:55:18 +0300 Subject: [PATCH 011/140] Documentation: Vehiclelock - add description Add description - ability to picklock --- documentation/feature/vehiclelock.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/feature/vehiclelock.md b/documentation/feature/vehiclelock.md index 5cea00534d..ce78566ee6 100644 --- a/documentation/feature/vehiclelock.md +++ b/documentation/feature/vehiclelock.md @@ -8,7 +8,7 @@ parent: wiki ## 1. Overview -ACE Vehicle Lock is disabled by default. This feature adds the ability to lock and unlock vehicles and their inventory using a key. +ACE Vehicle Lock is disabled by default. This feature adds the ability to lock and unlock vehicles and their inventory using a key, as well as lock picking locked vehicles. ### 1.1 Key modes The mission maker can choose one or both methods: From 96b92ac1721b19aea4e38f419dced4dff5b75862 Mon Sep 17 00:00:00 2001 From: ulteq Date: Sun, 17 May 2015 11:45:55 +0200 Subject: [PATCH 012/140] Added a new module option for advanced ballistics: * alwaysSimulateForGroupMembers --- addons/advanced_ballistics/ACE_Settings.hpp | 6 ++++++ addons/advanced_ballistics/CfgVehicles.hpp | 6 ++++++ addons/advanced_ballistics/functions/fnc_handleFired.sqf | 8 +++++--- .../functions/fnc_initModuleSettings.sqf | 1 + addons/advanced_ballistics/stringtable.xml | 6 ++++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/addons/advanced_ballistics/ACE_Settings.hpp b/addons/advanced_ballistics/ACE_Settings.hpp index 67bc51511e..c931ce4d21 100644 --- a/addons/advanced_ballistics/ACE_Settings.hpp +++ b/addons/advanced_ballistics/ACE_Settings.hpp @@ -11,6 +11,12 @@ class ACE_Settings { typeName = "BOOL"; value = 1; }; + class GVAR(alwaysSimulateForGroupMembers) { + displayName = "Always Enabled For Group Members"; + description = "Always enables advanced ballistics when a group member fires"; + typeName = "BOOL"; + value = 0; + }; class GVAR(disabledInFullAutoMode) { displayName = "Disabled In FullAuto Mode"; description = "Disables the advanced ballistics during full auto fire"; diff --git a/addons/advanced_ballistics/CfgVehicles.hpp b/addons/advanced_ballistics/CfgVehicles.hpp index 4e42f35f72..642faeda96 100644 --- a/addons/advanced_ballistics/CfgVehicles.hpp +++ b/addons/advanced_ballistics/CfgVehicles.hpp @@ -23,6 +23,12 @@ class CfgVehicles { typeName = "BOOL"; defaultValue = 1; }; + class alwaysSimulateForGroupMembers { + displayName = "$STR_ACE_AdvancedBallistics_alwaysSimulateForGroupMembers_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_alwaysSimulateForGroupMembers_Description"; + typeName = "BOOL"; + defaultValue = 0; + }; class disabledInFullAutoMode { displayName = "$STR_ACE_AdvancedBallistics_disabledInFullAutoMod_DisplayName"; description = "$STR_ACE_AdvancedBallistics_disabledInFullAutoMod_Description"; diff --git a/addons/advanced_ballistics/functions/fnc_handleFired.sqf b/addons/advanced_ballistics/functions/fnc_handleFired.sqf index bb0b649da4..33bd02a4e7 100644 --- a/addons/advanced_ballistics/functions/fnc_handleFired.sqf +++ b/addons/advanced_ballistics/functions/fnc_handleFired.sqf @@ -36,15 +36,17 @@ if (underwater _unit) exitWith {}; if (!(_ammo isKindOf "BulletBase")) exitWith {}; if (_unit distance ACE_player > GVAR(simulationRadius)) exitWith {}; if (GVAR(onlyActiveForLocalPlayers) && !(local _unit)) then { + // The shooter is non local + _abort = true; if (GVAR(alwaysSimulateForSnipers)) then { - // The shooter is non local if (currentWeapon _unit == primaryWeapon _unit && count primaryWeaponItems _unit > 2) then { _opticsName = (primaryWeaponItems _unit) select 2; _opticType = getNumber(configFile >> "CfgWeapons" >> _opticsName >> "ItemInfo" >> "opticType"); _abort = _opticType != 2; // We only abort if the non local shooter is not a sniper }; - } else { - _abort = true; + }; + if (GVAR(alwaysSimulateForGroupMembers) && _abort) then { + _abort = (group ACE_player) != (group _unit); }; }; //if (!GVAR(vehicleGunnerEnabled) && !(_unit isKindOf "Man")) then { _abort = true; }; // We currently do not have firedEHs on vehicles diff --git a/addons/advanced_ballistics/functions/fnc_initModuleSettings.sqf b/addons/advanced_ballistics/functions/fnc_initModuleSettings.sqf index ba7ea31a8f..554d9470b9 100644 --- a/addons/advanced_ballistics/functions/fnc_initModuleSettings.sqf +++ b/addons/advanced_ballistics/functions/fnc_initModuleSettings.sqf @@ -29,6 +29,7 @@ if !(_activated) exitWith {}; [_logic, QGVAR(onlyActiveForLocalPlayers), "onlyActiveForLocalPlayers"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(disabledInFullAutoMode), "disabledInFullAutoMode"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(alwaysSimulateForSnipers), "alwaysSimulateForSnipers"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(alwaysSimulateForGroupMembers), "alwaysSimulateForGroupMembers"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(simulationInterval), "simulationInterval"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(simulationRadius), "simulationRadius"] call EFUNC(common,readSettingFromModule); diff --git a/addons/advanced_ballistics/stringtable.xml b/addons/advanced_ballistics/stringtable.xml index 565e4bd801..79c2ec7c52 100644 --- a/addons/advanced_ballistics/stringtable.xml +++ b/addons/advanced_ballistics/stringtable.xml @@ -45,6 +45,12 @@ Always enables advanced ballistics when high power optics are used Aktywuje zaawansowaną balistykę zawsze, kiedy używana jest optyka
+ + Always Enabled For Group Members + + + Always enables advanced ballistics when a group member fires + Disabled In FullAuto Mode Wył. podczas ognia auto. From 4513b02c1068385957fd6d832950e319eaa4cce6 Mon Sep 17 00:00:00 2001 From: ulteq Date: Sun, 17 May 2015 12:57:55 +0200 Subject: [PATCH 013/140] Experiment with the bullet trace effect size --- addons/advanced_ballistics/functions/fnc_handleFired.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/advanced_ballistics/functions/fnc_handleFired.sqf b/addons/advanced_ballistics/functions/fnc_handleFired.sqf index bb0b649da4..3567efc1bb 100644 --- a/addons/advanced_ballistics/functions/fnc_handleFired.sqf +++ b/addons/advanced_ballistics/functions/fnc_handleFired.sqf @@ -132,7 +132,7 @@ GVAR(currentbulletID) = (GVAR(currentbulletID) + 1) % 10000; }; if (_bulletTraceVisible && _bulletSpeed > 600) then { - drop ["\A3\data_f\ParticleEffects\Universal\Refract","","Billboard",1,0.1,getPos _bullet,[0,0,0],0,1.275,1,0,[0.0157480315*_caliber,0.00787401574*_caliber],[[0,0,0,0.6],[0,0,0,0.4]],[1,0],0,0,"","",""]; + drop ["\A3\data_f\ParticleEffects\Universal\Refract","","Billboard",1,0.1,getPos _bullet,[0,0,0],0,1.275,1,0,[sqrt(0.006*_caliber),sqrt(0.003*_caliber)],[[0,0,0,0.6],[0,0,0,0.4]],[1,0],0,0,"","",""]; }; call compile ("ace_advanced_ballistics" callExtension format["simulate:%1:%2:%3:%4:%5:%6:%7", _index, _bulletVelocity, _bulletPosition, ACE_wind, ASLToATL(_bulletPosition) select 2, floor(time), time - floor(time)]); From 01e7a0cee4a6acd8a39813174ef492dd83caae88 Mon Sep 17 00:00:00 2001 From: BullHorn Date: Sun, 17 May 2015 15:51:40 +0300 Subject: [PATCH 014/140] Documentation: edit Vehiclelock Improve grammar Add note for users about lock modes Move lock modes description for mission makers --- documentation/feature/vehiclelock.md | 15 ++++++--------- documentation/missionmaker/modules.md | 10 ++++------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/documentation/feature/vehiclelock.md b/documentation/feature/vehiclelock.md index ce78566ee6..4217d13250 100644 --- a/documentation/feature/vehiclelock.md +++ b/documentation/feature/vehiclelock.md @@ -8,21 +8,18 @@ parent: wiki ## 1. Overview -ACE Vehicle Lock is disabled by default. This feature adds the ability to lock and unlock vehicles and their inventory using a key, as well as lock picking locked vehicles. - -### 1.1 Key modes -The mission maker can choose one or both methods: -- Side based keys - A key is responsible for locking and unlocking every vehicle specific to a side (BLUFOR, OPFOR, INDEP or Civilian). -- Custom keys - A key is responsible for locking and unclocking only one specific vehicle, determined by the mission maker. - -### 1.2 Lock picking -It is possible to pick a lock of a locked vehicle. +ACE Vehicle Lock is disabled by default. This feature adds the ability to lock and unlock vehicles and their inventory using a key, as well as picking locks of locked vehicles. ## 2. Usage Locking, unlocking and picking vehicle locks is possible via the ACE Interact menu. +
+
Note:
+

Different locking modes can be set, consult with your mission maker for more information.

+
+ ## 3. Dependencies diff --git a/documentation/missionmaker/modules.md b/documentation/missionmaker/modules.md index dcba720c6b..38b57595a7 100644 --- a/documentation/missionmaker/modules.md +++ b/documentation/missionmaker/modules.md @@ -283,9 +283,10 @@ The safe zone around players from a different team (in meters)
These modules allow you to lock and unlock vehicles and their inventory using a key. Players don't receive a key automatically; for key names, see [Classnames Wiki](http://ace3mod.com/wiki/missionmaker/classnames.html#vehicle-lock). #### 1.17.1 Vehicle Key Assign -Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. Only valid for objects present at mission start. +Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. Only valid for objects present at mission start. +Example: `[bob, car1, true] call ACE_VehicleLock_fnc_addKeyForVehicle;` - will add a key to bob and program it to work only on car1 -#### 1.17.2 Vehicle Lock Setup +#### 1.17.2.1 Vehicle Lock Setup Settings for lockpick strength and initial vehicle lock state. Removes ambiguous lock states. **Settings:** @@ -300,13 +301,10 @@ Set lock state for all vehicles (removes ambiguous lock states)
Default Time to lockpick (in seconds)
`Default value: 10` -#### 1.17.3 Vehicle setVariables: +#### 1.17.2.2 Vehicle setVariables * `ACE_VehicleLock_lockSide` - SIDE: overrides a vehicle's side, allowing locking and unlocking using a different side's key. For example: Unlocking INDEP vehicles with a BLUFOR key. * `ACE_vehicleLock_lockpickStrength` - NUMBER: seconds, determines how long lockpicking with take, overrides the value set in the module for a specific vehicle of the mission maker's choice. -#### 1.17.4 Public functions: -Example: `[bob, car1, true] call ACE_VehicleLock_fnc_addKeyForVehicle;` - will add a key to bob and program it to work only on car1 - ### 1.18 Weather *Part of: ace_weather* From b7944bdb0bdb0a80dcb56bd4a261fc0e8f529899 Mon Sep 17 00:00:00 2001 From: BullHorn Date: Sun, 17 May 2015 17:11:26 +0300 Subject: [PATCH 015/140] Documentation: Weather - add wind usage Add default keys for toggling wind indicator arrow on/off Add explanation for arrow colors --- documentation/feature/weather.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/documentation/feature/weather.md b/documentation/feature/weather.md index cc08eeff06..b33b438178 100644 --- a/documentation/feature/weather.md +++ b/documentation/feature/weather.md @@ -11,6 +11,13 @@ parent: wiki ACE Weather is enabled by default. This feature simulates realistic weather according to map location, time of day, date, etc. -## 2. Dependencies +## 2. Usage + +### 2.1 Wind info +- Wind info is toggled on/off using Shift+K +- The arrow representing wind info is based on [Beaufort scale](http://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale) + + +## 3. Dependencies `ace_common`, `ace_modules` From 9b9d2ad0f7d351913308339d6974582e91680706 Mon Sep 17 00:00:00 2001 From: BullHorn Date: Sun, 17 May 2015 17:54:06 +0300 Subject: [PATCH 016/140] Docs - rename ACE to ACE3 Renamed for docs: vehiclelock, weather and windeflection --- documentation/feature/vehiclelock.md | 2 +- documentation/feature/weather.md | 2 +- documentation/feature/windeflection.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/feature/vehiclelock.md b/documentation/feature/vehiclelock.md index 4217d13250..2dc8b7e92d 100644 --- a/documentation/feature/vehiclelock.md +++ b/documentation/feature/vehiclelock.md @@ -8,7 +8,7 @@ parent: wiki ## 1. Overview -ACE Vehicle Lock is disabled by default. This feature adds the ability to lock and unlock vehicles and their inventory using a key, as well as picking locks of locked vehicles. +ACE3 Vehicle Lock is disabled by default. This feature adds the ability to lock and unlock vehicles and their inventory using a key, as well as picking locks of locked vehicles. ## 2. Usage diff --git a/documentation/feature/weather.md b/documentation/feature/weather.md index b33b438178..d2330ed69b 100644 --- a/documentation/feature/weather.md +++ b/documentation/feature/weather.md @@ -8,7 +8,7 @@ parent: wiki ## 1. Overview -ACE Weather is enabled by default. This feature simulates realistic weather according to map location, time of day, date, etc. +ACE3 Weather is enabled by default. This feature simulates realistic weather according to map location, time of day, date, etc. ## 2. Usage diff --git a/documentation/feature/windeflection.md b/documentation/feature/windeflection.md index 386bd849c2..8a0a29ad1d 100644 --- a/documentation/feature/windeflection.md +++ b/documentation/feature/windeflection.md @@ -8,7 +8,7 @@ parent: wiki ## 1. Overview -Wind Deflection is enabled by default. This feature simulates the wind deflection of projectiles fired by players and is designed to work independently or in conjunction with the Advanced Ballistic feature. +ACE3 Wind Deflection is enabled by default. This feature simulates the wind deflection of projectiles fired by players and is designed to work independently or in conjunction with the Advanced Ballistic feature.
Note:
From 9f671e59c11bf96e23e80363a1da0a7c817b1841 Mon Sep 17 00:00:00 2001 From: BullHorn Date: Sun, 17 May 2015 18:00:06 +0300 Subject: [PATCH 017/140] Doc: modules.md - rename 'ACE' to 'ACE3' Rename all relevant instances of 'ACE' to 'ACE3, ignoring code examples --- documentation/missionmaker/modules.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/documentation/missionmaker/modules.md b/documentation/missionmaker/modules.md index 38b57595a7..473fd04a9f 100644 --- a/documentation/missionmaker/modules.md +++ b/documentation/missionmaker/modules.md @@ -7,7 +7,7 @@ order: 5 parent: wiki --- -## 1. ACE +## 1. ACE3 ### 1.1 Advanced Ballistics *Part of: ace_advanced_ballistics* @@ -45,10 +45,10 @@ Defines the radius around the player (in meters) at which advanced ballistics ar ### 1.2 Allow Config Export *Part of: ace_Optionmenu* -This modules allows to export all current ACE settings from the ACE Option menu to the clipboard and RPT file. +This modules allows to export all current ACE3 settings from the ACE3 Option menu to the clipboard and RPT file. 1. **Allow (Boolean)**
-Enables the "export" button in the ACE Option menu
+Enables the "export" button in the ACE3 Option menu
`Default value: Yes` ### 1.3 BlueForceTracking @@ -68,7 +68,7 @@ Hide markers for "AI only" groups.
### 1.4 Check PBOs *Part of: ace_common* -If you are worried that players haven't updated ACE or other mods to the version you're using on the server, you can place the "Check PBOs" module on your map. You can choose one of three posible actions that are being executed when a player joins that has a wrong version of ACE or an other mod: +If you are worried that players haven't updated ACE3 or other mods to the version you're using on the server, you can place the "Check PBOs" module on your map. You can choose one of three posible actions that are being executed when a player joins that has a wrong version of ACE3 or an other mod: * Warn once * Warn permanent @@ -81,7 +81,7 @@ What to do with people who do not have the right PBOs.
`Default value: "Warn once"` 2. **Check all addons (Boolean)**
-Check all addons instead of only those of ACE?
+Check all addons instead of only those of ACE3?
`Default value: "No"` 3. **Whitelist**
@@ -107,7 +107,7 @@ Example 3: @JSRS + @Blastcore-A3:
### 1.5 Explosive System *Part of: ace_explosive* -The "Explosive System" module lets you tweak the settings for the new explosive system that ACE introduces. +The "Explosive System" module lets you tweak the settings for the new explosive system that ACE3 introduces. **Settings:** @@ -236,7 +236,7 @@ This module enables Mission Makers to specificly enable units to move a rallypoi

It's important to mention that this doesn't work for player who join during a mission (JIP = Join in progress). That's something we can't change because that's the way Bohemia has implemented their module framework.

-To enable JIP players to move rally points have a look at [ACE Rallypoints](./mission-tools.html#1.-ace-rallypoints). +To enable JIP players to move rally points have a look at [ACE3 Rallypoints](./mission-tools.html#1.-ace-rallypoints). ### 1.15 Respawn System @@ -313,7 +313,7 @@ This module allows you to customize the weather settings.
Note:
-

ACE Weather overrides weather settings (editor, mission settings) and automatically calculates wind, temperature and pressure according to map location, date, time of day and cloud coverage and allows the weather to evolve realistically as the simulation progresses. Weather synchronization occurs between all clients.
Adjustment of the weather is possible by modifying the overcast value (for example: 0.7 may result in intermittent rain).

+

ACE3 Weather overrides weather settings (editor, mission settings) and automatically calculates wind, temperature and pressure according to map location, date, time of day and cloud coverage and allows the weather to evolve realistically as the simulation progresses. Weather synchronization occurs between all clients.
Adjustment of the weather is possible by modifying the overcast value (for example: 0.7 may result in intermittent rain).

@@ -322,8 +322,8 @@ This module allows you to customize the weather settings. 1. **Weather propagation (Boolean)**
Enables sever side weather propagation.
`Default value: Yes` -2. **ACE Weather (Boolean)**
-Overrides the default weather with ACE weather (map based).
+2. **ACE3 Weather (Boolean)**
+Overrides the default weather with ACE3 weather (map based).
`Default value: Yes` 3. **Sync Rain (Boolean)**
Synchronizes rain.
@@ -377,7 +377,7 @@ And then there's the "LSD Vehicles" module … it does 'something' to all v -## 2. ACE Medical +## 2. ACE3 Medical *Part of: ace_medical* ### 2.1 Medical Settings @@ -515,7 +515,7 @@ Whether or not the objects in the list will be a medical vehicle.
`Default value: Yes` -## 3. ACE Mission Modules +## 3. ACE3 Mission Modules *Part of: ace_missionmodules* ### 3.1 Ambiance Sounds From 1dd8dc3bfb9d54bbc50df30ccdc58ed9f5bc0416 Mon Sep 17 00:00:00 2001 From: jaynus-linux Date: Sun, 17 May 2015 10:10:02 -0700 Subject: [PATCH 018/140] cross platform macros and port added for linux for all extensions. Should be transparent --- .../AdvancedBallistics.cpp | 4 +-- extensions/break_line/ace_break_line.cpp | 2 +- extensions/clipboard/ace_clipboard.cpp | 2 +- extensions/common/p3d/animation.cpp | 3 +- extensions/common/p3d/compressed.cpp | 8 ++--- extensions/common/p3d/compressed.hpp | 30 ++++++++--------- extensions/common/pbo/archive.cpp | 2 +- extensions/common/pbo/search.cpp | 6 +++- extensions/common/pbo/search.hpp | 6 +++- extensions/common/shared.hpp | 33 +++++++++++++++++-- extensions/common/simplepipe_win32.cpp | 6 +++- extensions/common/simplepipe_win32.hpp | 3 ++ extensions/common/simulation/object.cpp | 4 +-- extensions/common/simulation/object.hpp | 10 +++--- extensions/common/vector.hpp | 12 ++++++- extensions/fcs/ace_fcs.cpp | 2 +- 16 files changed, 92 insertions(+), 41 deletions(-) diff --git a/extensions/advanced_ballistics/AdvancedBallistics.cpp b/extensions/advanced_ballistics/AdvancedBallistics.cpp index 48865f7f6b..06a398f342 100644 --- a/extensions/advanced_ballistics/AdvancedBallistics.cpp +++ b/extensions/advanced_ballistics/AdvancedBallistics.cpp @@ -82,7 +82,7 @@ double calculateRoughnessLength(double posX, double posY) { return 1.6; } - return roughness_lengths[2 + min(nearBuildings, 6)]; + return roughness_lengths[2 + std::min(nearBuildings, 6)]; } return 0.0024; @@ -230,7 +230,7 @@ double calculateRetard(int DragFunction, double DragCoefficient, double Velocity extern "C" { - __declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function); + EXPORT void __stdcall RVExtension(char *output, int outputSize, const char *function); } void __stdcall RVExtension(char *output, int outputSize, const char *function) diff --git a/extensions/break_line/ace_break_line.cpp b/extensions/break_line/ace_break_line.cpp index 440566b744..8bb5af9572 100644 --- a/extensions/break_line/ace_break_line.cpp +++ b/extensions/break_line/ace_break_line.cpp @@ -20,7 +20,7 @@ #define MAXCHARACTERS 14 extern "C" { - __declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function); + EXPORT void __stdcall RVExtension(char *output, int outputSize, const char *function); }; std::vector splitString(const std::string & input) { diff --git a/extensions/clipboard/ace_clipboard.cpp b/extensions/clipboard/ace_clipboard.cpp index 41e3a5721f..61960598ec 100644 --- a/extensions/clipboard/ace_clipboard.cpp +++ b/extensions/clipboard/ace_clipboard.cpp @@ -14,7 +14,7 @@ #include extern "C" { - __declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function); + EXPORT void __stdcall RVExtension(char *output, int outputSize, const char *function); }; std::string gClipboardData; diff --git a/extensions/common/p3d/animation.cpp b/extensions/common/p3d/animation.cpp index 1c97399a1e..f47a40fe5a 100644 --- a/extensions/common/p3d/animation.cpp +++ b/extensions/common/p3d/animation.cpp @@ -2,7 +2,6 @@ #include "p3d/animation.hpp" #include "read_helpers.hpp" -#include "..\simulation\object.hpp" namespace ace { namespace p3d { @@ -69,4 +68,4 @@ namespace ace { animation::~animation() { } }; -}; \ No newline at end of file +}; diff --git a/extensions/common/p3d/compressed.cpp b/extensions/common/p3d/compressed.cpp index d614e2b490..47940542b8 100644 --- a/extensions/common/p3d/compressed.cpp +++ b/extensions/common/p3d/compressed.cpp @@ -1,5 +1,7 @@ #include "compressed.hpp" +#include + #include #include #include @@ -41,11 +43,7 @@ namespace ace { if (in.eof()) { in.clear(); } -#if _MSC_VER == 1800 - _data = std::make_shared(expected_size + (expected_size % 8)); -#else - _data = std::make_unique(expected_size + (expected_size % 8)); -#endif + _data = std::unique_ptr(new uint8_t[expected_size + (expected_size % 8)]); result = _mikero_lzo1x_decompress_safe(buffer, _data.get(), expected_size); if (result < 0) { diff --git a/extensions/common/p3d/compressed.hpp b/extensions/common/p3d/compressed.hpp index d9c3a5654b..31bd3fc7f7 100644 --- a/extensions/common/p3d/compressed.hpp +++ b/extensions/common/p3d/compressed.hpp @@ -37,34 +37,34 @@ namespace ace { compressed() { } compressed(std::istream &stream_, bool compressed_ = false, bool fill_ = false, uint32_t version = 68) { - stream_.read((char *)&size, sizeof(uint32_t)); + stream_.read((char *)&this->size, sizeof(uint32_t)); // if(version <) if(fill_) - READ_BOOL(fill); + READ_BOOL(this->fill); - assert(size < 4095 * 10); - if (size > 0) { - if (fill) { + assert(this->size < 4095 * 10); + if (this->size > 0) { + if (this->fill) { T val; stream_.read((char *)&val, sizeof(T)); - for (int x = 0; x < size; x++) { - data.push_back(val); + for (int x = 0; x < this->size; x++) { + this->data.push_back(val); } } else { if (version >= 64 && compressed_) { - READ_BOOL(flag); + READ_BOOL(this->flag); } - if ( (size * sizeof(T) >= 1024 && compressed_ && version < 64) || (flag && compressed_)) { - int32_t result = _decompress_safe(stream_, size * sizeof(T)); + if ( (this->size * sizeof(T) >= 1024 && compressed_ && version < 64) || (this->flag && compressed_)) { + int32_t result = this->_decompress_safe(stream_, this->size * sizeof(T)); assert(result > 0); - T * ptr = (T *)(_data.get()); - data.assign(ptr, ptr + size ); + T * ptr = (T *)(this->_data.get()); + this->data.assign(ptr, ptr + this->size ); } else { - for (int x = 0; x < size; x++) { + for (int x = 0; x < this->size; x++) { T val; stream_.read((char *)&val, sizeof(T)); - data.push_back(val); + this->data.push_back(val); } } } @@ -167,4 +167,4 @@ namespace ace { } }; } -} \ No newline at end of file +} diff --git a/extensions/common/pbo/archive.cpp b/extensions/common/pbo/archive.cpp index 71c11de3fe..13a879b8d6 100644 --- a/extensions/common/pbo/archive.cpp +++ b/extensions/common/pbo/archive.cpp @@ -16,7 +16,7 @@ namespace ace { std::streampos _save = stream_.tellg(); file_offset = begin_data_offset + entry->offset; - use_size = max(entry->size, entry->storage_size); + use_size = std::max(entry->size, entry->storage_size); output->data = new uint8_t[use_size]; bytes_read = 0; diff --git a/extensions/common/pbo/search.cpp b/extensions/common/pbo/search.cpp index f383bf5dc5..3ed299d327 100644 --- a/extensions/common/pbo/search.cpp +++ b/extensions/common/pbo/search.cpp @@ -1,3 +1,5 @@ +#ifdef _WIN32 + #include "search.hpp" #include #include @@ -298,4 +300,6 @@ namespace ace { return true; } } -} \ No newline at end of file +} + +#endif diff --git a/extensions/common/pbo/search.hpp b/extensions/common/pbo/search.hpp index 61aaccb9f0..9a3051b918 100644 --- a/extensions/common/pbo/search.hpp +++ b/extensions/common/pbo/search.hpp @@ -1,3 +1,5 @@ +#ifdef _WIN32 + #pragma once #include "shared.hpp" @@ -24,4 +26,6 @@ namespace ace { }; typedef std::shared_ptr search_p; } -} \ No newline at end of file +} + +#endif diff --git a/extensions/common/shared.hpp b/extensions/common/shared.hpp index c84624132a..6c49b99fad 100644 --- a/extensions/common/shared.hpp +++ b/extensions/common/shared.hpp @@ -3,6 +3,8 @@ #include "targetver.h" #include #include +#include + #include #include #include @@ -23,8 +25,11 @@ #define EXTENSION_RETURN() return; #endif -#ifdef _WINDOWS +#ifdef _WIN32 #define sleep(x) Sleep(x) +#else +#define _strdup strdup +#define strtok_s strtok_r #endif namespace ace { @@ -40,6 +45,11 @@ namespace ace { std::vector &split(const std::string &s, char delim, std::vector &elems); std::vector split(const std::string &s, char delim); + template + std::unique_ptr make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); + } + // trim from start static inline std::string <rim(std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); @@ -74,4 +84,23 @@ namespace ace { #define ACE_ASSERT assert() #else #define ACE_ASSERT ace::runtime_assert() -#endif \ No newline at end of file +#endif + +#ifndef _WIN32 +#define __stdcall +#endif + +#if defined(_MSC_VER) + // Microsoft + #define EXPORT __declspec(dllexport) + #define IMPORT __declspec(dllimport) +#elif defined(_GCC) + // GCC + #define EXPORT __attribute__((visibility("default"))) + #define IMPORT +#else + // do nothing and hope for the best? + #define EXPORT + #define IMPORT + #pragma warning Unknown dynamic link import/export semantics. +#endif diff --git a/extensions/common/simplepipe_win32.cpp b/extensions/common/simplepipe_win32.cpp index f79af02857..469e803246 100644 --- a/extensions/common/simplepipe_win32.cpp +++ b/extensions/common/simplepipe_win32.cpp @@ -1,3 +1,5 @@ +#ifdef _WIN32 + #include "simplepipe_win32.hpp" #include #include @@ -176,4 +178,6 @@ namespace ace { return NULL; return &buf_[0]; } -} \ No newline at end of file +} + +#endif diff --git a/extensions/common/simplepipe_win32.hpp b/extensions/common/simplepipe_win32.hpp index 3c37c9637b..8f9247e4c3 100644 --- a/extensions/common/simplepipe_win32.hpp +++ b/extensions/common/simplepipe_win32.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef _WIN32 + #include #include #include @@ -55,3 +57,4 @@ namespace ace { }; } +#endif diff --git a/extensions/common/simulation/object.cpp b/extensions/common/simulation/object.cpp index 0831111711..aa702f34ac 100644 --- a/extensions/common/simulation/object.cpp +++ b/extensions/common/simulation/object.cpp @@ -1,8 +1,8 @@ #include "object.hpp" -#include "p3d\parser.hpp" +#include "p3d/parser.hpp" -#include "glm\gtc\matrix_transform.hpp" +#include "glm/gtc/matrix_transform.hpp" ace::simulation::vertex::vertex(vertex_table & _table, ace::vector3 _vertex, uint32_t _id) : table(_table), vertex_id(_id) { diff --git a/extensions/common/simulation/object.hpp b/extensions/common/simulation/object.hpp index a77da9d5cf..11ccf13390 100644 --- a/extensions/common/simulation/object.hpp +++ b/extensions/common/simulation/object.hpp @@ -8,10 +8,10 @@ #define GLM_PRECISION_HIGHP_FLOAT -#include "p3d\model.hpp" -#include "glm\glm.hpp" -#include "glm\vec3.hpp" -#include "glm\mat4x4.hpp" +#include "p3d/model.hpp" +#include "glm/glm.hpp" +#include "glm/vec3.hpp" +#include "glm/mat4x4.hpp" namespace ace { @@ -218,4 +218,4 @@ namespace ace { }; } -} \ No newline at end of file +} diff --git a/extensions/common/vector.hpp b/extensions/common/vector.hpp index ac5b38bd1f..0eb348f312 100644 --- a/extensions/common/vector.hpp +++ b/extensions/common/vector.hpp @@ -5,7 +5,17 @@ #include "LinearMath\btVector3.h" #endif */ + #include "shared.hpp" + +#ifndef _WIN32 + +#define sinf(x) sin(x) +#define cosf(x) cos(x) +#define acosf(x) acos(x) + +#endif + namespace ace { template T acos(T n) { return -1; } @@ -158,4 +168,4 @@ namespace ace { T _x; T _y; }; -}; \ No newline at end of file +}; diff --git a/extensions/fcs/ace_fcs.cpp b/extensions/fcs/ace_fcs.cpp index 75ef3b240b..178711f54c 100644 --- a/extensions/fcs/ace_fcs.cpp +++ b/extensions/fcs/ace_fcs.cpp @@ -26,7 +26,7 @@ #define RADIANS(X) (X / (180 / M_PI)) extern "C" { - __declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function); + EXPORT void __stdcall RVExtension(char *output, int outputSize, const char *function); }; std::vector splitString(std::string input) { From 836cd9d833a931fce20a46c48810a16bc5b7917c Mon Sep 17 00:00:00 2001 From: Josuan Albin Date: Sun, 17 May 2015 19:51:46 +0200 Subject: [PATCH 019/140] Documentation pass 3 - Fixed typos in laser/readme - Documentation guidelines updated - ACE3 mentions updated in - - ai - Updated doc - - fcs - - hearing - -hitreaction - - interaction - - interact_menu - - inventory - - javelin - - laser - - laserpointer - - laser_selfdesignate - - logistics_uavbattery - - logistics_wirecutter - - magazinerepack - - main - - map - - maptools - - markers --- addons/laser/README.md | 2 +- .../Documentation guidelines and tips.md | 2 ++ documentation/feature/ai.md | 4 +-- documentation/feature/fcs.md | 23 +++++++----- documentation/feature/hearing.md | 22 +++++++----- documentation/feature/hitreactions.md | 19 +++------- documentation/feature/interact_menu.md | 17 ++------- documentation/feature/interaction.md | 17 ++------- documentation/feature/inventory.md | 16 +++++---- documentation/feature/javelin.md | 35 +++++++++--------- documentation/feature/laser.md | 17 ++------- documentation/feature/laser_selfdesignate.md | 17 ++------- documentation/feature/laserpointer.md | 21 +++++------ documentation/feature/logistics_uavbattery.md | 20 +++++------ documentation/feature/logistics_wirecutter.md | 22 ++++++------ documentation/feature/magazinerepack.md | 20 +++++------ documentation/feature/main.md | 8 ++--- documentation/feature/map.md | 27 ++++++++------ documentation/feature/maptools.md | 36 ++++++++++++------- documentation/feature/markers.md | 13 ++----- 20 files changed, 162 insertions(+), 196 deletions(-) diff --git a/addons/laser/README.md b/addons/laser/README.md index acd112e233..96a2bd7b19 100644 --- a/addons/laser/README.md +++ b/addons/laser/README.md @@ -1,7 +1,7 @@ ace_laser ========= -Contains various functions necessary for the realitic protrayal of laser mechanics in other components. +Contains various functions necessary for the realistic portrayal of laser mechanics in other components. ## Maintainers diff --git a/documentation/development/Documentation guidelines and tips.md b/documentation/development/Documentation guidelines and tips.md index 620d4d9343..adb3c48b9c 100644 --- a/documentation/development/Documentation guidelines and tips.md +++ b/documentation/development/Documentation guidelines and tips.md @@ -42,6 +42,7 @@ Short description of sub-feature 2. - Step 3. ## 3. Dependencies + `ace_something` ## 4. Guides @@ -50,6 +51,7 @@ Short description of sub-feature 2. # Guidelines - A line between each entry like above. +- Use `ACE3` instead of `ACE 3`. - Remove each entry that is not used. - Don't forget to say what you're going to work on in #documentation in slack or [this topic] (https://github.com/acemod/ACE3/issues/1166) - Keybinds in ``` thoses thingies ``` diff --git a/documentation/feature/ai.md b/documentation/feature/ai.md index 18f76562fa..81dd52d895 100644 --- a/documentation/feature/ai.md +++ b/documentation/feature/ai.md @@ -20,10 +20,10 @@ AIs will now use the automatic mode of their weapons on short distances, instead The maximum engagement ranges are increased: AI will fire in bursts with variable length on high ranges of 500 - 700 meters, depending on their weapon and optic. ### 1.4 No deadzones in CQB -Some weapons had minimum engagement ranges. If you were as close as 2 meters to an AAF soldier, he wouldn't open fire, because the AI couldn't find any valid fire mode for their weapon. ACE 3 removes this behaviour mostly notable in CQB by adding a valid firing mode. +Some weapons had minimum engagement ranges. If you were as close as 2 meters to an AAF soldier, he wouldn't open fire, because the AI couldn't find any valid fire mode for their weapon. ACE3 removes this behaviour mostly notable in CQB by adding a valid firing mode. ### 1.5 No scripting -All changes of ACE 3 AI are config based to ensure full compatibility with advanced AI modifications like ASR AI. +All changes of ACE3 AI are config based to ensure full compatibility with advanced AI modifications like ASR AI. ## 2. Dependencies diff --git a/documentation/feature/fcs.md b/documentation/feature/fcs.md index 8085e47ee8..6ac4353599 100644 --- a/documentation/feature/fcs.md +++ b/documentation/feature/fcs.md @@ -6,25 +6,32 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Fire control system +### 1.1 Fire control system Offers a custom fire control system for tanks and helicopters. It enables engaging stationary and moving targets. -### Manual lasing targets +### 1.2 Manual lasing targets Changes the default rangefinders, including those in vehicles, to require manual lasing. -### Air burst ammunition +### 1.3 Air burst ammunition Anti air cannons can now use airburst ammunition. It will explode on the FCS' zeroed in range. -## Usage +## 2. Usage -To engage moving targets, place the crosshair on the enemy vehicle and press and hold tab. Follow the moving target with your crosshair for about 2 seconds and release tab. The optic will now be adjusted sideways to ensure a hit. +### 2.1 Engaging moving targets -To use manual lasing, place the crosshair on the object to range and press and hold tab. +- Place the crosshair on the enemy vehicle. +- Press and hold tab (by default) and follow the target for about 2 seconds. +- Release tab +- The optic is now adjusted sideways to ensue a hit. +### 2.2 Ranging stationary targets -## Dependencies +- Place the crosshair on the object to range. +- Tap tab (by default) the optic is now adjusted. + +## 3. Dependencies `ace_interaction` diff --git a/documentation/feature/hearing.md b/documentation/feature/hearing.md index 2f4c0b671d..01b8100bb1 100644 --- a/documentation/feature/hearing.md +++ b/documentation/feature/hearing.md @@ -6,22 +6,26 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Hearing damage simulation +### 1.1 Hearing damage simulation Introduces hearing damage caused by nearby explosions and large-caliber weapons. -### Earplugs +### 1.2 Earplugs Adds ear plugs to mitigate that effect. Soldiers with high caliber weapons or missile launchers will be equipped with those, but remember to put them in. -## Usage +## 2. Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. +### 2.1 Equipping earplugs +- For this you obviously need `Ear plugs`. +- Press the self interaction key ctrl+left windows (by default). +- Select `equipment`. +- Select `Earplugs in`. +- Same method to remove them but the option is `Earplugs out`. +- Note that you CAN re-use ear plugs. +## 3. Dependencies -## Dependencies - -`ace_interaction` +`ace_interaction` \ No newline at end of file diff --git a/documentation/feature/hitreactions.md b/documentation/feature/hitreactions.md index f5a4213908..fae394fa73 100644 --- a/documentation/feature/hitreactions.md +++ b/documentation/feature/hitreactions.md @@ -6,21 +6,12 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +### 1.1 Falling under fire +If a unit is shot while running it falls to the ground in a prone position, the area where the shot lands does not matters. +Note that the shot needs to inflict a certain amout of damage to make the unit fall, a small cut won't make the unit stumble. -### Sub-feature 2 -Short description of sub-feature 2. - - -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 2. Dependencies `ace_common` diff --git a/documentation/feature/interact_menu.md b/documentation/feature/interact_menu.md index 3335b32213..e66ea95406 100644 --- a/documentation/feature/interact_menu.md +++ b/documentation/feature/interact_menu.md @@ -6,22 +6,11 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +This handles the interaction layer of ACE3. -### Sub-feature 2 -Short description of sub-feature 2. - - -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 2. Dependencies `ace_common` diff --git a/documentation/feature/interaction.md b/documentation/feature/interaction.md index 27b9f05e64..bd96771788 100644 --- a/documentation/feature/interaction.md +++ b/documentation/feature/interaction.md @@ -6,22 +6,11 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +This provides interaction options between units. -### Sub-feature 2 -Short description of sub-feature 2. - - -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 2. Dependencies `ace_interact_menu` diff --git a/documentation/feature/inventory.md b/documentation/feature/inventory.md index fc10822917..20aa5204a2 100644 --- a/documentation/feature/inventory.md +++ b/documentation/feature/inventory.md @@ -6,18 +6,22 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Resized inventory UI +### 1.1 Resized inventory UI Makes the inventory dialog bigger and increases the number of items that can be seen in the list at once. -## Usage +## 2. Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. +### 2.1 Changing the size of the UI +- Press escape . +- Click on `ACE OPTIONS` on the top left corner of the screen. +- Click on `Make Inventory Display Bigger`. +- Choose the size desired on the right drop down menu. +- Press the `Close` button, your changes are automatically saved. -## Dependencies +## 3. Dependencies `ace_common` diff --git a/documentation/feature/javelin.md b/documentation/feature/javelin.md index 7095565ca9..be31f65e91 100644 --- a/documentation/feature/javelin.md +++ b/documentation/feature/javelin.md @@ -6,31 +6,30 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +### 1.1 Improved locking +The locking capabilities of the Titan and Javelin got improved, you can now lock on anything that has a thermal signature, including houses. -### Sub-feature 2 -Short description of sub-feature 2. +### 1.2 Fire mode switching +The Titan / Javelin now posses the ability to be used in top down attack or direct. -## Usage +## 2. Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. +### 2.1 Locking with the Titan / Javelin +- For this feature you need to have a compatible launcher. +- Fully zoom with the launcher. +- Switch to thermals n (by default). +- While keeping your aim steadily on target press and hold tab . +- When the sound changes and a cross appears on the screen it's time to fire. -Steps to lock titan/Javelin: - -1. You must be zoomed ALL THE WAY IN -2. You must be in thermal view -3. You must have a missile loaded -4. Hold TAB over a target, it will start beeping and the constraint boxes will appear -5. Once the beeping changes to LOCK tone, and the lock crosshairs appear, click fire without releasing tab - -CTRL+TAB is default key to change firemode (configurable as a key) +### 2.2 Switching fire mode +- For this feature you need to have a compatible launcher. +- When aiming with your launcher press ctrl+tab (by default). +- On the right side of the screen (for most launchers) you should see that `TOP`is now in green that means that your missile will be fired in top down mode. -## Dependencies +## 3. Dependencies `ace_main`, `ace_common`, `ace_missileguidance` diff --git a/documentation/feature/laser.md b/documentation/feature/laser.md index af07f5bc90..78ab448e8c 100644 --- a/documentation/feature/laser.md +++ b/documentation/feature/laser.md @@ -6,21 +6,10 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +Contains various functions necessary for the realistic portrayal of laser mechanics in other components. -### Sub-feature 2 -Short description of sub-feature 2. - - -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 2. Dependencies `ace_common` diff --git a/documentation/feature/laser_selfdesignate.md b/documentation/feature/laser_selfdesignate.md index 99432e0b4e..9130cc797e 100644 --- a/documentation/feature/laser_selfdesignate.md +++ b/documentation/feature/laser_selfdesignate.md @@ -6,21 +6,10 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +Allows gunners to lase their own targets. See [FCS] (http://ace3mod.com/wiki/feature/fcs.html) for more information. -### Sub-feature 2 -Short description of sub-feature 2. - - -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 2. Dependencies `ace_laser` diff --git a/documentation/feature/laserpointer.md b/documentation/feature/laserpointer.md index cbc79effd0..ee6d566733 100644 --- a/documentation/feature/laserpointer.md +++ b/documentation/feature/laserpointer.md @@ -6,21 +6,18 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +### 1.1 Visible light laser +ACE3 adds visible light laser. This feature is compatible with BI's lasers as well as supported modded ones. -### Sub-feature 2 -Short description of sub-feature 2. +## 2. Usage +### 2.1 Switching laser mode +- For this feature you need to have a compatible side attachment. +- Press ctrl+L (by default). +- A hint indicating the mode switch will appear in the top right corner. -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 3. Dependencies `ace_common` diff --git a/documentation/feature/logistics_uavbattery.md b/documentation/feature/logistics_uavbattery.md index 64f4775e46..a63a13cf4e 100644 --- a/documentation/feature/logistics_uavbattery.md +++ b/documentation/feature/logistics_uavbattery.md @@ -6,21 +6,17 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +### 1.1 Rechargeable darters. +Adds an item `ACE_UAVBattery` that allows refuelling/recharging of the "Darter" quadcopter UAVs. -### Sub-feature 2 -Short description of sub-feature 2. +## 2. Usage +### 2.1 Recharging the darter +- For this you need a `UAV battery` and the UAV needs to be a quadcopter. +- INTERACTION LAYER NOT IMPLEMENTED YET TO BE COMPLETED. -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 3. Dependencies `ace_interaction` diff --git a/documentation/feature/logistics_wirecutter.md b/documentation/feature/logistics_wirecutter.md index dccf8d91cb..db93c85836 100644 --- a/documentation/feature/logistics_wirecutter.md +++ b/documentation/feature/logistics_wirecutter.md @@ -6,21 +6,19 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +### 1.1 Wirecutter +Adds an item `ACE_wirecutter` that allows cutting of fences in A3 and AiA maps. -### Sub-feature 2 -Short description of sub-feature 2. +## 2. Usage +### 2.1 Using the wirecutter +- For this you need a `Wirecutter`. +- Approach the fence you want to cut. +- Press the interaction key left windows (by default). +- Find the interaction point and select `cut fence` (the only option). -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 3. Dependencies `ace_interaction` diff --git a/documentation/feature/magazinerepack.md b/documentation/feature/magazinerepack.md index 70cea9ac13..cc78dd1a00 100644 --- a/documentation/feature/magazinerepack.md +++ b/documentation/feature/magazinerepack.md @@ -6,20 +6,20 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Repacking magazines -Adds ability to repack magazines of the same type. An optional module provides -options to adjust the repacking time of single rounds and whole magazines to -the mission maker. +### 1.1 Repacking magazines +Adds the ability to repack magazines of the same type. -## Usage +## 2. Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. +### 2.1 Repacking +- For this you need multiple half empty mags of the same type. +- Press the self interaction button ctrl+left windows (by default). +- Select `Repack magazines`. +- Select the type of magazines you want to repack. - -## Dependencies +## 3. Dependencies `ace_interaction` diff --git a/documentation/feature/main.md b/documentation/feature/main.md index d5005ef163..3bfecf852a 100644 --- a/documentation/feature/main.md +++ b/documentation/feature/main.md @@ -6,13 +6,13 @@ group: feature parent: wiki --- -## Overview +## 1. Overview Main module which acts as the ACE core module. -## Dependencies +## 2. Dependencies -Arma 3 and CBA +`Arma 3` and `CBA (RC6 minimum)` -Note: Note: The Main module is required by all other modules. Do not disable it! +Note: The Main module is required by all other modules. Do not disable it! diff --git a/documentation/feature/map.md b/documentation/feature/map.md index 116d87eba1..b9dbb53c3b 100644 --- a/documentation/feature/map.md +++ b/documentation/feature/map.md @@ -6,21 +6,28 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +### 1.1 Map styling +Better map styling (contours, legend, hiding bushes and trees, etc). -### Sub-feature 2 -Short description of sub-feature 2. +### 1.2 Map zoom level (optional) +The mission maker / server owner can restrict the maximum zoom level of the map. + +### 1.3 Map shake (optional) +While walking your map will move all around the place. + +### 1.4 Map illumination (optional) +The map illumination will be the same as your surroundings meaning that in a dark night you'll either need a lightsource or NVGs to see your map. + +### 1.5 Blufor tracker (optional) +With blufor tracker you'll never loose your leader anymore, it marks the position of your faction group leader on the map. -## Usage +## 2. Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. +- IMPORTANT NOTICE: The (optional) features above CAN be restricted by the mission maker / server owner. User experience may vary. - -## Dependencies +## 3. Dependencies `ace_interaction` diff --git a/documentation/feature/maptools.md b/documentation/feature/maptools.md index 71508df3f3..81b3507db2 100644 --- a/documentation/feature/maptools.md +++ b/documentation/feature/maptools.md @@ -6,21 +6,33 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +### 1.1 Line drawing +This adds the possibility to draw accurate lines. -### Sub-feature 2 -Short description of sub-feature 2. +### 1.2 Map tools +This adds map tools that can be used to measure distances between two points on the map or bearings. + +### 1.3 GPS on map +If you are equipped with a vanilla GPS it will be shown on the map. (You don't need the map tools in your inventory for this.) + +## 2. Usage + +### 2.1 Using map tools +- For this you need to have `Map Tools`. +- Open the map M (by default). +- Press the self interaction key ctrl+left windows (by default). +- Select `Map tools`. +- Select the type of tools you want to use. +- Note that you can drag the Roamer (map tool) around with LMB and rotate it with ctrl+LMB . + +### 2.2 Drawing lines +- To draw lines `Map Tools` are not required. +- Press alt+left click (by default) to start the line, left click again to end it. +- To delete a line simply press delete around the center of the line. -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 3. Dependencies `ace_interaction` diff --git a/documentation/feature/markers.md b/documentation/feature/markers.md index a63adf89b7..c9e27b6a6d 100644 --- a/documentation/feature/markers.md +++ b/documentation/feature/markers.md @@ -6,18 +6,11 @@ group: feature parent: wiki --- -## Overview +## 1. Overview -### Improved marker placement +### 1.1 Improved marker placement Expands the "Insert Marker" menu and allows to rotate map markers. Shows the currently selected channel to prevent misplacement. - -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 2. Dependencies `ace_common` From 725b1447e7d4a5308da276d8129e26c3da562dbd Mon Sep 17 00:00:00 2001 From: BullHorn Date: Mon, 18 May 2015 00:07:26 +0300 Subject: [PATCH 020/140] Doc: Weather explanation Add note for players explaining weather sync Add notes for mission makers explaining synergy between propagation and weather variables --- documentation/feature/weather.md | 2 +- documentation/missionmaker/modules.md | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/documentation/feature/weather.md b/documentation/feature/weather.md index d2330ed69b..284b5627fd 100644 --- a/documentation/feature/weather.md +++ b/documentation/feature/weather.md @@ -8,7 +8,7 @@ parent: wiki ## 1. Overview -ACE3 Weather is enabled by default. This feature simulates realistic weather according to map location, time of day, date, etc. +ACE3 Weather is enabled by default. This feature simulates realistic weather according to map location, time of day, date, etc and makes sure every player experiences the same weather effects. ## 2. Usage diff --git a/documentation/missionmaker/modules.md b/documentation/missionmaker/modules.md index 473fd04a9f..37ae31e4cf 100644 --- a/documentation/missionmaker/modules.md +++ b/documentation/missionmaker/modules.md @@ -322,8 +322,16 @@ This module allows you to customize the weather settings. 1. **Weather propagation (Boolean)**
Enables sever side weather propagation.
`Default value: Yes` +
+
Note:
+

This feature is responsible for synchronizing weather between all clients. Disabling it is not recommended.

+
2. **ACE3 Weather (Boolean)**
Overrides the default weather with ACE3 weather (map based).
+
+
Note:
+

This feature can be disabled without affecting the weather propagation above. Useful if you prefer changing weather settings manually.

+
`Default value: Yes` 3. **Sync Rain (Boolean)**
Synchronizes rain.
From 08afd3e4e546015aaf7fe6d953f694f7bf730c42 Mon Sep 17 00:00:00 2001 From: BullHorn Date: Mon, 18 May 2015 00:18:13 +0300 Subject: [PATCH 021/140] Docs: modules.md remove redundant word --- documentation/missionmaker/modules.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/missionmaker/modules.md b/documentation/missionmaker/modules.md index 37ae31e4cf..93af598761 100644 --- a/documentation/missionmaker/modules.md +++ b/documentation/missionmaker/modules.md @@ -324,13 +324,13 @@ Enables sever side weather propagation.
`Default value: Yes`
Note:
-

This feature is responsible for synchronizing weather between all clients. Disabling it is not recommended.

+

This is responsible for synchronizing weather between all clients. Disabling it is not recommended.

2. **ACE3 Weather (Boolean)**
Overrides the default weather with ACE3 weather (map based).
Note:
-

This feature can be disabled without affecting the weather propagation above. Useful if you prefer changing weather settings manually.

+

This can be disabled without affecting the weather propagation above. Useful if you prefer changing weather settings manually.

`Default value: Yes` 3. **Sync Rain (Boolean)**
From 455f3fc75c40b9174712b0fd3fe1dbe9d7700a03 Mon Sep 17 00:00:00 2001 From: ulteq Date: Sun, 17 May 2015 23:34:12 +0200 Subject: [PATCH 022/140] Fixed a typo --- documentation/missionmaker/modules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/missionmaker/modules.md b/documentation/missionmaker/modules.md index 93af598761..9712977cd0 100644 --- a/documentation/missionmaker/modules.md +++ b/documentation/missionmaker/modules.md @@ -328,11 +328,11 @@ Enables sever side weather propagation.
2. **ACE3 Weather (Boolean)**
Overrides the default weather with ACE3 weather (map based).
+`Default value: Yes`
Note:

This can be disabled without affecting the weather propagation above. Useful if you prefer changing weather settings manually.

-`Default value: Yes` 3. **Sync Rain (Boolean)**
Synchronizes rain.
`Default value: Yes` From 53d6d4578bcd52c4ce0f15d5e446e931ae7e37ff Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Sun, 17 May 2015 17:21:31 -0500 Subject: [PATCH 023/140] Explosives - Fix UBC Updating base class PipeBombBase->IEDUrbanBig_Remote_Ammo, by z\addons\ace\explosives\config.cpp/CfgAmmo/IEDLandBig_Remote_Ammo/ Updating base class PipeBombBase->IEDUrbanSmall_Remote_Ammo, by z\addons\ace\explosives\config.cpp/CfgAmmo/IEDLandSmall_Remote_Ammo/ --- addons/explosives/CfgAmmo.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/explosives/CfgAmmo.hpp b/addons/explosives/CfgAmmo.hpp index 1471eb7e1e..c6d70bc64a 100644 --- a/addons/explosives/CfgAmmo.hpp +++ b/addons/explosives/CfgAmmo.hpp @@ -75,7 +75,7 @@ class CfgAmmo { triggerWhenDestroyed = 1; soundTrigger[] = {"A3\Sounds_F\weapons\mines\mech_trigger_1", 0.562341, 1, 40}; }; - class IEDLandBig_Remote_Ammo: IEDUrbanBig_Remote_Ammo { + class IEDLandBig_Remote_Ammo: PipeBombBase { mineTrigger = "RangeTrigger"; triggerWhenDestroyed = 1; soundTrigger[] = {"A3\Sounds_F\weapons\mines\mech_trigger_1", 0.562341, 1, 40}; @@ -85,7 +85,7 @@ class CfgAmmo { triggerWhenDestroyed = 1; soundTrigger[] = {"A3\Sounds_F\weapons\mines\mech_trigger_1", 0.562341, 1, 40}; }; - class IEDLandSmall_Remote_Ammo: IEDUrbanSmall_Remote_Ammo { + class IEDLandSmall_Remote_Ammo: PipeBombBase { mineTrigger = "RangeTrigger"; triggerWhenDestroyed = 1; soundTrigger[] = {"A3\Sounds_F\weapons\mines\mech_trigger_1", 0.562341, 1, 40}; From 04150ee4859126e4b1eef20722300248545a7d8e Mon Sep 17 00:00:00 2001 From: BullHorn Date: Mon, 18 May 2015 01:39:48 +0300 Subject: [PATCH 024/140] Docs: proofread #1 Proofread AB, AI, Aircraft, Attach, Backpacks, Ballistics and Captives Fix typos, grammar, inconsistencies Not fully satisfied with captives, will reiterate --- documentation/feature/advanced_ballistics.md | 8 ++-- documentation/feature/ai.md | 4 +- documentation/feature/aircraft.md | 8 ++-- documentation/feature/attach.md | 8 ++-- documentation/feature/backpacks.md | 4 +- documentation/feature/ballistics.md | 42 +++++++++++--------- documentation/feature/captives.md | 7 ++-- 7 files changed, 42 insertions(+), 39 deletions(-) diff --git a/documentation/feature/advanced_ballistics.md b/documentation/feature/advanced_ballistics.md index bbdf440fec..d84f2b69b2 100644 --- a/documentation/feature/advanced_ballistics.md +++ b/documentation/feature/advanced_ballistics.md @@ -1,13 +1,13 @@ --- layout: wiki title: Advanced Ballistics -description: The advanced ballistics module improves internal- and external ballistics. +description: The advanced ballistics module improves internal and external ballistics. group: feature parent: wiki --- ## 1. Overview -The advanced ballistics module improves internal- and external ballistics. +The Advanced Ballistics module improves internal and external ballistics. ## 2. Features - Drag modeling based on real-world ballistic coefficients. @@ -17,8 +17,8 @@ The advanced ballistics module improves internal- and external ballistics. - Terrain features, buildings and other objects disrupt the wind. - [Magnus effect](https://en.wikipedia.org/wiki/Magnus_effect) (spin drift) - [Coriolis effect](https://en.wikipedia.org/wiki/Coriolis_effect) and [Eötvös effect](https://en.wikipedia.org/wiki/Eotvos_effect) (Earth rotation) -- Loss of stability during transonic flight -- Variable muzzle velocity based on on powder burn rate and barrel length +- Loss of stability during transonic flight. +- Variable muzzle velocity based on powder burn rate and barrel length. - Bullet trace effect for supersonic bullets (light refraction due to air pressure waves). - A protractor for quickly measuring the inclination angle. diff --git a/documentation/feature/ai.md b/documentation/feature/ai.md index 81dd52d895..00ef799531 100644 --- a/documentation/feature/ai.md +++ b/documentation/feature/ai.md @@ -1,7 +1,7 @@ --- layout: wiki title: AI (Artifical Intelligence) -description: +description: Config based changes to AI to ensure compatibility with advanced AI modifications group: feature order: 5 parent: wiki @@ -14,7 +14,7 @@ The idea here is to reduce the AI's godlike aiming capabilties while retaining i Note: All these values can still be adjusted via scripts, these arrays just change what 0 & 1 are for setSkill. ### 1.2 Firing in burst mode -AIs will now use the automatic mode of their weapons on short distances, instead of always relying on firing single shots in quick succession. +AI will now use the automatic mode of their weapons at short distances, instead of always relying on firing single shots in quick succession. ### 1.3 Longer engagement ranges The maximum engagement ranges are increased: AI will fire in bursts with variable length on high ranges of 500 - 700 meters, depending on their weapon and optic. diff --git a/documentation/feature/aircraft.md b/documentation/feature/aircraft.md index 19aec0337c..7519c5c130 100644 --- a/documentation/feature/aircraft.md +++ b/documentation/feature/aircraft.md @@ -1,7 +1,7 @@ --- layout: wiki title: Aircraft -description: +description: Changes the flight behaviour of various aircraft group: feature order: 5 parent: wiki @@ -18,10 +18,10 @@ Changes the flight behaviour of various aircraft. - AP rockets have less splash damage. ### 1.3 Missile lock warnings -Adds missile-lock warning systems to helicopters and planes based on the various real life capabilities. +Adds missile-lock warning systems to helicopters and planes based on the equivalent real life capabilities. ### 1.4 Semi-automatic flare mode -Adds the semi-automatic flare mode known from Arma 2. The key to switch the mode still exists in Arma 3's key settings, but is unused. +Adds the semi-automatic flare mode known from Arma 2. The key to switch modes existed in Arma 3's key settings, but wasn't operational until now. ### 1.5 Ejecting from pilot and copilot seats Pilots and copilots of all helicopters can now eject. @@ -32,8 +32,6 @@ Adds a laser marker to the copilot seat of the Wildcat. ### 1.7 HUD for AH-9 Adds a HUD to the AH-9 based on the Comanche's HUD. -## 1.8 Adjusted flight behaviour -Changes the flight behaviour of various aircraft. ## 2. Usage diff --git a/documentation/feature/attach.md b/documentation/feature/attach.md index fafe4bf501..22820f1e7a 100644 --- a/documentation/feature/attach.md +++ b/documentation/feature/attach.md @@ -1,7 +1,7 @@ --- layout: wiki title: Attach -description: +description: Allows players to attach items to objects group: feature parent: wiki --- @@ -19,17 +19,17 @@ Adds an attachable IR strobe, which is only visible using night vision devices a ## 2. Usage ### 2.1 Attaching to yourself -- Self interact left windows (by default). +- Self interact left windows . - Choose `equipment`. - Choose `attach item`. - Select which item you want to attach. -- Same thing to detach. +- Repeat to detach. ### 2.2 attaching to a vehicle - Interact with the vehicle ctrl+left windows . - Choose `attach item`. - Select your item and follow the instructions on the screen. -- To detach the item it's the same as placing it, use the interaction key from outside the vehicle. +- Repeat to detach. ## 3. Dependencies diff --git a/documentation/feature/backpacks.md b/documentation/feature/backpacks.md index aedfb37d6a..9fcfce6b3b 100644 --- a/documentation/feature/backpacks.md +++ b/documentation/feature/backpacks.md @@ -1,7 +1,7 @@ --- layout: wiki title: Backpacks -description: +description: Notifies a player when his backpack is opened group: feature parent: wiki --- @@ -9,7 +9,7 @@ parent: wiki ## 1. Overview ### 1.1 Zipping sounds -A zipper sound rings out, if someone tries to open your backpack. This helps to prevent banana theft. +A zipper sound rings out when someone tries to open your backpack. This helps to prevent banana theft. ## 2. Dependencies diff --git a/documentation/feature/ballistics.md b/documentation/feature/ballistics.md index cd44e618ba..6df71050ff 100644 --- a/documentation/feature/ballistics.md +++ b/documentation/feature/ballistics.md @@ -1,35 +1,39 @@ --- layout: wiki title: Ballistics -description: +description: Realistic ballistic improvements group: feature +order: 5 parent: wiki --- -# Overview -## Realistic ballistics +## 1. Overview + +### 1.1 Realistic ballistics Changes include adjusted muzzle velocity, air friction and dispersion based on real life values. -## Weaker body armor -Decreases protection values of vests, CSAT uniforms and various campaign only gear to levels comparable to Arma 2. +### 1.2 Weaker body armor +Decreases protection values of vests, CSAT uniforms and various campaign only gear to better represent realism. -## Realistic silencers and subsonic ammunition -Silencers no longer decrease the muzzle velocity and are generally less effective when used with normal ammunition. They now only remove the muzzle blast and flash. To prevent the crack caused by supersonic projectiles, ACE introduces subsonic ammunition for the 7.62mm caliber. This is also fully compatible with AI. +### 1.3 Realistic silencers and subsonic ammunition +Silencers no longer decrease the muzzle velocity and are generally less effective when used with normal ammunition. They now only remove the muzzle blast and flash. To prevent the crack caused by supersonic projectiles, ACE3 introduces subsonic ammunition for the 7.62mm caliber. This is also fully compatible with AI. -## Armour piercing ammunition -Armour piercing rounds have higher penetration values against light armoured targets or other obstacles on the battlefield. Their drawback is a slightly decreased man-stopping power. AP rounds are available in multiple calibers incudling 5.56mm and 7.62mm. - -## IR-Dim tracer ammunition -IR-Dim ammunition is similar to tracer rounds, but their tracers are only visible using night vision devices. - -## M118 long range ammunition -The M14 EBR now uses ammunition with decreased muzzle velocity and air friction to improve precision and energy retention at long ranges. - -## Flash suppressors +### 1.4 Flash suppressors Flash suppressors are similar to sound suppressors and prevent the muzzle flash from reducing visibility without decreasing combat effectiveness. Flash suppressors are available for the calibers 5.56mm, 6.5mm, 7.62mm, .45 ACP and 9mm. -## Fully config-based +### 1.5 Armour piercing ammunition +Armour piercing rounds have higher penetration values against light armoured targets and other obstacles on the battlefield. Their drawback is a slightly decreased man-stopping power. AP rounds are available in multiple calibers incudling 5.56mm and 7.62mm. + +### 1.6 IR-Dim tracer ammunition +IR-Dim ammunition is similar to tracer rounds, but their tracers are only visible using night vision devices. + +### 1.7 M118 long range ammunition +The M14 EBR now uses ammunition with decreased muzzle velocity and air friction to improve precision and energy retention at long ranges. + +### 1.8 Fully config-based This module uses configuration changes only and does not decrease game performance. -# Dependencies + +## 2. Dependencies + `ace_common` diff --git a/documentation/feature/captives.md b/documentation/feature/captives.md index 398210781e..af68e2af1e 100644 --- a/documentation/feature/captives.md +++ b/documentation/feature/captives.md @@ -1,7 +1,7 @@ --- layout: wiki title: Captives -description: +description: System for taking and handling captives group: feature parent: wiki --- @@ -12,7 +12,7 @@ parent: wiki Introduces a captivity system for taking and moving prisoners. ### 1.2 Load and unload captives into / from vehicles -You can load and unload captives from vehicles using ACE 3 interactions. +You can load and unload captives from vehicles using ACE3 interactions. ### 1.3 Frisk captives You can frisk a restrained captive. @@ -20,6 +20,7 @@ You can frisk a restrained captive. ### 1.4 Surrendering You can surrender. While surrendering AI will cease fire. + ## 2. Usage ### 2.1 Capturing someone @@ -33,7 +34,7 @@ You can surrender. While surrendering AI will cease fire. - Select the escort prisoner option. - To stop escorting just scroll down and select `release` or use self interaction ctrl+left windows (by default) and select `release`. -### 2.3 Loading and unloading a captive in vehicle +### 2.3 Loading and unloading a captive into/from a vehicle - Escort the person. - Approach the vehicle you desire to load the captive in. - Interact with the vehicle left windows (by default) and load him. From 979d2673a17f6047014d9427ff8451e6c1b04a73 Mon Sep 17 00:00:00 2001 From: BullHorn Date: Mon, 18 May 2015 01:39:48 +0300 Subject: [PATCH 025/140] Docs: proofread, 1st iteration Proofread AB, AI, Aircraft, Attach, Backpacks, Ballistics and Captives Fix typos, grammar, inconsistencies Not fully satisfied with captives, will reiterate --- documentation/feature/advanced_ballistics.md | 8 ++-- documentation/feature/ai.md | 4 +- documentation/feature/aircraft.md | 8 ++-- documentation/feature/attach.md | 8 ++-- documentation/feature/backpacks.md | 4 +- documentation/feature/ballistics.md | 42 +++++++++++--------- documentation/feature/captives.md | 7 ++-- 7 files changed, 42 insertions(+), 39 deletions(-) diff --git a/documentation/feature/advanced_ballistics.md b/documentation/feature/advanced_ballistics.md index bbdf440fec..d84f2b69b2 100644 --- a/documentation/feature/advanced_ballistics.md +++ b/documentation/feature/advanced_ballistics.md @@ -1,13 +1,13 @@ --- layout: wiki title: Advanced Ballistics -description: The advanced ballistics module improves internal- and external ballistics. +description: The advanced ballistics module improves internal and external ballistics. group: feature parent: wiki --- ## 1. Overview -The advanced ballistics module improves internal- and external ballistics. +The Advanced Ballistics module improves internal and external ballistics. ## 2. Features - Drag modeling based on real-world ballistic coefficients. @@ -17,8 +17,8 @@ The advanced ballistics module improves internal- and external ballistics. - Terrain features, buildings and other objects disrupt the wind. - [Magnus effect](https://en.wikipedia.org/wiki/Magnus_effect) (spin drift) - [Coriolis effect](https://en.wikipedia.org/wiki/Coriolis_effect) and [Eötvös effect](https://en.wikipedia.org/wiki/Eotvos_effect) (Earth rotation) -- Loss of stability during transonic flight -- Variable muzzle velocity based on on powder burn rate and barrel length +- Loss of stability during transonic flight. +- Variable muzzle velocity based on powder burn rate and barrel length. - Bullet trace effect for supersonic bullets (light refraction due to air pressure waves). - A protractor for quickly measuring the inclination angle. diff --git a/documentation/feature/ai.md b/documentation/feature/ai.md index 81dd52d895..00ef799531 100644 --- a/documentation/feature/ai.md +++ b/documentation/feature/ai.md @@ -1,7 +1,7 @@ --- layout: wiki title: AI (Artifical Intelligence) -description: +description: Config based changes to AI to ensure compatibility with advanced AI modifications group: feature order: 5 parent: wiki @@ -14,7 +14,7 @@ The idea here is to reduce the AI's godlike aiming capabilties while retaining i Note: All these values can still be adjusted via scripts, these arrays just change what 0 & 1 are for setSkill. ### 1.2 Firing in burst mode -AIs will now use the automatic mode of their weapons on short distances, instead of always relying on firing single shots in quick succession. +AI will now use the automatic mode of their weapons at short distances, instead of always relying on firing single shots in quick succession. ### 1.3 Longer engagement ranges The maximum engagement ranges are increased: AI will fire in bursts with variable length on high ranges of 500 - 700 meters, depending on their weapon and optic. diff --git a/documentation/feature/aircraft.md b/documentation/feature/aircraft.md index 19aec0337c..7519c5c130 100644 --- a/documentation/feature/aircraft.md +++ b/documentation/feature/aircraft.md @@ -1,7 +1,7 @@ --- layout: wiki title: Aircraft -description: +description: Changes the flight behaviour of various aircraft group: feature order: 5 parent: wiki @@ -18,10 +18,10 @@ Changes the flight behaviour of various aircraft. - AP rockets have less splash damage. ### 1.3 Missile lock warnings -Adds missile-lock warning systems to helicopters and planes based on the various real life capabilities. +Adds missile-lock warning systems to helicopters and planes based on the equivalent real life capabilities. ### 1.4 Semi-automatic flare mode -Adds the semi-automatic flare mode known from Arma 2. The key to switch the mode still exists in Arma 3's key settings, but is unused. +Adds the semi-automatic flare mode known from Arma 2. The key to switch modes existed in Arma 3's key settings, but wasn't operational until now. ### 1.5 Ejecting from pilot and copilot seats Pilots and copilots of all helicopters can now eject. @@ -32,8 +32,6 @@ Adds a laser marker to the copilot seat of the Wildcat. ### 1.7 HUD for AH-9 Adds a HUD to the AH-9 based on the Comanche's HUD. -## 1.8 Adjusted flight behaviour -Changes the flight behaviour of various aircraft. ## 2. Usage diff --git a/documentation/feature/attach.md b/documentation/feature/attach.md index fafe4bf501..22820f1e7a 100644 --- a/documentation/feature/attach.md +++ b/documentation/feature/attach.md @@ -1,7 +1,7 @@ --- layout: wiki title: Attach -description: +description: Allows players to attach items to objects group: feature parent: wiki --- @@ -19,17 +19,17 @@ Adds an attachable IR strobe, which is only visible using night vision devices a ## 2. Usage ### 2.1 Attaching to yourself -- Self interact left windows (by default). +- Self interact left windows . - Choose `equipment`. - Choose `attach item`. - Select which item you want to attach. -- Same thing to detach. +- Repeat to detach. ### 2.2 attaching to a vehicle - Interact with the vehicle ctrl+left windows . - Choose `attach item`. - Select your item and follow the instructions on the screen. -- To detach the item it's the same as placing it, use the interaction key from outside the vehicle. +- Repeat to detach. ## 3. Dependencies diff --git a/documentation/feature/backpacks.md b/documentation/feature/backpacks.md index aedfb37d6a..9fcfce6b3b 100644 --- a/documentation/feature/backpacks.md +++ b/documentation/feature/backpacks.md @@ -1,7 +1,7 @@ --- layout: wiki title: Backpacks -description: +description: Notifies a player when his backpack is opened group: feature parent: wiki --- @@ -9,7 +9,7 @@ parent: wiki ## 1. Overview ### 1.1 Zipping sounds -A zipper sound rings out, if someone tries to open your backpack. This helps to prevent banana theft. +A zipper sound rings out when someone tries to open your backpack. This helps to prevent banana theft. ## 2. Dependencies diff --git a/documentation/feature/ballistics.md b/documentation/feature/ballistics.md index cd44e618ba..6df71050ff 100644 --- a/documentation/feature/ballistics.md +++ b/documentation/feature/ballistics.md @@ -1,35 +1,39 @@ --- layout: wiki title: Ballistics -description: +description: Realistic ballistic improvements group: feature +order: 5 parent: wiki --- -# Overview -## Realistic ballistics +## 1. Overview + +### 1.1 Realistic ballistics Changes include adjusted muzzle velocity, air friction and dispersion based on real life values. -## Weaker body armor -Decreases protection values of vests, CSAT uniforms and various campaign only gear to levels comparable to Arma 2. +### 1.2 Weaker body armor +Decreases protection values of vests, CSAT uniforms and various campaign only gear to better represent realism. -## Realistic silencers and subsonic ammunition -Silencers no longer decrease the muzzle velocity and are generally less effective when used with normal ammunition. They now only remove the muzzle blast and flash. To prevent the crack caused by supersonic projectiles, ACE introduces subsonic ammunition for the 7.62mm caliber. This is also fully compatible with AI. +### 1.3 Realistic silencers and subsonic ammunition +Silencers no longer decrease the muzzle velocity and are generally less effective when used with normal ammunition. They now only remove the muzzle blast and flash. To prevent the crack caused by supersonic projectiles, ACE3 introduces subsonic ammunition for the 7.62mm caliber. This is also fully compatible with AI. -## Armour piercing ammunition -Armour piercing rounds have higher penetration values against light armoured targets or other obstacles on the battlefield. Their drawback is a slightly decreased man-stopping power. AP rounds are available in multiple calibers incudling 5.56mm and 7.62mm. - -## IR-Dim tracer ammunition -IR-Dim ammunition is similar to tracer rounds, but their tracers are only visible using night vision devices. - -## M118 long range ammunition -The M14 EBR now uses ammunition with decreased muzzle velocity and air friction to improve precision and energy retention at long ranges. - -## Flash suppressors +### 1.4 Flash suppressors Flash suppressors are similar to sound suppressors and prevent the muzzle flash from reducing visibility without decreasing combat effectiveness. Flash suppressors are available for the calibers 5.56mm, 6.5mm, 7.62mm, .45 ACP and 9mm. -## Fully config-based +### 1.5 Armour piercing ammunition +Armour piercing rounds have higher penetration values against light armoured targets and other obstacles on the battlefield. Their drawback is a slightly decreased man-stopping power. AP rounds are available in multiple calibers incudling 5.56mm and 7.62mm. + +### 1.6 IR-Dim tracer ammunition +IR-Dim ammunition is similar to tracer rounds, but their tracers are only visible using night vision devices. + +### 1.7 M118 long range ammunition +The M14 EBR now uses ammunition with decreased muzzle velocity and air friction to improve precision and energy retention at long ranges. + +### 1.8 Fully config-based This module uses configuration changes only and does not decrease game performance. -# Dependencies + +## 2. Dependencies + `ace_common` diff --git a/documentation/feature/captives.md b/documentation/feature/captives.md index 398210781e..af68e2af1e 100644 --- a/documentation/feature/captives.md +++ b/documentation/feature/captives.md @@ -1,7 +1,7 @@ --- layout: wiki title: Captives -description: +description: System for taking and handling captives group: feature parent: wiki --- @@ -12,7 +12,7 @@ parent: wiki Introduces a captivity system for taking and moving prisoners. ### 1.2 Load and unload captives into / from vehicles -You can load and unload captives from vehicles using ACE 3 interactions. +You can load and unload captives from vehicles using ACE3 interactions. ### 1.3 Frisk captives You can frisk a restrained captive. @@ -20,6 +20,7 @@ You can frisk a restrained captive. ### 1.4 Surrendering You can surrender. While surrendering AI will cease fire. + ## 2. Usage ### 2.1 Capturing someone @@ -33,7 +34,7 @@ You can surrender. While surrendering AI will cease fire. - Select the escort prisoner option. - To stop escorting just scroll down and select `release` or use self interaction ctrl+left windows (by default) and select `release`. -### 2.3 Loading and unloading a captive in vehicle +### 2.3 Loading and unloading a captive into/from a vehicle - Escort the person. - Approach the vehicle you desire to load the captive in. - Interact with the vehicle left windows (by default) and load him. From 1e7e5c7aa52eb88993496fcf4db8a69c9c90cec1 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Sun, 17 May 2015 17:52:56 -0500 Subject: [PATCH 026/140] Don't show passenger actions for UAV crew --- addons/interaction/functions/fnc_addPassengersActions.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/interaction/functions/fnc_addPassengersActions.sqf b/addons/interaction/functions/fnc_addPassengersActions.sqf index 7a7d8618d1..7ee56415bf 100644 --- a/addons/interaction/functions/fnc_addPassengersActions.sqf +++ b/addons/interaction/functions/fnc_addPassengersActions.sqf @@ -25,7 +25,7 @@ _actions = []; { private ["_unit"]; _unit = _x; - if (_unit != _player) then { + if ((_unit != _player) && {(getText (configFile >> "CfgVehicles" >> (typeOf _x) >> "simulation")) != "UAVPilot"}) then { _actions pushBack [ [ From 9db69add695438d15e7cdf7686afe819616967d2 Mon Sep 17 00:00:00 2001 From: bux578 Date: Mon, 18 May 2015 09:56:42 +0200 Subject: [PATCH 027/140] fix settings.md formatting --- documentation/framework/settings.md | 62 +++++++++++++++-------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/documentation/framework/settings.md b/documentation/framework/settings.md index 8a9acfdb8c..6cccb93718 100644 --- a/documentation/framework/settings.md +++ b/documentation/framework/settings.md @@ -16,40 +16,42 @@ Part of this settings framework are global settings and client settings. Both us Settings are entries in the config that get translated to `missionnamespace` global variables. An example settings entry looks like this: -``` - class ACE_module_sampleSetting { - // Value - value = 1; - - // Type (SCALAR, BOOL, STRING, ARRAY, COLOR) - typeName = "SCALAR"; - - // Force the setting? - force = 0; - - // Does it appear on the options menu? - isClientSettable = 1; - - // The following settings only apply when isClientSettable == 1 - // Stringtable entry with the setting name - displayName = "$STR_ACE_Common_SettingName"; - - // Stringtable entry with the setting description - description = "$STR_ACE_Common_SettingDescription"; - - // Stringtable entries that describe the options - // Only applies if typeName == "SCALAR"; and is optional - values[] = {"Disabled", "Enabled", "Only Cursor", "Only On Keypress", "Only Cursor and KeyPress"}; - }; +```c++ +class ACE_module_sampleSetting { + // Value + value = 1; + + // Type (SCALAR, BOOL, STRING, ARRAY, COLOR) + typeName = "SCALAR"; + + // Force the setting? + force = 0; + + // Does it appear on the options menu? + isClientSettable = 1; + + // The following settings only apply when isClientSettable == 1 + // Stringtable entry with the setting name + displayName = "$STR_ACE_Common_SettingName"; + + // Stringtable entry with the setting description + description = "$STR_ACE_Common_SettingDescription"; + + // Stringtable entries that describe the options + // Only applies if typeName == "SCALAR"; and is optional + values[] = {"Disabled", "Enabled", "Only Cursor", "Only On Keypress", "Only Cursor and KeyPress"}; +}; ``` Settings are defined from the mods config but can be adjusted through the following methods: + * Optional config entries * Mission side modules ## 2. Load order The load order for the settings are: + * 1. Mod Config * 2. Server Config * 3. Mission config @@ -59,18 +61,18 @@ What this means is that at any the 3 points after the mod config it is possible ## 3. How do I use them? -In the 'how do they work' chapter an example of settings was shown. This is the same for any settings config. The only difference is the location. For ACE modules, the settings are placed in the class `ACE_settings`. The same goes for the mission config. +In the 'how do they work' chapter an example of settings was shown. This is the same for any settings config. The only difference is the location. For ACE3 modules, the settings are placed in the class `ACE_settings`. The same goes for the mission config. -The server config setting entries are done through our optional ACE_server.pbo, which can be found in the optionals folder of @ace. It also contains a userconfig folder, which inside contains the file ace\serverconfig.hpp. This is the location ACE settings are placed. There is no need for a sub class. +The server config setting entries are done through our optional ACE_server.pbo, which can be found in the optionals folder of @ace. It also contains a userconfig folder, which inside contains the file ace\serverconfig.hpp. This is the location ACE3 settings are placed. There is no need for a sub class. ### 3.1 Getting all the settings! -ACE contains a lot of settings; to tweak everything to your liking manually therefor can be quite a task. We have provided the option to export all settings in single player. For this, follow these simple steps: +ACE3 contains a lot of settings; to tweak everything to your liking manually therefor can be quite a task. We have provided the option to export all settings in single player. For this, follow these simple steps: * Open the editor (Singleplayer). -* Under modules (f7), find ACE, `Config Export [ACE]`. +* Under modules (F7), find ACE, `Config Export [ACE]`. * Place down the module, ensure that the allow parameter is set to yes. -* Press preview, once in game, press Esc and open the ACE Options dialog (top left) +* Press preview, once in game, press Esc and open the ACE3 Options dialog (top left) * This is the dialog where you can modify client side settings. On the bottom left of it, you will now see a button called 'Config Export'. Press it and a new dialog opens. * You are now in the dialog that allows you to adjust all settings from ACE. Tweak this to your liking. * Once you are done tweaking, press the 'Export' button and all settings will be copied to your clipboard. From 5453baab47a814b2730f7b39d4e4ed5fac69a4c1 Mon Sep 17 00:00:00 2001 From: bux578 Date: Mon, 18 May 2015 10:04:52 +0200 Subject: [PATCH 028/140] overhaul settings.md --- documentation/framework/settings.md | 35 +++++++++++++++++------------ 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/documentation/framework/settings.md b/documentation/framework/settings.md index 6cccb93718..7b820e750c 100644 --- a/documentation/framework/settings.md +++ b/documentation/framework/settings.md @@ -52,37 +52,44 @@ Settings are defined from the mods config but can be adjusted through the follow The load order for the settings are: -* 1. Mod Config -* 2. Server Config +* 1. Mod config +* 2. Server config * 3. Mission config * 4. Placed down mission modules -What this means is that at any the 3 points after the mod config it is possible to insert your adjusted settings and force those (optionally). This is a powerful tool for server admins, whom can ensure that everyone is using uniform settings across the board on their server. And it provides mission makers the ability to easily set settings for their mission, without creating a large dependancy on ACE; you do not have to place down mission modules. +What this means is that at any the 3 points after the mod config it is possible to insert your adjusted settings and force those (optionally). This is a powerful tool for server admins, whom can ensure that everyone is using uniform settings across the board on their server. And it provides mission makers the ability to easily set settings for their mission, without creating a large dependency on ACE; you do not have to place down mission modules. ## 3. How do I use them? In the 'how do they work' chapter an example of settings was shown. This is the same for any settings config. The only difference is the location. For ACE3 modules, the settings are placed in the class `ACE_settings`. The same goes for the mission config. -The server config setting entries are done through our optional ACE_server.pbo, which can be found in the optionals folder of @ace. It also contains a userconfig folder, which inside contains the file ace\serverconfig.hpp. This is the location ACE3 settings are placed. There is no need for a sub class. +The server config setting entries are done through our optional ACE_server.pbo, which can be found in the optionals folder of @ace. It also contains a `userconfig` folder, which inside contains the file `ace\serverconfig.hpp`. This is the location ACE3 settings are placed. There is no need for a sub class. ### 3.1 Getting all the settings! -ACE3 contains a lot of settings; to tweak everything to your liking manually therefor can be quite a task. We have provided the option to export all settings in single player. For this, follow these simple steps: +ACE3 contains a lot of settings; for that reason tweaking everything to your liking manually can be quite a task. We have provided the option to export all settings in the editor. For this, follow these simple steps: * Open the editor (Singleplayer). * Under modules (F7), find ACE, `Config Export [ACE]`. * Place down the module, ensure that the allow parameter is set to yes. -* Press preview, once in game, press Esc and open the ACE3 Options dialog (top left) -* This is the dialog where you can modify client side settings. On the bottom left of it, you will now see a button called 'Config Export'. Press it and a new dialog opens. -* You are now in the dialog that allows you to adjust all settings from ACE. Tweak this to your liking. -* Once you are done tweaking, press the 'Export' button and all settings will be copied to your clipboard. -* Paste the settings in your serverconfig.hpp file and done. +* Press preview, once in game, press Esc and open the ACE3 Options dialog (top left) +* This is the dialog where you can modify client side settings. On the bottom left of it, you will now see a button called `Config Export`. Press it and a new dialog opens. +* You are now in the dialog that allows you to adjust all settings from ACE3. Tweak this to your liking. +* Once you are done tweaking, press the `Export` button and all settings will be copied to your clipboard. +* Paste the settings in your `serverconfig.hpp` file and you're done. -Note that the format copied to your clipboard by this can also be used in the mission config, as long as they are in the class `ACE_Settings`. +Note that the format copied to your clipboard by this can also be used in the mission config (`description.ext`), as long as they are in the class `ACE_Settings`. -### 3.2 Loading up the serverconfig +```c++ +class ACE_Settings { + // add exported settings here +}; +``` -As stated before, the serverconfig gets loaded through the optional ACE_server.pbo. This pbo is only required (and should only be used on) the server - clients do not need to have this! It is for this reason we have not signed this pbo. -Load the ACE_server.pbo like any other addon you do on your server. Advised is to create an @aceServer mod folder and load that through `-serverMod=@aceServer`. +### 3.2 Loading up the server config + +As stated before, the server config gets loaded through the optional `ACE_server.pbo`. This PBO is only required (and should only be used) on the server - clients do not need to have this! It is for this reason we have not signed this PBO. + +Load the `ACE_server.pbo` like any other addon on your server. It is advised to create an `@aceServer` mod folder with an `addons` sub folder where you would paste the `ACE_server.pbo` and load that through `-serverMod=@aceServer`. From 4ed13fb3b13f75f3ab7426aff446b44540dc0370 Mon Sep 17 00:00:00 2001 From: bux578 Date: Mon, 18 May 2015 10:19:05 +0200 Subject: [PATCH 029/140] add "single-player" requirement --- documentation/framework/settings.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/framework/settings.md b/documentation/framework/settings.md index 7b820e750c..58208a873d 100644 --- a/documentation/framework/settings.md +++ b/documentation/framework/settings.md @@ -57,7 +57,7 @@ The load order for the settings are: * 3. Mission config * 4. Placed down mission modules -What this means is that at any the 3 points after the mod config it is possible to insert your adjusted settings and force those (optionally). This is a powerful tool for server admins, whom can ensure that everyone is using uniform settings across the board on their server. And it provides mission makers the ability to easily set settings for their mission, without creating a large dependency on ACE; you do not have to place down mission modules. +What this means is that at any the 3 points after the mod config it is possible to insert your adjusted settings and force those (optionally). This is a powerful tool for server admins, whom can ensure that everyone is using uniform settings across the board on their server. And it provides mission makers the ability to easily set settings for their mission, without creating a large dependency on ACE3; you do not have to place down mission modules. ## 3. How do I use them? @@ -67,9 +67,9 @@ The server config setting entries are done through our optional ACE_server.pbo, ### 3.1 Getting all the settings! -ACE3 contains a lot of settings; for that reason tweaking everything to your liking manually can be quite a task. We have provided the option to export all settings in the editor. For this, follow these simple steps: +ACE3 contains a lot of settings; for that reason tweaking everything to your liking manually can be quite a task. We have provided the option to export all settings in the editor (single-player). For this, follow these simple steps: -* Open the editor (Singleplayer). +* Open the editor (single-player). * Under modules (F7), find ACE, `Config Export [ACE]`. * Place down the module, ensure that the allow parameter is set to yes. * Press preview, once in game, press Esc and open the ACE3 Options dialog (top left) From 8eaf754fdd239ac74098308bc4bc3f448ee77be0 Mon Sep 17 00:00:00 2001 From: ulteq Date: Mon, 18 May 2015 10:56:34 +0200 Subject: [PATCH 030/140] Further increased the visibility of the bullet trace effect. --- addons/advanced_ballistics/functions/fnc_handleFired.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/advanced_ballistics/functions/fnc_handleFired.sqf b/addons/advanced_ballistics/functions/fnc_handleFired.sqf index 3567efc1bb..03f1d03d43 100644 --- a/addons/advanced_ballistics/functions/fnc_handleFired.sqf +++ b/addons/advanced_ballistics/functions/fnc_handleFired.sqf @@ -132,7 +132,7 @@ GVAR(currentbulletID) = (GVAR(currentbulletID) + 1) % 10000; }; if (_bulletTraceVisible && _bulletSpeed > 600) then { - drop ["\A3\data_f\ParticleEffects\Universal\Refract","","Billboard",1,0.1,getPos _bullet,[0,0,0],0,1.275,1,0,[sqrt(0.006*_caliber),sqrt(0.003*_caliber)],[[0,0,0,0.6],[0,0,0,0.4]],[1,0],0,0,"","",""]; + drop ["\A3\data_f\ParticleEffects\Universal\Refract","","Billboard",1,0.1,getPos _bullet,[0,0,0],0,1.275,1,0,[sqrt(0.006*_caliber),sqrt(0.003*_caliber)],[[0,0,0,0.75],[0,0,0,0.4]],[1,0],0,0,"","",""]; }; call compile ("ace_advanced_ballistics" callExtension format["simulate:%1:%2:%3:%4:%5:%6:%7", _index, _bulletVelocity, _bulletPosition, ACE_wind, ASLToATL(_bulletPosition) select 2, floor(time), time - floor(time)]); From fe1055bdbb0a4b45a4f9cdfca65580cffe8fd117 Mon Sep 17 00:00:00 2001 From: KoffeinFlummi Date: Mon, 18 May 2015 13:31:21 +0200 Subject: [PATCH 031/140] Fix list in devenv setup page --- .../development/setting-up-the-development-environment.md | 1 + 1 file changed, 1 insertion(+) diff --git a/documentation/development/setting-up-the-development-environment.md b/documentation/development/setting-up-the-development-environment.md index 3de25d3ea9..9a2880b319 100644 --- a/documentation/development/setting-up-the-development-environment.md +++ b/documentation/development/setting-up-the-development-environment.md @@ -87,6 +87,7 @@ File Patching allows you to change the files in an addon while the game is runni ### 7.1 Enabling File Patching There are two ways to enable file patching: + - Load cba_cache_disable.pbo (included in CBA's optional folder) - Add the following to your test missions description.ext: From d8b4b53b8086b85f0dc8970251dc47d30cfc6c87 Mon Sep 17 00:00:00 2001 From: jaynus Date: Mon, 18 May 2015 08:31:29 -0700 Subject: [PATCH 032/140] Added: Monitor 5sec interval to propegate assignedTeams from leader, allowing team colors to be assigned by the team leader and show in the group. Uses vanilla team assignment. Closes #1279 --- addons/nametags/XEH_postInit.sqf | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/addons/nametags/XEH_postInit.sqf b/addons/nametags/XEH_postInit.sqf index cea2025dcc..27f8cdae02 100644 --- a/addons/nametags/XEH_postInit.sqf +++ b/addons/nametags/XEH_postInit.sqf @@ -22,6 +22,41 @@ GVAR(ShowNamesTime) = -10; {false}, [29, [false, false, false]], false] call cba_fnc_addKeybind; //LeftControl Key +// Monitor the assigned teams, and propegate them appropriately for the player +// This allows for assigned team colors to match across the entire group +[{ + private["_leader", "_playerIsLeader", "_unitTeam"]; + if (alive ACE_player) then { + _leader = leader (group ACE_player); + _playerIsLeader = false; + + if(alive _leader) then { + if(_leader == ACE_player) then { + _playerIsLeader = true; + }; + }; + + if (_playerIsLeader) then { + { + if(alive _x) then { + _unitTeam = _x getVariable [QGVAR(teamAssignment),"MAIN"]; + if (_unitTeam != assignedTeam _x) then { + _x setVariable [QGVAR(teamAssignment), assignedTeam _x,true]; + }; + }; + } forEach units (group ACE_player); + } else { + { + if(alive _x) then { + _unitTeam = _x getVariable [QGVAR(teamAssignment),"MAIN"]; + if (_unitTeam != assignedTeam _x) then { + _x assignTeam _unitTeam; + }; + }; + } forEach units (group ACE_player); + }; + }; +}, 5, []] call CBA_fnc_addPerFrameHandler; // Draw handle addMissionEventHandler ["Draw3D", {_this call FUNC(onDraw3d);}]; From 2f67935c911e62b8f08297165854b1fceb3b3165 Mon Sep 17 00:00:00 2001 From: Josuan Albin Date: Mon, 18 May 2015 17:12:22 +0200 Subject: [PATCH 033/140] mk6mortar and missing entries - mk6 mortar doc added - apl doc added - classnames fixed (forgot an entry) --- documentation/feature/apl.md | 18 ++------- documentation/feature/mk6mortar.md | 50 ++++++++++++++++++------ documentation/missionmaker/classnames.md | 4 ++ 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/documentation/feature/apl.md b/documentation/feature/apl.md index c0705a2abe..e30de7613e 100644 --- a/documentation/feature/apl.md +++ b/documentation/feature/apl.md @@ -1,25 +1,15 @@ --- layout: wiki title: APL -description: +description: assets under APL license group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. -### Sub-feature 2 -Short description of sub-feature 2. +This folder regroup all assets released under the APL license. - -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies +## 2. Dependencies `ace_main` diff --git a/documentation/feature/mk6mortar.md b/documentation/feature/mk6mortar.md index 1693a9e23d..8995b8a761 100644 --- a/documentation/feature/mk6mortar.md +++ b/documentation/feature/mk6mortar.md @@ -1,26 +1,54 @@ --- layout: wiki title: Mk6 Mortar -description: +description: Improve the existing mk6 mortar. group: feature parent: wiki --- -## Overview +## 1. Overview -### Sub-feature 1 -Short description of sub-feature 1. +### 1.1 mk6 mortar overhaul -### Sub-feature 2 -Short description of sub-feature 2. +ACE3 adds wind deflection for shells as well as a rangetable to accurately take out your target without the artillery computer. +## 2. Usage -## Usage +### 2.1 Switching charge +- Press F (fire mode switch) to switch between charges -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. +### 2.2 Working with the rangetable +- To open the table: + - Self interact ctrl + left windows (by default). + - Select `equipment`. + - Select `Open 82mm Rangetable`. +- Using the table: + - Get the distance and elevation difference between you and the target for this you can use map tools. For this example we'll say we're 2 000m away and 50m below (we're at 20m they are at 70m, 70-20=50). + - Select the charge you want to use (0 = close / 1 = medium / 2 = far). For this case we're using charge 2. + - Check the range column on the table, we're at 2 000 then look at the corresponding entry in the column on the right (ELEV = elevation) For this example it's 1339. + - After that's done move by one column on the right that's the elevation for 100m heigh so in our case we're subtracting 2 (4:2 = 2) if our target was 300m above us we would have to subtract 12 from our elevation (3x4 = 12). + - After you finished your maths, it's time to aim, get the cross of the mortar on target, if you don't see it use a waypoint if possible. In our case ELEV is 1339-2 = 1337. + - On the right side of the screen, while looking through the mk6 scope you should see ELV, we need to match this number with the one we found. + - To adjust the ELV use pageUp and pageDown . + - Once the number you found and ELV are the same FIRE ! + - On top of that you can calculate the time the shell will take to land by using the third row from the left, in our case the shell need to travel 2000m that's 20xthe number indicated. so 20x0,5 = 10s. +### 2.3 Working with the rangetable (Crosswinds enabled) +- Same as above there's just an extra step, I'll provide an other example in case you forgot. + - Get the distance and elevation difference between you and the target for this you can use map tools. For this example we'll say we're 2 400m away and 223m below (we're at 2m they are at 225, 225-2=223) + - Select the charge you want to use (0 = close / 1 = medium / 2 = far). For this case we're using charge 2. + - Check the range column on the table, we're 2 400m a then look at the corresponding entry in the column on the right (ELEV = elevation) For this example it's 1145. + - After that's done move by one column on the right that's the elevation for 100m heigh so in our case we're subtracting 22 (2,2 x 10 (2,2 because we're around 220m below)). + - Extra step needed here, a kestrel 4500 IS NEEDED. + - Pick the crosswind on your kestrel (for this refer to the kestrel documentation). + - For this example the crosswind is of 2 MPS on my table I can see under Azimuth correction that for each 1MPS I need to correct by 2.5 mill. + - So in this case i'm subtracting 5 mill from the ELV. + - It's MATH TIME the ELV given by the table is 1 145, we subtract 22 because of the heigh, we also subtract 5 for the crosswind ( 1 145-22-5 = 1 118 ). + - After you finished your maths, it's time to aim, get the cross of the mortar on target, if you don't see it use a waypoint if possible. In our case ELEV is 1 118. + - On the right side of the screen, while looking through the mk6 scope you should see ELV, we need to match this number with the one we found. + - FIREEEE !!!! + - Little advantage of having crosswind enabled is that you don't have to calculate the flight time, it's marked on the table in this case it's 33,8s. -## Dependencies +## 3. Dependencies -`ace_interaction` +`ace_interaction` \ No newline at end of file diff --git a/documentation/missionmaker/classnames.md b/documentation/missionmaker/classnames.md index 62d80afe98..c6476c075d 100644 --- a/documentation/missionmaker/classnames.md +++ b/documentation/missionmaker/classnames.md @@ -1,6 +1,7 @@ --- layout: wiki title: Classnames +description: A list of all the classnames in ACE3, your wet dream came true. group: missionmaker order: 11 parent: wiki @@ -174,6 +175,9 @@ classname | in game name | type | --------- | --------- | --------- ACE_microDAGR | MicroDAGR GPS | ACE_ItemCore | +### mk6 mortar +`added in 3.0.0.3` + classname | in game name | type | --------- | --------- | --------- ACE_RangeTable_82mm | 82mm Rangetable | ACE_ItemCore | From 5c7e59fd29dd4aae04d6473775ef39f952058ada Mon Sep 17 00:00:00 2001 From: VKing Date: Mon, 11 May 2015 23:17:17 +0200 Subject: [PATCH 034/140] Hacked order to fix order of comanche zoom levels --- addons/aircraft/Heli_Attack_01_base_F.hpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/addons/aircraft/Heli_Attack_01_base_F.hpp b/addons/aircraft/Heli_Attack_01_base_F.hpp index 14ca7ef7cd..3566336353 100644 --- a/addons/aircraft/Heli_Attack_01_base_F.hpp +++ b/addons/aircraft/Heli_Attack_01_base_F.hpp @@ -891,8 +891,7 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { class OpticsIn { - class WideUnstabalized - { + class Wide { // Wide Unstabilized opticsDisplayName = "WU"; initAngleX = 0; minAngleX = -35; @@ -910,8 +909,7 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { horizontallyStabilized = 1; gunnerOpticsModel = "\A3\Weapons_F_Beta\Reticle\Heli_Attack_01_Optics_Gunner_wide_F"; }; - class Wide - { + class Medium: Wide { // Wide Stabilized opticsDisplayName = "W"; initAngleX = 0; minAngleX = -35; @@ -929,8 +927,7 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { horizontallyStabilized = 1; gunnerOpticsModel = "\A3\Weapons_F_Beta\Reticle\Heli_Attack_01_Optics_Gunner_wide_F"; }; - class Medium: Wide - { + class Narrow: Wide { // Medium Stabilized opticsDisplayName = "M"; initFov = 0.093; minFov = 0.093; @@ -940,8 +937,7 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { horizontallyStabilized = 1; gunnerOpticsModel = "\A3\Weapons_F_Beta\Reticle\Heli_Attack_01_Optics_Gunner_medium_F"; }; - class Narrow: Wide - { + class Narrower: Wide { // Narrow Stabilized opticsDisplayName = "N"; initFov = 0.029; minFov = 0.029; @@ -952,8 +948,7 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { gunnerOpticsModel = "\A3\Weapons_F_Beta\Reticle\Heli_Attack_01_Optics_Gunner_narrow_F"; }; - class Narrower: Wide - { + class Narrowest: Wide { // Narrower Stabilized opticsDisplayName = "Z"; initFov = 0.01; minFov = 0.01; From 1cab51156a9d18d6af39c719c9246d7b30b0230f Mon Sep 17 00:00:00 2001 From: VKing Date: Tue, 12 May 2015 15:53:49 +0200 Subject: [PATCH 035/140] Made better with Pabstology (tm) --- addons/aircraft/Heli_Attack_01_base_F.hpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/addons/aircraft/Heli_Attack_01_base_F.hpp b/addons/aircraft/Heli_Attack_01_base_F.hpp index 3566336353..26a4605910 100644 --- a/addons/aircraft/Heli_Attack_01_base_F.hpp +++ b/addons/aircraft/Heli_Attack_01_base_F.hpp @@ -891,8 +891,12 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { class OpticsIn { - class Wide { // Wide Unstabilized - opticsDisplayName = "WU"; + delete Narrow; + delete Medium; + delete Wide; + + class ACE_WideUnstabilized { + opticsDisplayName = "W NS"; initAngleX = 0; minAngleX = -35; maxAngleX = 10; @@ -909,7 +913,7 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { horizontallyStabilized = 1; gunnerOpticsModel = "\A3\Weapons_F_Beta\Reticle\Heli_Attack_01_Optics_Gunner_wide_F"; }; - class Medium: Wide { // Wide Stabilized + class ACE_Wide: ACE_WideUnstabilized { opticsDisplayName = "W"; initAngleX = 0; minAngleX = -35; @@ -927,7 +931,7 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { horizontallyStabilized = 1; gunnerOpticsModel = "\A3\Weapons_F_Beta\Reticle\Heli_Attack_01_Optics_Gunner_wide_F"; }; - class Narrow: Wide { // Medium Stabilized + class ACE_Medium: ACE_Wide { opticsDisplayName = "M"; initFov = 0.093; minFov = 0.093; @@ -937,7 +941,7 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { horizontallyStabilized = 1; gunnerOpticsModel = "\A3\Weapons_F_Beta\Reticle\Heli_Attack_01_Optics_Gunner_medium_F"; }; - class Narrower: Wide { // Narrow Stabilized + class ACE_Narrow: ACE_Wide { opticsDisplayName = "N"; initFov = 0.029; minFov = 0.029; @@ -948,7 +952,7 @@ class Heli_Attack_01_base_F: Helicopter_Base_F { gunnerOpticsModel = "\A3\Weapons_F_Beta\Reticle\Heli_Attack_01_Optics_Gunner_narrow_F"; }; - class Narrowest: Wide { // Narrower Stabilized + class ACE_Narrower: ACE_Wide { opticsDisplayName = "Z"; initFov = 0.01; minFov = 0.01; From e4fb652dd21619fa4d9d4873830662cc105decb1 Mon Sep 17 00:00:00 2001 From: jaynus Date: Wed, 13 May 2015 08:34:14 -0700 Subject: [PATCH 036/140] initial pick from vehicledamage for new extension build process. --- extensions/CMakeLists.txt | 84 +- .../AdvancedBallistics.cpp | 34 +- extensions/advanced_ballistics/CMakeLists.txt | 7 +- extensions/break_line/CMakeLists.txt | 7 +- extensions/break_line/ace_break_line.cpp | 4 +- extensions/clipboard/ace_clipboard.cpp | 17 +- extensions/cmake/FindDirectX.cmake | 215 + extensions/common/CMakeLists.txt | 18 + extensions/common/arguments.hpp | 90 + extensions/common/directx/d3d_display.cpp | 439 ++ extensions/common/directx/d3d_display.hpp | 130 + extensions/common/dispatch.hpp | 153 + extensions/common/easyloggingc++.hpp | 6718 +++++++++++++++++ extensions/common/glm/CMakeLists.txt | 43 + extensions/common/glm/common.hpp | 35 + extensions/common/glm/detail/_features.hpp | 428 ++ extensions/common/glm/detail/_fixes.hpp | 59 + extensions/common/glm/detail/_noise.hpp | 136 + extensions/common/glm/detail/_swizzle.hpp | 833 ++ .../common/glm/detail/_swizzle_func.hpp | 725 ++ extensions/common/glm/detail/_vectorize.hpp | 160 + extensions/common/glm/detail/dummy.cpp | 232 + extensions/common/glm/detail/func_common.hpp | 456 ++ extensions/common/glm/detail/func_common.inl | 758 ++ .../common/glm/detail/func_exponential.hpp | 132 + .../common/glm/detail/func_exponential.inl | 161 + .../common/glm/detail/func_geometric.hpp | 142 + .../common/glm/detail/func_geometric.inl | 201 + extensions/common/glm/detail/func_integer.hpp | 232 + extensions/common/glm/detail/func_integer.inl | 393 + extensions/common/glm/detail/func_matrix.hpp | 178 + extensions/common/glm/detail/func_matrix.inl | 310 + extensions/common/glm/detail/func_noise.hpp | 93 + extensions/common/glm/detail/func_noise.inl | 388 + extensions/common/glm/detail/func_packing.hpp | 197 + extensions/common/glm/detail/func_packing.inl | 119 + .../common/glm/detail/func_trigonometric.hpp | 205 + .../common/glm/detail/func_trigonometric.inl | 224 + .../glm/detail/func_vector_relational.hpp | 140 + .../glm/detail/func_vector_relational.inl | 131 + extensions/common/glm/detail/glm.cpp | 286 + .../common/glm/detail/intrinsic_common.hpp | 87 + .../common/glm/detail/intrinsic_common.inl | 313 + .../glm/detail/intrinsic_exponential.hpp | 77 + .../glm/detail/intrinsic_exponential.inl | 27 + .../common/glm/detail/intrinsic_geometric.hpp | 74 + .../common/glm/detail/intrinsic_geometric.inl | 147 + .../common/glm/detail/intrinsic_integer.hpp | 48 + .../common/glm/detail/intrinsic_integer.inl | 139 + .../common/glm/detail/intrinsic_matrix.hpp | 67 + .../common/glm/detail/intrinsic_matrix.inl | 1070 +++ .../glm/detail/intrinsic_trigonometric.hpp | 46 + .../glm/detail/intrinsic_trigonometric.inl | 27 + .../detail/intrinsic_vector_relational.hpp | 46 + .../detail/intrinsic_vector_relational.inl | 366 + extensions/common/glm/detail/precision.hpp | 44 + extensions/common/glm/detail/setup.hpp | 962 +++ extensions/common/glm/detail/type_float.hpp | 96 + extensions/common/glm/detail/type_gentype.hpp | 224 + extensions/common/glm/detail/type_gentype.inl | 370 + extensions/common/glm/detail/type_half.hpp | 48 + extensions/common/glm/detail/type_half.inl | 277 + extensions/common/glm/detail/type_int.hpp | 326 + extensions/common/glm/detail/type_mat.hpp | 793 ++ extensions/common/glm/detail/type_mat.inl | 32 + extensions/common/glm/detail/type_mat2x2.hpp | 223 + extensions/common/glm/detail/type_mat2x2.inl | 548 ++ extensions/common/glm/detail/type_mat2x3.hpp | 201 + extensions/common/glm/detail/type_mat2x3.inl | 506 ++ extensions/common/glm/detail/type_mat2x4.hpp | 202 + extensions/common/glm/detail/type_mat2x4.inl | 515 ++ extensions/common/glm/detail/type_mat3x2.hpp | 207 + extensions/common/glm/detail/type_mat3x2.inl | 540 ++ extensions/common/glm/detail/type_mat3x3.hpp | 230 + extensions/common/glm/detail/type_mat3x3.inl | 631 ++ extensions/common/glm/detail/type_mat3x4.hpp | 206 + extensions/common/glm/detail/type_mat3x4.inl | 579 ++ extensions/common/glm/detail/type_mat4x2.hpp | 212 + extensions/common/glm/detail/type_mat4x2.inl | 587 ++ extensions/common/glm/detail/type_mat4x3.hpp | 211 + extensions/common/glm/detail/type_mat4x3.inl | 631 ++ extensions/common/glm/detail/type_mat4x4.hpp | 235 + extensions/common/glm/detail/type_mat4x4.inl | 790 ++ extensions/common/glm/detail/type_vec.hpp | 518 ++ extensions/common/glm/detail/type_vec.inl | 31 + extensions/common/glm/detail/type_vec1.hpp | 322 + extensions/common/glm/detail/type_vec1.inl | 616 ++ extensions/common/glm/detail/type_vec2.hpp | 403 + extensions/common/glm/detail/type_vec2.inl | 909 +++ extensions/common/glm/detail/type_vec3.hpp | 425 ++ extensions/common/glm/detail/type_vec3.inl | 1042 +++ extensions/common/glm/detail/type_vec4.hpp | 531 ++ extensions/common/glm/detail/type_vec4.inl | 1124 +++ .../common/glm/detail/type_vec4_avx.inl | 41 + .../common/glm/detail/type_vec4_avx2.inl | 41 + .../common/glm/detail/type_vec4_sse2.inl | 120 + extensions/common/glm/exponential.hpp | 35 + extensions/common/glm/ext.hpp | 143 + extensions/common/glm/fwd.hpp | 2601 +++++++ extensions/common/glm/geometric.hpp | 35 + extensions/common/glm/glm.hpp | 117 + extensions/common/glm/gtc/bitfield.hpp | 236 + extensions/common/glm/gtc/bitfield.inl | 542 ++ extensions/common/glm/gtc/constants.hpp | 205 + extensions/common/glm/gtc/constants.inl | 210 + extensions/common/glm/gtc/epsilon.hpp | 102 + extensions/common/glm/gtc/epsilon.inl | 154 + extensions/common/glm/gtc/integer.hpp | 105 + extensions/common/glm/gtc/integer.inl | 74 + extensions/common/glm/gtc/matrix_access.hpp | 88 + extensions/common/glm/gtc/matrix_access.inl | 92 + extensions/common/glm/gtc/matrix_integer.hpp | 515 ++ extensions/common/glm/gtc/matrix_inverse.hpp | 78 + extensions/common/glm/gtc/matrix_inverse.inl | 148 + .../common/glm/gtc/matrix_transform.hpp | 304 + .../common/glm/gtc/matrix_transform.inl | 413 + extensions/common/glm/gtc/noise.hpp | 89 + extensions/common/glm/gtc/noise.inl | 837 ++ extensions/common/glm/gtc/packing.hpp | 478 ++ extensions/common/glm/gtc/packing.inl | 490 ++ extensions/common/glm/gtc/quaternion.hpp | 377 + extensions/common/glm/gtc/quaternion.inl | 784 ++ extensions/common/glm/gtc/random.hpp | 120 + extensions/common/glm/gtc/random.inl | 379 + extensions/common/glm/gtc/reciprocal.hpp | 134 + extensions/common/glm/gtc/reciprocal.inl | 221 + extensions/common/glm/gtc/round.hpp | 203 + extensions/common/glm/gtc/round.inl | 378 + extensions/common/glm/gtc/type_precision.hpp | 890 +++ extensions/common/glm/gtc/type_precision.inl | 36 + extensions/common/glm/gtc/type_ptr.hpp | 178 + extensions/common/glm/gtc/type_ptr.inl | 479 ++ extensions/common/glm/gtc/ulp.hpp | 92 + extensions/common/glm/gtc/ulp.inl | 350 + extensions/common/glm/gtc/vec1.hpp | 193 + extensions/common/glm/gtc/vec1.inl | 31 + .../common/glm/gtx/associated_min_max.hpp | 231 + .../common/glm/gtx/associated_min_max.inl | 384 + extensions/common/glm/gtx/bit.hpp | 120 + extensions/common/glm/gtx/bit.inl | 107 + extensions/common/glm/gtx/closest_point.hpp | 74 + extensions/common/glm/gtx/closest_point.inl | 75 + extensions/common/glm/gtx/color_space.hpp | 97 + extensions/common/glm/gtx/color_space.inl | 172 + .../common/glm/gtx/color_space_YCoCg.hpp | 85 + .../common/glm/gtx/color_space_YCoCg.inl | 87 + extensions/common/glm/gtx/common.hpp | 74 + extensions/common/glm/gtx/common.inl | 102 + extensions/common/glm/gtx/compatibility.hpp | 158 + extensions/common/glm/gtx/compatibility.inl | 83 + extensions/common/glm/gtx/component_wise.hpp | 84 + extensions/common/glm/gtx/component_wise.inl | 70 + extensions/common/glm/gtx/dual_quaternion.hpp | 321 + extensions/common/glm/gtx/dual_quaternion.inl | 400 + extensions/common/glm/gtx/euler_angles.hpp | 156 + extensions/common/glm/gtx/euler_angles.inl | 287 + extensions/common/glm/gtx/extend.hpp | 67 + extensions/common/glm/gtx/extend.inl | 78 + .../common/glm/gtx/extented_min_max.hpp | 162 + .../common/glm/gtx/extented_min_max.inl | 169 + .../common/glm/gtx/fast_exponential.hpp | 120 + .../common/glm/gtx/fast_exponential.inl | 166 + .../common/glm/gtx/fast_square_root.hpp | 117 + .../common/glm/gtx/fast_square_root.inl | 110 + .../common/glm/gtx/fast_trigonometry.hpp | 104 + .../common/glm/gtx/fast_trigonometry.inl | 162 + extensions/common/glm/gtx/gradient_paint.hpp | 77 + extensions/common/glm/gtx/gradient_paint.inl | 66 + .../glm/gtx/handed_coordinate_space.hpp | 75 + .../glm/gtx/handed_coordinate_space.inl | 56 + extensions/common/glm/gtx/integer.hpp | 101 + extensions/common/glm/gtx/integer.inl | 211 + extensions/common/glm/gtx/intersect.hpp | 112 + extensions/common/glm/gtx/intersect.inl | 217 + extensions/common/glm/gtx/io.hpp | 224 + extensions/common/glm/gtx/io.inl | 618 ++ extensions/common/glm/gtx/log_base.hpp | 73 + extensions/common/glm/gtx/log_base.inl | 47 + .../common/glm/gtx/matrix_cross_product.hpp | 72 + .../common/glm/gtx/matrix_cross_product.inl | 67 + .../common/glm/gtx/matrix_decompose.hpp | 70 + .../common/glm/gtx/matrix_decompose.inl | 231 + .../common/glm/gtx/matrix_interpolation.hpp | 89 + .../common/glm/gtx/matrix_interpolation.inl | 163 + .../common/glm/gtx/matrix_major_storage.hpp | 144 + .../common/glm/gtx/matrix_major_storage.inl | 196 + .../common/glm/gtx/matrix_operation.hpp | 113 + .../common/glm/gtx/matrix_operation.inl | 147 + extensions/common/glm/gtx/matrix_query.hpp | 102 + extensions/common/glm/gtx/matrix_query.inl | 143 + .../common/glm/gtx/matrix_transform_2d.hpp | 106 + .../common/glm/gtx/matrix_transform_2d.inl | 97 + extensions/common/glm/gtx/mixed_product.hpp | 66 + extensions/common/glm/gtx/mixed_product.inl | 45 + extensions/common/glm/gtx/multiple.hpp | 106 + extensions/common/glm/gtx/multiple.inl | 64 + extensions/common/glm/gtx/norm.hpp | 128 + extensions/common/glm/gtx/norm.inl | 170 + extensions/common/glm/gtx/normal.hpp | 68 + extensions/common/glm/gtx/normal.inl | 45 + extensions/common/glm/gtx/normalize_dot.hpp | 74 + extensions/common/glm/gtx/normalize_dot.inl | 46 + .../common/glm/gtx/number_precision.hpp | 86 + .../common/glm/gtx/number_precision.inl | 36 + extensions/common/glm/gtx/optimum_pow.hpp | 79 + extensions/common/glm/gtx/optimum_pow.inl | 52 + extensions/common/glm/gtx/orthonormalize.hpp | 74 + extensions/common/glm/gtx/orthonormalize.inl | 59 + extensions/common/glm/gtx/perpendicular.hpp | 68 + extensions/common/glm/gtx/perpendicular.inl | 44 + .../common/glm/gtx/polar_coordinates.hpp | 73 + .../common/glm/gtx/polar_coordinates.inl | 66 + extensions/common/glm/gtx/projection.hpp | 65 + extensions/common/glm/gtx/projection.inl | 40 + extensions/common/glm/gtx/quaternion.hpp | 214 + extensions/common/glm/gtx/quaternion.inl | 285 + extensions/common/glm/gtx/range.hpp | 102 + extensions/common/glm/gtx/raw_data.hpp | 76 + extensions/common/glm/gtx/raw_data.inl | 31 + .../common/glm/gtx/rotate_normalized_axis.hpp | 93 + .../common/glm/gtx/rotate_normalized_axis.inl | 88 + extensions/common/glm/gtx/rotate_vector.hpp | 146 + extensions/common/glm/gtx/rotate_vector.inl | 217 + .../common/glm/gtx/scalar_multiplication.hpp | 98 + .../common/glm/gtx/scalar_relational.hpp | 61 + .../common/glm/gtx/scalar_relational.inl | 118 + extensions/common/glm/gtx/simd_mat4.hpp | 205 + extensions/common/glm/gtx/simd_mat4.inl | 602 ++ extensions/common/glm/gtx/simd_quat.hpp | 335 + extensions/common/glm/gtx/simd_quat.inl | 645 ++ extensions/common/glm/gtx/simd_vec4.hpp | 574 ++ extensions/common/glm/gtx/simd_vec4.inl | 727 ++ extensions/common/glm/gtx/spline.hpp | 90 + extensions/common/glm/gtx/spline.inl | 92 + extensions/common/glm/gtx/std_based_type.hpp | 92 + extensions/common/glm/gtx/std_based_type.inl | 36 + extensions/common/glm/gtx/string_cast.hpp | 74 + extensions/common/glm/gtx/string_cast.inl | 455 ++ extensions/common/glm/gtx/transform.hpp | 85 + extensions/common/glm/gtx/transform.inl | 60 + extensions/common/glm/gtx/transform2.hpp | 136 + extensions/common/glm/gtx/transform2.inl | 177 + extensions/common/glm/gtx/type_aligned.hpp | 995 +++ extensions/common/glm/gtx/type_aligned.inl | 36 + extensions/common/glm/gtx/vector_angle.hpp | 89 + extensions/common/glm/gtx/vector_angle.inl | 87 + extensions/common/glm/gtx/vector_query.hpp | 91 + extensions/common/glm/gtx/vector_query.inl | 222 + extensions/common/glm/gtx/wrap.hpp | 74 + extensions/common/glm/gtx/wrap.inl | 185 + extensions/common/glm/integer.hpp | 35 + extensions/common/glm/mat2x2.hpp | 81 + extensions/common/glm/mat2x3.hpp | 61 + extensions/common/glm/mat2x4.hpp | 60 + extensions/common/glm/mat3x2.hpp | 60 + extensions/common/glm/mat3x3.hpp | 81 + extensions/common/glm/mat3x4.hpp | 60 + extensions/common/glm/mat4x2.hpp | 60 + extensions/common/glm/mat4x3.hpp | 60 + extensions/common/glm/mat4x4.hpp | 81 + extensions/common/glm/matrix.hpp | 35 + extensions/common/glm/packing.hpp | 35 + extensions/common/glm/trigonometric.hpp | 35 + extensions/common/glm/vec2.hpp | 35 + extensions/common/glm/vec3.hpp | 35 + extensions/common/glm/vec4.hpp | 35 + extensions/common/glm/vector_relational.hpp | 35 + extensions/common/logging.hpp | 6 + extensions/common/lzoconf.h | 453 ++ extensions/common/lzodefs.h | 3134 ++++++++ extensions/common/membuf.hpp | 56 + extensions/common/minilzo.c | 6231 +++++++++++++++ extensions/common/minilzo.h | 106 + extensions/common/p3d/animation.cpp | 72 + extensions/common/p3d/animation.hpp | 69 + extensions/common/p3d/compressed.cpp | 237 + extensions/common/p3d/compressed.hpp | 166 + extensions/common/p3d/lod_info.cpp | 289 + extensions/common/p3d/lod_info.hpp | 237 + extensions/common/p3d/lod_types.hpp | 33 + extensions/common/p3d/model.cpp | 116 + extensions/common/p3d/model.hpp | 57 + extensions/common/p3d/model_info.cpp | 91 + extensions/common/p3d/model_info.hpp | 74 + extensions/common/p3d/parser.cpp | 26 + extensions/common/p3d/parser.hpp | 17 + extensions/common/p3d/parser_ref.txt | 269 + extensions/common/p3d/read_helpers.hpp | 11 + extensions/common/p3d/skeleton.cpp | 46 + extensions/common/p3d/skeleton.hpp | 36 + extensions/common/pbo/archive.cpp | 91 + extensions/common/pbo/archive.hpp | 61 + extensions/common/pbo/search.cpp | 301 + extensions/common/pbo/search.hpp | 27 + extensions/common/shared.cpp | 41 + extensions/common/shared.hpp | 77 + extensions/common/simplepipe_win32.cpp | 179 + extensions/common/simplepipe_win32.hpp | 57 + extensions/common/simulation/object.cpp | 464 ++ extensions/common/simulation/object.hpp | 221 + extensions/common/singleton.hpp | 31 + extensions/common/targetver.h | 2 +- extensions/common/transform_matrix.hpp | 34 + extensions/common/vector.cpp | 11 + extensions/common/vector.hpp | 161 + extensions/dynload/CMakeLists.txt | 14 + extensions/dynload/ace_dynload.cpp | 66 + extensions/dynload/ace_dynload_dllmain.cpp | 33 + extensions/dynload/dynloader.hpp | 168 + extensions/fcs/CMakeLists.txt | 7 +- extensions/fcs/ace_fcs.cpp | 5 +- extensions/lib/bullet3 | 1 + 312 files changed, 79346 insertions(+), 40 deletions(-) create mode 100644 extensions/cmake/FindDirectX.cmake create mode 100644 extensions/common/CMakeLists.txt create mode 100644 extensions/common/arguments.hpp create mode 100644 extensions/common/directx/d3d_display.cpp create mode 100644 extensions/common/directx/d3d_display.hpp create mode 100644 extensions/common/dispatch.hpp create mode 100644 extensions/common/easyloggingc++.hpp create mode 100644 extensions/common/glm/CMakeLists.txt create mode 100644 extensions/common/glm/common.hpp create mode 100644 extensions/common/glm/detail/_features.hpp create mode 100644 extensions/common/glm/detail/_fixes.hpp create mode 100644 extensions/common/glm/detail/_noise.hpp create mode 100644 extensions/common/glm/detail/_swizzle.hpp create mode 100644 extensions/common/glm/detail/_swizzle_func.hpp create mode 100644 extensions/common/glm/detail/_vectorize.hpp create mode 100644 extensions/common/glm/detail/dummy.cpp create mode 100644 extensions/common/glm/detail/func_common.hpp create mode 100644 extensions/common/glm/detail/func_common.inl create mode 100644 extensions/common/glm/detail/func_exponential.hpp create mode 100644 extensions/common/glm/detail/func_exponential.inl create mode 100644 extensions/common/glm/detail/func_geometric.hpp create mode 100644 extensions/common/glm/detail/func_geometric.inl create mode 100644 extensions/common/glm/detail/func_integer.hpp create mode 100644 extensions/common/glm/detail/func_integer.inl create mode 100644 extensions/common/glm/detail/func_matrix.hpp create mode 100644 extensions/common/glm/detail/func_matrix.inl create mode 100644 extensions/common/glm/detail/func_noise.hpp create mode 100644 extensions/common/glm/detail/func_noise.inl create mode 100644 extensions/common/glm/detail/func_packing.hpp create mode 100644 extensions/common/glm/detail/func_packing.inl create mode 100644 extensions/common/glm/detail/func_trigonometric.hpp create mode 100644 extensions/common/glm/detail/func_trigonometric.inl create mode 100644 extensions/common/glm/detail/func_vector_relational.hpp create mode 100644 extensions/common/glm/detail/func_vector_relational.inl create mode 100644 extensions/common/glm/detail/glm.cpp create mode 100644 extensions/common/glm/detail/intrinsic_common.hpp create mode 100644 extensions/common/glm/detail/intrinsic_common.inl create mode 100644 extensions/common/glm/detail/intrinsic_exponential.hpp create mode 100644 extensions/common/glm/detail/intrinsic_exponential.inl create mode 100644 extensions/common/glm/detail/intrinsic_geometric.hpp create mode 100644 extensions/common/glm/detail/intrinsic_geometric.inl create mode 100644 extensions/common/glm/detail/intrinsic_integer.hpp create mode 100644 extensions/common/glm/detail/intrinsic_integer.inl create mode 100644 extensions/common/glm/detail/intrinsic_matrix.hpp create mode 100644 extensions/common/glm/detail/intrinsic_matrix.inl create mode 100644 extensions/common/glm/detail/intrinsic_trigonometric.hpp create mode 100644 extensions/common/glm/detail/intrinsic_trigonometric.inl create mode 100644 extensions/common/glm/detail/intrinsic_vector_relational.hpp create mode 100644 extensions/common/glm/detail/intrinsic_vector_relational.inl create mode 100644 extensions/common/glm/detail/precision.hpp create mode 100644 extensions/common/glm/detail/setup.hpp create mode 100644 extensions/common/glm/detail/type_float.hpp create mode 100644 extensions/common/glm/detail/type_gentype.hpp create mode 100644 extensions/common/glm/detail/type_gentype.inl create mode 100644 extensions/common/glm/detail/type_half.hpp create mode 100644 extensions/common/glm/detail/type_half.inl create mode 100644 extensions/common/glm/detail/type_int.hpp create mode 100644 extensions/common/glm/detail/type_mat.hpp create mode 100644 extensions/common/glm/detail/type_mat.inl create mode 100644 extensions/common/glm/detail/type_mat2x2.hpp create mode 100644 extensions/common/glm/detail/type_mat2x2.inl create mode 100644 extensions/common/glm/detail/type_mat2x3.hpp create mode 100644 extensions/common/glm/detail/type_mat2x3.inl create mode 100644 extensions/common/glm/detail/type_mat2x4.hpp create mode 100644 extensions/common/glm/detail/type_mat2x4.inl create mode 100644 extensions/common/glm/detail/type_mat3x2.hpp create mode 100644 extensions/common/glm/detail/type_mat3x2.inl create mode 100644 extensions/common/glm/detail/type_mat3x3.hpp create mode 100644 extensions/common/glm/detail/type_mat3x3.inl create mode 100644 extensions/common/glm/detail/type_mat3x4.hpp create mode 100644 extensions/common/glm/detail/type_mat3x4.inl create mode 100644 extensions/common/glm/detail/type_mat4x2.hpp create mode 100644 extensions/common/glm/detail/type_mat4x2.inl create mode 100644 extensions/common/glm/detail/type_mat4x3.hpp create mode 100644 extensions/common/glm/detail/type_mat4x3.inl create mode 100644 extensions/common/glm/detail/type_mat4x4.hpp create mode 100644 extensions/common/glm/detail/type_mat4x4.inl create mode 100644 extensions/common/glm/detail/type_vec.hpp create mode 100644 extensions/common/glm/detail/type_vec.inl create mode 100644 extensions/common/glm/detail/type_vec1.hpp create mode 100644 extensions/common/glm/detail/type_vec1.inl create mode 100644 extensions/common/glm/detail/type_vec2.hpp create mode 100644 extensions/common/glm/detail/type_vec2.inl create mode 100644 extensions/common/glm/detail/type_vec3.hpp create mode 100644 extensions/common/glm/detail/type_vec3.inl create mode 100644 extensions/common/glm/detail/type_vec4.hpp create mode 100644 extensions/common/glm/detail/type_vec4.inl create mode 100644 extensions/common/glm/detail/type_vec4_avx.inl create mode 100644 extensions/common/glm/detail/type_vec4_avx2.inl create mode 100644 extensions/common/glm/detail/type_vec4_sse2.inl create mode 100644 extensions/common/glm/exponential.hpp create mode 100644 extensions/common/glm/ext.hpp create mode 100644 extensions/common/glm/fwd.hpp create mode 100644 extensions/common/glm/geometric.hpp create mode 100644 extensions/common/glm/glm.hpp create mode 100644 extensions/common/glm/gtc/bitfield.hpp create mode 100644 extensions/common/glm/gtc/bitfield.inl create mode 100644 extensions/common/glm/gtc/constants.hpp create mode 100644 extensions/common/glm/gtc/constants.inl create mode 100644 extensions/common/glm/gtc/epsilon.hpp create mode 100644 extensions/common/glm/gtc/epsilon.inl create mode 100644 extensions/common/glm/gtc/integer.hpp create mode 100644 extensions/common/glm/gtc/integer.inl create mode 100644 extensions/common/glm/gtc/matrix_access.hpp create mode 100644 extensions/common/glm/gtc/matrix_access.inl create mode 100644 extensions/common/glm/gtc/matrix_integer.hpp create mode 100644 extensions/common/glm/gtc/matrix_inverse.hpp create mode 100644 extensions/common/glm/gtc/matrix_inverse.inl create mode 100644 extensions/common/glm/gtc/matrix_transform.hpp create mode 100644 extensions/common/glm/gtc/matrix_transform.inl create mode 100644 extensions/common/glm/gtc/noise.hpp create mode 100644 extensions/common/glm/gtc/noise.inl create mode 100644 extensions/common/glm/gtc/packing.hpp create mode 100644 extensions/common/glm/gtc/packing.inl create mode 100644 extensions/common/glm/gtc/quaternion.hpp create mode 100644 extensions/common/glm/gtc/quaternion.inl create mode 100644 extensions/common/glm/gtc/random.hpp create mode 100644 extensions/common/glm/gtc/random.inl create mode 100644 extensions/common/glm/gtc/reciprocal.hpp create mode 100644 extensions/common/glm/gtc/reciprocal.inl create mode 100644 extensions/common/glm/gtc/round.hpp create mode 100644 extensions/common/glm/gtc/round.inl create mode 100644 extensions/common/glm/gtc/type_precision.hpp create mode 100644 extensions/common/glm/gtc/type_precision.inl create mode 100644 extensions/common/glm/gtc/type_ptr.hpp create mode 100644 extensions/common/glm/gtc/type_ptr.inl create mode 100644 extensions/common/glm/gtc/ulp.hpp create mode 100644 extensions/common/glm/gtc/ulp.inl create mode 100644 extensions/common/glm/gtc/vec1.hpp create mode 100644 extensions/common/glm/gtc/vec1.inl create mode 100644 extensions/common/glm/gtx/associated_min_max.hpp create mode 100644 extensions/common/glm/gtx/associated_min_max.inl create mode 100644 extensions/common/glm/gtx/bit.hpp create mode 100644 extensions/common/glm/gtx/bit.inl create mode 100644 extensions/common/glm/gtx/closest_point.hpp create mode 100644 extensions/common/glm/gtx/closest_point.inl create mode 100644 extensions/common/glm/gtx/color_space.hpp create mode 100644 extensions/common/glm/gtx/color_space.inl create mode 100644 extensions/common/glm/gtx/color_space_YCoCg.hpp create mode 100644 extensions/common/glm/gtx/color_space_YCoCg.inl create mode 100644 extensions/common/glm/gtx/common.hpp create mode 100644 extensions/common/glm/gtx/common.inl create mode 100644 extensions/common/glm/gtx/compatibility.hpp create mode 100644 extensions/common/glm/gtx/compatibility.inl create mode 100644 extensions/common/glm/gtx/component_wise.hpp create mode 100644 extensions/common/glm/gtx/component_wise.inl create mode 100644 extensions/common/glm/gtx/dual_quaternion.hpp create mode 100644 extensions/common/glm/gtx/dual_quaternion.inl create mode 100644 extensions/common/glm/gtx/euler_angles.hpp create mode 100644 extensions/common/glm/gtx/euler_angles.inl create mode 100644 extensions/common/glm/gtx/extend.hpp create mode 100644 extensions/common/glm/gtx/extend.inl create mode 100644 extensions/common/glm/gtx/extented_min_max.hpp create mode 100644 extensions/common/glm/gtx/extented_min_max.inl create mode 100644 extensions/common/glm/gtx/fast_exponential.hpp create mode 100644 extensions/common/glm/gtx/fast_exponential.inl create mode 100644 extensions/common/glm/gtx/fast_square_root.hpp create mode 100644 extensions/common/glm/gtx/fast_square_root.inl create mode 100644 extensions/common/glm/gtx/fast_trigonometry.hpp create mode 100644 extensions/common/glm/gtx/fast_trigonometry.inl create mode 100644 extensions/common/glm/gtx/gradient_paint.hpp create mode 100644 extensions/common/glm/gtx/gradient_paint.inl create mode 100644 extensions/common/glm/gtx/handed_coordinate_space.hpp create mode 100644 extensions/common/glm/gtx/handed_coordinate_space.inl create mode 100644 extensions/common/glm/gtx/integer.hpp create mode 100644 extensions/common/glm/gtx/integer.inl create mode 100644 extensions/common/glm/gtx/intersect.hpp create mode 100644 extensions/common/glm/gtx/intersect.inl create mode 100644 extensions/common/glm/gtx/io.hpp create mode 100644 extensions/common/glm/gtx/io.inl create mode 100644 extensions/common/glm/gtx/log_base.hpp create mode 100644 extensions/common/glm/gtx/log_base.inl create mode 100644 extensions/common/glm/gtx/matrix_cross_product.hpp create mode 100644 extensions/common/glm/gtx/matrix_cross_product.inl create mode 100644 extensions/common/glm/gtx/matrix_decompose.hpp create mode 100644 extensions/common/glm/gtx/matrix_decompose.inl create mode 100644 extensions/common/glm/gtx/matrix_interpolation.hpp create mode 100644 extensions/common/glm/gtx/matrix_interpolation.inl create mode 100644 extensions/common/glm/gtx/matrix_major_storage.hpp create mode 100644 extensions/common/glm/gtx/matrix_major_storage.inl create mode 100644 extensions/common/glm/gtx/matrix_operation.hpp create mode 100644 extensions/common/glm/gtx/matrix_operation.inl create mode 100644 extensions/common/glm/gtx/matrix_query.hpp create mode 100644 extensions/common/glm/gtx/matrix_query.inl create mode 100644 extensions/common/glm/gtx/matrix_transform_2d.hpp create mode 100644 extensions/common/glm/gtx/matrix_transform_2d.inl create mode 100644 extensions/common/glm/gtx/mixed_product.hpp create mode 100644 extensions/common/glm/gtx/mixed_product.inl create mode 100644 extensions/common/glm/gtx/multiple.hpp create mode 100644 extensions/common/glm/gtx/multiple.inl create mode 100644 extensions/common/glm/gtx/norm.hpp create mode 100644 extensions/common/glm/gtx/norm.inl create mode 100644 extensions/common/glm/gtx/normal.hpp create mode 100644 extensions/common/glm/gtx/normal.inl create mode 100644 extensions/common/glm/gtx/normalize_dot.hpp create mode 100644 extensions/common/glm/gtx/normalize_dot.inl create mode 100644 extensions/common/glm/gtx/number_precision.hpp create mode 100644 extensions/common/glm/gtx/number_precision.inl create mode 100644 extensions/common/glm/gtx/optimum_pow.hpp create mode 100644 extensions/common/glm/gtx/optimum_pow.inl create mode 100644 extensions/common/glm/gtx/orthonormalize.hpp create mode 100644 extensions/common/glm/gtx/orthonormalize.inl create mode 100644 extensions/common/glm/gtx/perpendicular.hpp create mode 100644 extensions/common/glm/gtx/perpendicular.inl create mode 100644 extensions/common/glm/gtx/polar_coordinates.hpp create mode 100644 extensions/common/glm/gtx/polar_coordinates.inl create mode 100644 extensions/common/glm/gtx/projection.hpp create mode 100644 extensions/common/glm/gtx/projection.inl create mode 100644 extensions/common/glm/gtx/quaternion.hpp create mode 100644 extensions/common/glm/gtx/quaternion.inl create mode 100644 extensions/common/glm/gtx/range.hpp create mode 100644 extensions/common/glm/gtx/raw_data.hpp create mode 100644 extensions/common/glm/gtx/raw_data.inl create mode 100644 extensions/common/glm/gtx/rotate_normalized_axis.hpp create mode 100644 extensions/common/glm/gtx/rotate_normalized_axis.inl create mode 100644 extensions/common/glm/gtx/rotate_vector.hpp create mode 100644 extensions/common/glm/gtx/rotate_vector.inl create mode 100644 extensions/common/glm/gtx/scalar_multiplication.hpp create mode 100644 extensions/common/glm/gtx/scalar_relational.hpp create mode 100644 extensions/common/glm/gtx/scalar_relational.inl create mode 100644 extensions/common/glm/gtx/simd_mat4.hpp create mode 100644 extensions/common/glm/gtx/simd_mat4.inl create mode 100644 extensions/common/glm/gtx/simd_quat.hpp create mode 100644 extensions/common/glm/gtx/simd_quat.inl create mode 100644 extensions/common/glm/gtx/simd_vec4.hpp create mode 100644 extensions/common/glm/gtx/simd_vec4.inl create mode 100644 extensions/common/glm/gtx/spline.hpp create mode 100644 extensions/common/glm/gtx/spline.inl create mode 100644 extensions/common/glm/gtx/std_based_type.hpp create mode 100644 extensions/common/glm/gtx/std_based_type.inl create mode 100644 extensions/common/glm/gtx/string_cast.hpp create mode 100644 extensions/common/glm/gtx/string_cast.inl create mode 100644 extensions/common/glm/gtx/transform.hpp create mode 100644 extensions/common/glm/gtx/transform.inl create mode 100644 extensions/common/glm/gtx/transform2.hpp create mode 100644 extensions/common/glm/gtx/transform2.inl create mode 100644 extensions/common/glm/gtx/type_aligned.hpp create mode 100644 extensions/common/glm/gtx/type_aligned.inl create mode 100644 extensions/common/glm/gtx/vector_angle.hpp create mode 100644 extensions/common/glm/gtx/vector_angle.inl create mode 100644 extensions/common/glm/gtx/vector_query.hpp create mode 100644 extensions/common/glm/gtx/vector_query.inl create mode 100644 extensions/common/glm/gtx/wrap.hpp create mode 100644 extensions/common/glm/gtx/wrap.inl create mode 100644 extensions/common/glm/integer.hpp create mode 100644 extensions/common/glm/mat2x2.hpp create mode 100644 extensions/common/glm/mat2x3.hpp create mode 100644 extensions/common/glm/mat2x4.hpp create mode 100644 extensions/common/glm/mat3x2.hpp create mode 100644 extensions/common/glm/mat3x3.hpp create mode 100644 extensions/common/glm/mat3x4.hpp create mode 100644 extensions/common/glm/mat4x2.hpp create mode 100644 extensions/common/glm/mat4x3.hpp create mode 100644 extensions/common/glm/mat4x4.hpp create mode 100644 extensions/common/glm/matrix.hpp create mode 100644 extensions/common/glm/packing.hpp create mode 100644 extensions/common/glm/trigonometric.hpp create mode 100644 extensions/common/glm/vec2.hpp create mode 100644 extensions/common/glm/vec3.hpp create mode 100644 extensions/common/glm/vec4.hpp create mode 100644 extensions/common/glm/vector_relational.hpp create mode 100644 extensions/common/logging.hpp create mode 100644 extensions/common/lzoconf.h create mode 100644 extensions/common/lzodefs.h create mode 100644 extensions/common/membuf.hpp create mode 100644 extensions/common/minilzo.c create mode 100644 extensions/common/minilzo.h create mode 100644 extensions/common/p3d/animation.cpp create mode 100644 extensions/common/p3d/animation.hpp create mode 100644 extensions/common/p3d/compressed.cpp create mode 100644 extensions/common/p3d/compressed.hpp create mode 100644 extensions/common/p3d/lod_info.cpp create mode 100644 extensions/common/p3d/lod_info.hpp create mode 100644 extensions/common/p3d/lod_types.hpp create mode 100644 extensions/common/p3d/model.cpp create mode 100644 extensions/common/p3d/model.hpp create mode 100644 extensions/common/p3d/model_info.cpp create mode 100644 extensions/common/p3d/model_info.hpp create mode 100644 extensions/common/p3d/parser.cpp create mode 100644 extensions/common/p3d/parser.hpp create mode 100644 extensions/common/p3d/parser_ref.txt create mode 100644 extensions/common/p3d/read_helpers.hpp create mode 100644 extensions/common/p3d/skeleton.cpp create mode 100644 extensions/common/p3d/skeleton.hpp create mode 100644 extensions/common/pbo/archive.cpp create mode 100644 extensions/common/pbo/archive.hpp create mode 100644 extensions/common/pbo/search.cpp create mode 100644 extensions/common/pbo/search.hpp create mode 100644 extensions/common/shared.cpp create mode 100644 extensions/common/shared.hpp create mode 100644 extensions/common/simplepipe_win32.cpp create mode 100644 extensions/common/simplepipe_win32.hpp create mode 100644 extensions/common/simulation/object.cpp create mode 100644 extensions/common/simulation/object.hpp create mode 100644 extensions/common/singleton.hpp create mode 100644 extensions/common/transform_matrix.hpp create mode 100644 extensions/common/vector.cpp create mode 100644 extensions/common/vector.hpp create mode 100644 extensions/dynload/CMakeLists.txt create mode 100644 extensions/dynload/ace_dynload.cpp create mode 100644 extensions/dynload/ace_dynload_dllmain.cpp create mode 100644 extensions/dynload/dynloader.hpp create mode 160000 extensions/lib/bullet3 diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index 9f4a8a29fa..b1c1703f94 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -1,11 +1,20 @@ cmake_minimum_required (VERSION 3.0) project (ACE) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +if(WIN32) +add_definitions(/DWINVER=0x0600 /D_WIN32_WINNT=0x0600) +endif() + if (NOT CMAKE_BUILD_TYPE AND CMAKE_COMPILER_IS_GNUCXX) message(STATUS "No build type selected, default to Debug") set(CMAKE_BUILD_TYPE "Debug") endif() +option(DEVEL "DEVEL" OFF) +option(USE_BULLET "USE_BULLET" OFF) +option(USE_DIRECTX "USE_DIRECTX" OFF) option(USE_64BIT_BUILD "USE_64BIT_BUILD" OFF) option(USE_STATIC_LINKING "USE_STATIC_LINKING" ON) @@ -15,15 +24,66 @@ if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc -static-libstdc++") else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:x86") set(CMAKE_CXX_FLAGS_DEBUG "/D _DEBUG /MTd /Zi /Ob0 /Od /RTC1") set(CMAKE_CXX_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /D NDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG") endif() -file(GLOB ACE_COMMON_SOURCES common/*.h common/*.hpp common/*.c common/*.cpp) -add_library(ace_common STATIC ${ACE_COMMON_SOURCES}) -include_directories(AFTER "common") +include_directories("common") + +if(USE_BULLET) + # Dependencies + # + set(BACKUP_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) + set(BACKUP_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + set(BACKUP_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + + add_definitions(-DUSE_DIRECTX) + add_subdirectory(lib/bullet3) + + set_target_properties(App_BasicExample PROPERTIES FOLDER Bullet3) + set_target_properties(App_HelloWorld PROPERTIES FOLDER Bullet3) + set_target_properties(App_ExampleBrowser PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet2FileLoader PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3Collision PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3Dynamics PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3Geometry PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3Common PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3OpenCL_clew PROPERTIES FOLDER Bullet3) + set_target_properties(BulletCollision PROPERTIES FOLDER Bullet3) + set_target_properties(BulletDynamics PROPERTIES FOLDER Bullet3) + set_target_properties(BulletFileLoader PROPERTIES FOLDER Bullet3) + set_target_properties(BulletSoftBody PROPERTIES FOLDER Bullet3) + + set_target_properties(BulletWorldImporter PROPERTIES FOLDER Bullet3) + set_target_properties(BulletXmlWorldImporter PROPERTIES FOLDER Bullet3) + set_target_properties(ConvexDecomposition PROPERTIES FOLDER Bullet3) + set_target_properties(GIMPACTUtils PROPERTIES FOLDER Bullet3) + set_target_properties(gtest PROPERTIES FOLDER Bullet3) + set_target_properties(gwen PROPERTIES FOLDER Bullet3) + set_target_properties(HACD PROPERTIES FOLDER Bullet3) + set_target_properties(OpenGLWindow PROPERTIES FOLDER Bullet3) + set_target_properties(LinearMath PROPERTIES FOLDER Bullet3) + + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BACKUP_ARCHIVE_OUTPUT_DIRECTORY}) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BACKUP_LIBRARY_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BACKUP_RUNTIME_OUTPUT_DIRECTORY}) + + include_directories(BEFORE "lib/bullet3/src") +endif() +if(USE_DIRECTX) + add_definitions(-DUSE_DIRECTX) + set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) + find_package (DirectX) + link_directories (BEFORE ${DirectX_D3DX11_LIBRARY}) + include_directories (BEFORE ${DirectX_D3DX11_INCLUDE_DIR} ) +endif() +if(DEVEL) + add_definitions(-DDEVEL) +endif() + string(TIMESTAMP ACE_BUILDSTAMP "%Y-%m-%dT%H:%M:%SZ") set(ACE_VERSION_MAJOR 3) @@ -50,13 +110,29 @@ if(MSVC) set(GLOBAL_RC ${CMAKE_CURRENT_BINARY_DIR}/common/ace_version_win32.rc) endif() -include_directories(AFTER ${CMAKE_CURRENT_BINARY_DIR}/common) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/common) set(GLOBAL_SOURCES ${GLOBAL_RC}) + # Add extensions to build here +add_subdirectory(common) + +# Extensions + add_subdirectory(fcs) add_subdirectory(break_line) add_subdirectory(clipboard) add_subdirectory(advanced_ballistics) +# Test Extension for dynamically loading/unloading built extensions; does not build in release +if (DEVEL) + add_subdirectory(dynload) + add_subdirectory(tests) + if(USE_DIRECTX) + add_subdirectory(lib/directxtk) + endif() +endif() + + + message("Build Type: ${CMAKE_BUILD_TYPE}") \ No newline at end of file diff --git a/extensions/advanced_ballistics/AdvancedBallistics.cpp b/extensions/advanced_ballistics/AdvancedBallistics.cpp index e6c55184a7..7e87592e00 100644 --- a/extensions/advanced_ballistics/AdvancedBallistics.cpp +++ b/extensions/advanced_ballistics/AdvancedBallistics.cpp @@ -1,4 +1,4 @@ -#include "ace_common.h" +#include "shared.hpp" #include #include @@ -235,9 +235,11 @@ extern "C" void __stdcall RVExtension(char *output, int outputSize, const char *function) { + ZERO_OUTPUT(); + if (!strcmp(function, "version")) { int n = sprintf_s(output, outputSize, "%s", ACE_FULL_VERSION_STR); - return; + EXTENSION_RETURN(); } char* input = _strdup(function); @@ -257,7 +259,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) retard = calculateRetard(dragModel, ballisticCoefficient, velocity); int n = sprintf_s(output, outputSize, "%f", retard); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "atmosphericCorrection")) { double ballisticCoefficient = 1.0; double temperature = 15.0; @@ -273,7 +275,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) ballisticCoefficient = calculateAtmosphericCorrection(ballisticCoefficient, temperature, pressure, humidity, atmosphereModel); int n = sprintf_s(output, outputSize, "%f", ballisticCoefficient); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "new")) { unsigned int index = 0; double airFriction = 0.0; @@ -339,8 +341,10 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) tickTime = strtod(strtok_s(NULL, ":", &next_token), NULL); tickTime += strtod(strtok_s(NULL, ":", &next_token), NULL); - if (index >= bulletDatabase.size()) - bulletDatabase.resize(index+1); + while (index >= bulletDatabase.size()) { + Bullet bullet; + bulletDatabase.push_back(bullet); + } bulletDatabase[index].airFriction = airFriction; bulletDatabase[index].ballisticCoefficients = ballisticCoefficients; @@ -366,7 +370,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) bulletDatabase[index].randSeed = 0; int n = sprintf_s(output, outputSize, "%s", ""); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "simulate")) { // simulate:0:[-0.109985,542.529,-3.98301]:[3751.57,5332.23,214.252]:[0.598153,2.38829,0]:28.6:0:0.481542:0:215.16 unsigned int index = 0; @@ -583,7 +587,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) }; int n = sprintf_s(output, outputSize, "_bullet setVelocity (_bulletVelocity vectorAdd [%f, %f, %f]); _bullet setPosASL (_bulletPosition vectorAdd [%f, %f, %f]);", velocityOffset[0], velocityOffset[1], velocityOffset[2], positionOffset[0], positionOffset[1], positionOffset[2]); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "set")) { int height = 0; int numObjects = 0; @@ -598,7 +602,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) map->gridSurfaceIsWater.push_back(surfaceIsWater); int n = sprintf_s(output, outputSize, "%s", ""); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "init")) { int mapSize = 0; int mapGrids = 0; @@ -609,15 +613,11 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) mapGrids = (int)ceil((double)mapSize / 50.0) + 1; gridCells = mapGrids * mapGrids; - - auto map_iter = mapDatabase.find(worldName); - if (map_iter == mapDatabase.end()) - return; - map = &map_iter->second; + map = &mapDatabase[worldName]; if (map->gridHeights.size() == gridCells) { int n = sprintf_s(output, outputSize, "%s", "Terrain already initialized"); - return; + EXTENSION_RETURN(); } map->mapSize = mapSize; @@ -630,9 +630,9 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) map->gridSurfaceIsWater.reserve(gridCells); int n = sprintf_s(output, outputSize, "%s", ""); - return; + EXTENSION_RETURN(); } int n = sprintf_s(output, outputSize, "%s", ""); - return; + EXTENSION_RETURN(); } diff --git a/extensions/advanced_ballistics/CMakeLists.txt b/extensions/advanced_ballistics/CMakeLists.txt index 19b9fc41d9..51e709f6d2 100644 --- a/extensions/advanced_ballistics/CMakeLists.txt +++ b/extensions/advanced_ballistics/CMakeLists.txt @@ -1,9 +1,10 @@ set(ACE_EXTENSION_NAME "ace_advanced_ballistics") file(GLOB SOURCES *.h *.hpp *.c *.cpp) -add_library( ${ACE_EXTENSION_NAME} SHARED ${GLOBAL_SOURCES} ${SOURCES}) -add_dependencies(${ACE_EXTENSION_NAME} ace_common) -SET_TARGET_PROPERTIES(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +add_library( ${ACE_EXTENSION_NAME} SHARED ${SOURCES} ${GLOBAL_SOURCES}) +target_link_libraries(${ACE_EXTENSION_NAME} ace_common) +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES FOLDER Extensions) if(CMAKE_COMPILER_IS_GNUCXX) set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1) diff --git a/extensions/break_line/CMakeLists.txt b/extensions/break_line/CMakeLists.txt index 00a74d4c3a..5d29d295c8 100644 --- a/extensions/break_line/CMakeLists.txt +++ b/extensions/break_line/CMakeLists.txt @@ -1,9 +1,10 @@ set(ACE_EXTENSION_NAME "ace_break_line") file(GLOB SOURCES *.h *.hpp *.c *.cpp) -add_library( ${ACE_EXTENSION_NAME} SHARED ${GLOBAL_SOURCES} ${SOURCES}) -add_dependencies(${ACE_EXTENSION_NAME} ace_common) -SET_TARGET_PROPERTIES(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +add_library( ${ACE_EXTENSION_NAME} SHARED ${SOURCES} ${GLOBAL_SOURCES}) +target_link_libraries(${ACE_EXTENSION_NAME} ace_common) +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES FOLDER Extensions) if(CMAKE_COMPILER_IS_GNUCXX) set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1) diff --git a/extensions/break_line/ace_break_line.cpp b/extensions/break_line/ace_break_line.cpp index 2b253c05bc..440566b744 100644 --- a/extensions/break_line/ace_break_line.cpp +++ b/extensions/break_line/ace_break_line.cpp @@ -11,7 +11,7 @@ * String with line breaks */ -#include "ace_common.h" +#include "shared.hpp" #include #include @@ -65,12 +65,14 @@ std::string addLineBreaks(const std::vector &words) { #pragma warning( disable : 4996 ) void __stdcall RVExtension(char *output, int outputSize, const char *function) { + ZERO_OUTPUT(); if (!strcmp(function, "version")) { strncpy(output, ACE_FULL_VERSION_STR, outputSize); } else { strncpy(output, addLineBreaks(splitString(function)).c_str(), outputSize); output[outputSize - 1] = '\0'; } + EXTENSION_RETURN(); } #pragma warning( pop ) diff --git a/extensions/clipboard/ace_clipboard.cpp b/extensions/clipboard/ace_clipboard.cpp index 4809a14acf..41e3a5721f 100644 --- a/extensions/clipboard/ace_clipboard.cpp +++ b/extensions/clipboard/ace_clipboard.cpp @@ -9,7 +9,7 @@ * Returns: * None */ -#include "ace_common.h" +#include "shared.hpp" #include #include @@ -23,12 +23,15 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { std::string cur_input(function); std::string result; - if (cur_input.length() < 1) - return; + ZERO_OUTPUT(); + + if (cur_input.length() < 1) { + EXTENSION_RETURN(); + } if (!strcmp(function, "version")) { strncpy(output, ACE_FULL_VERSION_STR, outputSize); - return; + EXTENSION_RETURN(); } #ifdef _WIN32 @@ -38,14 +41,14 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { if (!hClipboardData) { result = "GlobalAlloc() failed, GetLastError=" + GetLastError(); gClipboardData = ""; - return; + EXTENSION_RETURN(); } char *pClipboardData = (char *)GlobalLock(hClipboardData); if (!pClipboardData) { result = "GlobalLock() failed, GetLastError=" + GetLastError(); gClipboardData = ""; - return; + EXTENSION_RETURN(); } memcpy(pClipboardData, gClipboardData.c_str(), gClipboardData.length()); pClipboardData[gClipboardData.length() + 1] = 0x00; @@ -82,6 +85,6 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { #endif - + EXTENSION_RETURN(); } diff --git a/extensions/cmake/FindDirectX.cmake b/extensions/cmake/FindDirectX.cmake new file mode 100644 index 0000000000..69bf1d62e8 --- /dev/null +++ b/extensions/cmake/FindDirectX.cmake @@ -0,0 +1,215 @@ +# - try to find DirectX include directories and libraries +# +# Once done this will define: +# +# DirectX_XYZ_FOUND - system has the XYZ API +# DirectX_XYZ_INCLUDE_FOUND - system has the include for the XYZ API +# DirectX_XYZ_INCLUDE_DIR - include directory for the XYZ API +# DirectX_XYZ_LIBRARY - path/name for the XYZ library +# +# Where XYZ can be any of: +# +# DDRAW +# D3D +# D3DX +# D3D8 +# D3DX8 +# D3D9 +# D3DX9 +# D3D10 +# D3D10_1 +# D3DX10 +# D3D11 +# D3D11_1 +# D3D11_2 +# D3DX11 +# D2D1 +# + + +include (CheckIncludeFileCXX) +include (FindPackageMessage) + + +if (WIN32) + + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set (DirectX_ARCHITECTURE x64) + else () + set (DirectX_ARCHITECTURE x86) + endif () + + # Can't use "$ENV{ProgramFiles(x86)}" to avoid violating CMP0053. See + # http://public.kitware.com/pipermail/cmake-developers/2014-October/023190.html + set (ProgramFiles_x86 "ProgramFiles(x86)") + if ("$ENV{${ProgramFiles_x86}}") + set (ProgramFiles "$ENV{${ProgramFiles_x86}}") + else () + set (ProgramFiles "$ENV{ProgramFiles}") + endif () + + find_path (DirectX_ROOT_DIR + Include/d3d9.h + PATHS + "$ENV{DXSDK_DIR}" + "${ProgramFiles}/Microsoft DirectX SDK (June 2010)" + "${ProgramFiles}/Microsoft DirectX SDK (February 2010)" + "${ProgramFiles}/Microsoft DirectX SDK (March 2009)" + "${ProgramFiles}/Microsoft DirectX SDK (August 2008)" + "${ProgramFiles}/Microsoft DirectX SDK (June 2008)" + "${ProgramFiles}/Microsoft DirectX SDK (March 2008)" + "${ProgramFiles}/Microsoft DirectX SDK (November 2007)" + "${ProgramFiles}/Microsoft DirectX SDK (August 2007)" + "${ProgramFiles}/Microsoft DirectX SDK" + DOC "DirectX SDK root directory" + ) + if (DirectX_ROOT_DIR) + set (DirectX_INC_SEARCH_PATH "${DirectX_ROOT_DIR}/Include") + set (DirectX_LIB_SEARCH_PATH "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}") + set (DirectX_BIN_SEARCH_PATH "${DirectX_ROOT_DIR}/Utilities/bin/x86") + endif () + + # With VS 2011 and Windows 8 SDK, the DirectX SDK is included as part of + # the Windows SDK. + # + # See also: + # - http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx + if (DEFINED MSVC_VERSION AND NOT ${MSVC_VERSION} LESS 1700) + set (USE_WINSDK_HEADERS TRUE) + endif () + + # Find a header in the DirectX SDK + macro (find_dxsdk_header var_name header) + set (include_dir_var "DirectX_${var_name}_INCLUDE_DIR") + set (include_found_var "DirectX_${var_name}_INCLUDE_FOUND") + find_path (${include_dir_var} ${header} + HINTS ${DirectX_INC_SEARCH_PATH} + DOC "The directory where ${header} resides" + CMAKE_FIND_ROOT_PATH_BOTH + ) + if (${include_dir_var}) + set (${include_found_var} TRUE) + find_package_message (${var_name}_INC "Found ${header} header: ${${include_dir_var}}/${header}" "[${${include_dir_var}}]") + endif () + mark_as_advanced (${include_found_var}) + endmacro () + + # Find a library in the DirectX SDK + macro (find_dxsdk_library var_name library) + # DirectX SDK + set (library_var "DirectX_${var_name}_LIBRARY") + find_library (${library_var} ${library} + HINTS ${DirectX_LIB_SEARCH_PATH} + DOC "The directory where ${library} resides" + CMAKE_FIND_ROOT_PATH_BOTH + ) + if (${library_var}) + find_package_message (${var_name}_LIB "Found ${library} library: ${${library_var}}" "[${${library_var}}]") + endif () + mark_as_advanced (${library_var}) + endmacro () + + # Find a header in the Windows SDK + macro (find_winsdk_header var_name header) + if (USE_WINSDK_HEADERS) + # Windows SDK + set (include_dir_var "DirectX_${var_name}_INCLUDE_DIR") + set (include_found_var "DirectX_${var_name}_INCLUDE_FOUND") + check_include_file_cxx (${header} ${include_found_var}) + set (${include_dir_var}) + mark_as_advanced (${include_found_var}) + else () + find_dxsdk_header (${var_name} ${header}) + endif () + endmacro () + + # Find a library in the Windows SDK + macro (find_winsdk_library var_name library) + if (USE_WINSDK_HEADERS) + # XXX: We currently just assume the library exists + set (library_var "DirectX_${var_name}_LIBRARY") + set (${library_var} ${library}) + mark_as_advanced (${library_var}) + else () + find_dxsdk_library (${var_name} ${library}) + endif () + endmacro () + + # Combine header and library variables into an API found variable + macro (find_combined var_name inc_var_name lib_var_name) + if (DirectX_${inc_var_name}_INCLUDE_FOUND AND DirectX_${lib_var_name}_LIBRARY) + set (DirectX_${var_name}_FOUND 1) + find_package_message (${var_name} "Found ${var_name} API" "[${DirectX_${lib_var_name}_LIBRARY}][${DirectX_${inc_var_name}_INCLUDE_DIR}]") + endif () + endmacro () + + find_winsdk_header (DDRAW ddraw.h) + find_winsdk_library (DDRAW ddraw) + find_combined (DDRAW DDRAW DDRAW) + + if (CMAKE_GENERATOR_TOOLSET MATCHES "_xp$") + # Windows 7 SDKs, used by XP toolset, do not include d3d.h + find_dxsdk_header (D3D d3d.h) + else () + find_winsdk_header (D3D d3d.h) + endif () + find_combined (D3D D3D DDRAW) + + find_dxsdk_header (D3DX d3dx.h) + find_combined (D3DX D3DX D3DX) + + find_dxsdk_header (D3D8 d3d8.h) + find_dxsdk_library (D3D8 d3d8) + find_combined (D3D8 D3D8 D3D8) + + find_dxsdk_header (D3DX8 d3dx8.h) + find_dxsdk_library (D3DX8 d3dx8) + find_combined (D3DX8 D3DX8 D3DX8) + + find_winsdk_header (D3D9 d3d9.h) + find_winsdk_library (D3D9 d3d9) + find_combined (D3D9 D3D9 D3D9) + + find_dxsdk_header (D3DX9 d3dx9.h) + find_dxsdk_library (D3DX9 d3dx9) + find_combined (D3DX9 D3DX9 D3DX9) + + find_winsdk_header (DXGI dxgi.h) + find_winsdk_header (DXGI1_2 dxgi1_2.h) + find_winsdk_header (DXGI1_3 dxgi1_3.h) + find_winsdk_library (DXGI dxgi) + + find_winsdk_header (D3D10 d3d10.h) + find_winsdk_library (D3D10 d3d10) + find_combined (D3D10 D3D10 D3D10) + + find_winsdk_header (D3D10_1 d3d10_1.h) + find_winsdk_library (D3D10_1 d3d10_1) + find_combined (D3D10_1 D3D10_1 D3D10_1) + + find_dxsdk_header (D3DX10 d3dx10.h) + find_dxsdk_library (D3DX10 d3dx10) + find_combined (D3DX10 D3DX10 D3DX10) + + find_winsdk_header (D3D11 d3d11.h) + find_winsdk_library (D3D11 d3d11) + find_combined (D3D11 D3D11 D3D11) + find_winsdk_header (D3D11_1 d3d11_1.h) + find_combined (D3D11_1 D3D11_1 D3D11) + find_winsdk_header (D3D11_2 d3d11_2.h) + find_combined (D3D11_2 D3D11_2 D3D11) + + find_dxsdk_header (D3DX11 d3dx11.h) + find_dxsdk_library (D3DX11 d3dx11) + find_combined (D3DX11 D3DX11 D3DX11) + + find_winsdk_header (D2D1 d2d1.h) + find_winsdk_library (D2D1 d2d1) + find_combined (D2D1 D2D1 D2D1) + + find_program (DirectX_FXC_EXECUTABLE fxc + HINTS ${DirectX_BIN_SEARCH_PATH} + DOC "Path to fxc.exe executable." + ) + +endif () \ No newline at end of file diff --git a/extensions/common/CMakeLists.txt b/extensions/common/CMakeLists.txt new file mode 100644 index 0000000000..620023ceb1 --- /dev/null +++ b/extensions/common/CMakeLists.txt @@ -0,0 +1,18 @@ +file(GLOB_RECURSE ACE_COMMON_SOURCES *.h *.hpp *.c *.cpp) + + +file(GLOB ACE_BASE_COMMON_SOURCES *.h *.hpp *.c *.cpp) +file(GLOB ACE_P3D_SOURCES p3d/*.h p3d/*.hpp p3d/*.c p3d/*.cpp) +file(GLOB ACE_PBO_SOURCES pbo/*.h pbo/*.hpp pbo/*.c pbo/*.cpp) +file(GLOB ACE_SIMULATION_SOURCES simulation/*.h simulation/*.hpp simulation/*.c simulation/*.cpp) +file(GLOB ACE_DIRECTX_SOURCES directx/*.h directx/*.hpp directx/*.c directx/*.cpp) +file(GLOB ACE_GLM_SOURCES glm/*.h glm/*.hpp glm/*.c glm/*.cpp) + +SOURCE_GROUP("common" FILES ${ACE_BASE_COMMON_SOURCES}) +SOURCE_GROUP("p3d" FILES ${ACE_P3D_SOURCES}) +SOURCE_GROUP("pbo" FILES ${ACE_PBO_SOURCES}) +SOURCE_GROUP("simulation" FILES ${ACE_SIMULATION_SOURCES}) +SOURCE_GROUP("directx" FILES ${ACE_DIRECTX_SOURCES}) +SOURCE_GROUP("glm" FILES ${ACE_GLM_SOURCES}) + +add_library(ace_common STATIC ${ACE_GLM_SOURCES} ${ACE_BASE_COMMON_SOURCES} ${ACE_P3D_SOURCES} ${ACE_PBO_SOURCES} ${ACE_SIMULATION_SOURCES} ${ACE_DIRECTX_SOURCES}) diff --git a/extensions/common/arguments.hpp b/extensions/common/arguments.hpp new file mode 100644 index 0000000000..70e942a241 --- /dev/null +++ b/extensions/common/arguments.hpp @@ -0,0 +1,90 @@ +#pragma once + +#include "shared.hpp" +#include "vector.hpp" + +#include +#include + +namespace ace { + class argument_accessor { + public: + argument_accessor(const uint32_t index, const std::vector & ar) : _index(index), _args(ar) { } + + const std::string & as_string() const { return _args[_index]; } + operator const std::string &() const { return as_string(); } + + float as_float() const { return atof(_args[_index].c_str()); } + operator float() const { return as_float(); } + + int as_int() const { return atoi(_args[_index].c_str()); } + operator int() const { return as_int(); } + + int as_uint32() const { return (uint32_t)atoi(_args[_index].c_str()); } + operator uint32_t() const { return as_uint32(); } + + ace::vector3 as_vector() const { + std::vector t = ace::split(_args[_index], ';'); + return ace::vector3(atof(t[0].c_str()), + atof(t[1].c_str()), + atof(t[2].c_str())); + } + operator ace::vector3() const { return as_vector(); } + + protected: + const uint32_t _index; + const std::vector & _args; + }; + + class arguments { + public: + arguments(const std::string & str) : _original(str) { + _args = ace::split(str, ','); + for (int i = 0; i < _args.size(); i++) { + _args[i] = trim(_args[i]); + } + } + + size_t size() const { return _args.size(); } + + const argument_accessor operator[] (int index) const { return argument_accessor(index, _args); } + + const std::string & as_string(uint32_t _index) const { return _args[_index]; } + float as_float(uint32_t _index) const { return atof(_args[_index].c_str()); } + int as_int(uint32_t _index) const { return atoi(_args[_index].c_str()); } + int as_uint32(uint32_t _index) const { return (uint32_t)atoi(_args[_index].c_str()); } + ace::vector3 as_vector(uint32_t _index) const { + std::vector t = ace::split(_args[_index], ';'); + return ace::vector3(atof(t[0].c_str()), + atof(t[1].c_str()), + atof(t[2].c_str())); + } + + const std::string & get() const { + return _original; + } + + std::string create(const std::string & command) const { + std::stringstream ss; + ss << command << ":"; + + for (auto & v : _args) { + ss << v << ","; + } + + // Remove the trailing , + std::string result = ss.str(); + result.erase(result.length()); + + return result; + } + static std::string create(const std::string & command, const arguments & args) { + return args.create(command); + } + + + protected: + std::vector _args; + const std::string _original; + }; +} \ No newline at end of file diff --git a/extensions/common/directx/d3d_display.cpp b/extensions/common/directx/d3d_display.cpp new file mode 100644 index 0000000000..bfc7a0e013 --- /dev/null +++ b/extensions/common/directx/d3d_display.cpp @@ -0,0 +1,439 @@ +#ifdef USE_DIRECTX + +#include "shared.hpp" +#include "d3d_display.hpp" + +#include + +#include + +using namespace DirectX; + +namespace ace { + namespace debug { + + DWORD GetMainThreadId() { + const std::shared_ptr hThreadSnapshot( + CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0), CloseHandle); + if (hThreadSnapshot.get() == INVALID_HANDLE_VALUE) { + throw std::runtime_error("GetMainThreadId failed"); + } + THREADENTRY32 tEntry; + tEntry.dwSize = sizeof(THREADENTRY32); + DWORD result = 0; + DWORD currentPID = GetCurrentProcessId(); + for (BOOL success = Thread32First(hThreadSnapshot.get(), &tEntry); + !result && success && GetLastError() != ERROR_NO_MORE_FILES; + success = Thread32Next(hThreadSnapshot.get(), &tEntry)) + { + if (tEntry.th32OwnerProcessID == currentPID) { + result = tEntry.th32ThreadID; + } + } + return result; + } + + d3d_display::d3d_display() : _fullscreen(false) {} + d3d_display::~d3d_display() {} + + bool d3d_display::render_thread(uint32_t w, uint32_t h, bool f) { + _render_thread = std::make_unique(this, d3d_display_worker_args(w, h, f) ); + return true; + } + + void d3d_display::render_worker(d3d_display_worker_args args) { + { + create(args.width, args.height, args.fullscreen); + init(); + } + run(); + } + + bool d3d_display::run() { + MSG msg = { 0 }; + + while (WM_QUIT != msg.message) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } else { + render(); + } + } + + return true; + } + + bool d3d_display::init() { + + std::lock_guard _lock(_render_lock); + + HRESULT hr = S_OK; + RECT rc; + + GetClientRect(_hWnd, &rc); + UINT width = rc.right - rc.left; + UINT height = rc.bottom - rc.top; + UINT createDeviceFlags = 0; +#ifdef _DEBUG + createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + D3D_DRIVER_TYPE driverTypes[] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + D3D_DRIVER_TYPE_REFERENCE, + }; + UINT numDriverTypes = ARRAYSIZE(driverTypes); + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + UINT numFeatureLevels = ARRAYSIZE(featureLevels); + + DXGI_SWAP_CHAIN_DESC sd; + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = 1; + sd.BufferDesc.Width = width; + sd.BufferDesc.Height = height; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = _hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.Windowed = _fullscreen ? FALSE : TRUE; + + for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) + { + _driverType = driverTypes[driverTypeIndex]; + hr = D3D11CreateDeviceAndSwapChain(nullptr, _driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, + D3D11_SDK_VERSION, &sd, &_pSwapChain, &_pd3dDevice, &_featureLevel, &_pImmediateContext); + if (SUCCEEDED(hr)) + break; + } + if (FAILED(hr)) + return false; + + // Create a render target view + ID3D11Texture2D* pBackBuffer = nullptr; + hr = _pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); + if (FAILED(hr)) + return false; + + hr = _pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &_pRenderTargetView); + pBackBuffer->Release(); + if (FAILED(hr)) + return false; + + // Create depth stencil texture + D3D11_TEXTURE2D_DESC descDepth; + ZeroMemory(&descDepth, sizeof(descDepth)); + descDepth.Width = width; + descDepth.Height = height; + descDepth.MipLevels = 1; + descDepth.ArraySize = 1; + descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + descDepth.SampleDesc.Count = 1; + descDepth.SampleDesc.Quality = 0; + descDepth.Usage = D3D11_USAGE_DEFAULT; + descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; + descDepth.CPUAccessFlags = 0; + descDepth.MiscFlags = 0; + hr = _pd3dDevice->CreateTexture2D(&descDepth, nullptr, &_pDepthStencil); + if (FAILED(hr)) + return false; + + // Create the depth stencil view + D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; + ZeroMemory(&descDSV, sizeof(descDSV)); + descDSV.Format = descDepth.Format; + descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + descDSV.Texture2D.MipSlice = 0; + hr = _pd3dDevice->CreateDepthStencilView(_pDepthStencil, &descDSV, &_pDepthStencilView); + if (FAILED(hr)) + return false; + + _pImmediateContext->OMSetRenderTargets(1, &_pRenderTargetView, _pDepthStencilView); + + // Setup the viewport + D3D11_VIEWPORT vp; + vp.Width = (FLOAT)width; + vp.Height = (FLOAT)height; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = 0; + vp.TopLeftY = 0; + _pImmediateContext->RSSetViewports(1, &vp); + + XMStoreFloat4x4(&_World, XMMatrixIdentity()); + XMStoreFloat4x4(&_View, XMMatrixLookAtLH(XMLoadFloat4(&_camera.camPosition), XMLoadFloat4(&_camera.camTarget), XMLoadFloat4(&_camera.camUp))); + XMStoreFloat4x4(&_Projection, XMMatrixPerspectiveFovLH(XM_PIDIV4, width / (FLOAT)height, 0.01f, 100.0f)); + + init_input(); + + return true; + } + + bool d3d_display::init_input() { + RAWINPUTDEVICE Rid[2]; + + Rid[0].usUsagePage = 0x01; // magic numbers + Rid[0].usUsage = 0x02; // magically means mouse + Rid[0].dwFlags = 0; // (use this if you DO NOT WANT to capture mouse) + //Rid[0].dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY ; // (use this to CAPTURE MOUSE) + Rid[0].hwndTarget = _hWnd; + + Rid[1].usUsagePage = 0x01; // magic numbers + Rid[1].usUsage = 0x06; // magically means keyboard + Rid[1].dwFlags = 0; // use RIDEV_NOHOTKEYS for no winkey + Rid[1].hwndTarget = _hWnd; + + if (!RegisterRawInputDevices(Rid, 2, sizeof(Rid[0]))) { + LOG(ERROR) << "Could not register raw input devices. "; + exit(1); + } + } + + bool d3d_display::create(uint32_t width = 1024, uint32_t height = 768, bool fullscreen = false) { + std::lock_guard _lock(_render_lock); + + _fullscreen = fullscreen; + + WNDCLASSEXW wcex; + wcex.cbSize = sizeof(WNDCLASSEXW); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)&ace::debug::d3d_display::wndproc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = (HINSTANCE)GetCurrentProcess(); + //wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SAMPLE1); + //wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszMenuName = nullptr; + wcex.lpszClassName = L"ACE3BaseDisplayClass"; + //wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SAMPLE1); + if (!RegisterClassExW(&wcex)) { + return false; + } + + // Create window + _hInst = (HINSTANCE)GetCurrentProcess(); + RECT rc = { 0, 0, width, height }; + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); + _hWnd = CreateWindowW(L"ACE3BaseDisplayClass", L"ACE3 D3D Render", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, _hInst, + nullptr); + + if (!_hWnd) { + return false; + } + + // Attach our input to the master input + //AttachThreadInput(GetCurrentThreadId(), GetMainThraedId()); + + SetWindowLongPtr(_hWnd, GWLP_USERDATA, (LONG)this); + + ShowWindow(_hWnd, 5); + + return true; + } + + bool d3d_display::destroy() { + if (_pImmediateContext) _pImmediateContext->ClearState(); + + if (_pBatchInputLayout) _pBatchInputLayout->Release(); + + if (_pTextureRV1) _pTextureRV1->Release(); + if (_pTextureRV2) _pTextureRV2->Release(); + + if (_pDepthStencilView) _pDepthStencilView->Release(); + if (_pDepthStencil) _pDepthStencil->Release(); + if (_pRenderTargetView) _pRenderTargetView->Release(); + if (_pSwapChain) _pSwapChain->Release(); + if (_pImmediateContext) _pImmediateContext->Release(); + if (_pd3dDevice) _pd3dDevice->Release(); + + return true; + } + + bool d3d_display::render() { + // Update our time + static float t = 0.0f; + static float dt = 0.f; + if (_driverType == D3D_DRIVER_TYPE_REFERENCE) { + t += (float)XM_PI * 0.0125f; + } else { + static uint64_t dwTimeStart = 0; + static uint64_t dwTimeLast = 0; + uint64_t dwTimeCur = GetTickCount64(); + if (dwTimeStart == 0) + dwTimeStart = dwTimeCur; + t = (dwTimeCur - dwTimeStart) / 1000.0f; + dt = (dwTimeCur - dwTimeLast) / 1000.0f; + dwTimeLast = dwTimeCur; + } + + { + std::lock_guard _lock(_render_lock); + + _pImmediateContext->ClearRenderTargetView(_pRenderTargetView, Colors::MidnightBlue); + _pImmediateContext->ClearDepthStencilView(_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); + + update_camera(); + step(); + + _pSwapChain->Present(0, 0); + } + + return true; + } + + bool d3d_display::step() { + return true; + } + + void d3d_display::_move_camera(ace::vector3 direction) { + + } + void d3d_display::_rotate_camera(ace::vector3 direction) { + + } + void d3d_display::update_camera() { + XMVECTOR DefaultForward, DefaultRight, camPosition; + + DefaultForward = XMLoadFloat4(&_camera.DefaultForward); + DefaultRight = XMLoadFloat4(&_camera.DefaultRight); + camPosition = XMLoadFloat4(&_camera.camPosition); + + XMMATRIX camRotationMatrix = XMMatrixRotationRollPitchYaw(_camera.camPitch, _camera.camYaw, 0); + XMVECTOR camTarget = XMVector3TransformCoord(DefaultForward, camRotationMatrix); + camTarget = XMVector3Normalize(camTarget); + + XMVECTOR camRight = XMVector3TransformCoord(DefaultRight, camRotationMatrix); + XMVECTOR camForward = XMVector3TransformCoord(DefaultForward, camRotationMatrix); + XMVECTOR camUp = XMVector3Cross(camForward, camRight); + + camPosition += _camera.moveLeftRight * camRight; + camPosition += _camera.moveBackForward * camForward; + XMStoreFloat4(&_camera.camPosition, camPosition); + + _camera.moveLeftRight = 0.0f; + _camera.moveBackForward = 0.0f; + + camTarget = camPosition + camTarget; + + XMStoreFloat4x4(&_View, XMMatrixLookAtLH(camPosition, camTarget, camUp)); + } + + LRESULT CALLBACK d3d_display::_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + PAINTSTRUCT ps; + HDC hdc; + + switch (message) { + case WM_INPUT: { + UINT dwSize; + if (GetActiveWindow() != _hWnd) { + return DefWindowProc(hWnd, message, wParam, lParam); + } + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, + sizeof(RAWINPUTHEADER)); + LPBYTE lpb = new BYTE[dwSize]; + if (lpb == NULL) { + return 0; + } + + int readSize = GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); + + if (readSize != dwSize) + break; + + RAWINPUT* raw = (RAWINPUT*)lpb; + + float speed = 0.5f; + + if (raw->header.dwType == RIM_TYPEKEYBOARD) { + switch (raw->data.keyboard.VKey) { + case VK_SPACE: { + XMStoreFloat4(&_camera.camPosition, XMVectorSet(0, 0, 0, 0)); + break; + } + // Camera Movement + case 0x57: case VK_NUMPAD8: + case VK_UP: { + _camera.moveBackForward += speed; + break; + } + case 0x53: case VK_NUMPAD2: + case VK_DOWN: { + _camera.moveBackForward -= speed; + break; + } + case 0x41: case VK_NUMPAD4: + case VK_LEFT: { + _camera.moveLeftRight -= speed; + break; + } + case 0x44: case VK_NUMPAD6: + case VK_RIGHT: { + _camera.moveLeftRight += speed; + break; + } + // Numpad Movement + case VK_NUMPAD5: { + XMStoreFloat4(&_camera.camPosition, XMVectorSet(0, 0, 0, 0)); + break; + } + } + } + else if (raw->header.dwType == RIM_TYPEMOUSE) { + RAWMOUSE mouseCurrState = raw->data.mouse; + + if ((mouseCurrState.lLastX != _last_mouse_state.lLastY) || (mouseCurrState.lLastX != _last_mouse_state.lLastY)) + { + _camera.camYaw += mouseCurrState.lLastX * 0.005f; + _camera.camPitch += mouseCurrState.lLastY * 0.005f; + _last_mouse_state = mouseCurrState; + } + + } + + delete[] lpb; + return 0; + } + + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + break; + + case WM_DESTROY: + PostQuitMessage(0); + + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + + return 0; + } + LRESULT CALLBACK d3d_display::wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + LONG data; + data = GetWindowLongPtr(hWnd, GWLP_USERDATA); + if (data) { + return ((d3d_display*)data)->_wndproc(hWnd, message, wParam, lParam); + } else { + return DefWindowProc(hWnd, message, wParam, lParam); + } + } + }; + + +}; + +#endif \ No newline at end of file diff --git a/extensions/common/directx/d3d_display.hpp b/extensions/common/directx/d3d_display.hpp new file mode 100644 index 0000000000..b10e8ef070 --- /dev/null +++ b/extensions/common/directx/d3d_display.hpp @@ -0,0 +1,130 @@ +#pragma once + +#ifdef USE_DIRECTX + +#include +#include +#include +#include + +#include +#include +#include + +#include "singleton.hpp" +#include "vector.hpp" + +#define IDI_ACE_DEBUG 666 + +namespace ace { + namespace debug { + + __declspec(align(16)) + struct camera_movement { + camera_movement() { + XMStoreFloat4(&DefaultForward, DirectX::XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f)); + XMStoreFloat4(&DefaultRight, DirectX::XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f)); + XMStoreFloat4(&camForward, DirectX::XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f)); + XMStoreFloat4(&camRight, DirectX::XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f)); + + camYaw = 0.0f; + camPitch = 0.0f; + + moveLeftRight = 0.0f; + moveBackForward = 0.0f; + + XMStoreFloat4(&camPosition, DirectX::XMVectorSet(0.0f, 12.0f, 6.0f, 0.0f)); + XMStoreFloat4(&camTarget, DirectX::XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f)); + XMStoreFloat4(&camUp, DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f)); + } + + DirectX::XMFLOAT4 DefaultForward; + DirectX::XMFLOAT4 DefaultRight; + DirectX::XMFLOAT4 camForward; + DirectX::XMFLOAT4 camRight; + + DirectX::XMFLOAT4X4 camRotationMatrix; + DirectX::XMFLOAT4X4 groundWorld; + + float moveLeftRight; + float moveBackForward; + + float camYaw; + float camPitch; + + DirectX::XMFLOAT4 camPosition; + DirectX::XMFLOAT4 camTarget; + DirectX::XMFLOAT4 camUp; + }; + + struct d3d_display_worker; + struct d3d_display_worker_args; + __declspec(align(16)) + class d3d_display { + public: + d3d_display(); + ~d3d_display(); + + virtual bool run(); + virtual bool render(); + virtual bool render_thread(uint32_t, uint32_t, bool); + + virtual void update_camera(); + virtual bool step(); + + virtual bool create(uint32_t, uint32_t, bool); + virtual bool init(); + virtual bool init_input(); + + virtual bool destroy(); + + void render_worker(d3d_display_worker_args); + + static LRESULT CALLBACK wndproc(HWND, UINT, WPARAM, LPARAM); + LRESULT CALLBACK _wndproc(HWND, UINT, WPARAM, LPARAM); + protected: + void _move_camera(ace::vector3); + void _rotate_camera(ace::vector3); + + std::unique_ptr _render_thread; + std::mutex _render_lock; + + bool _fullscreen; + HINSTANCE _hInst = nullptr; + HWND _hWnd = nullptr; + D3D_DRIVER_TYPE _driverType = D3D_DRIVER_TYPE_NULL; + D3D_FEATURE_LEVEL _featureLevel = D3D_FEATURE_LEVEL_11_0; + ID3D11Device* _pd3dDevice = nullptr; + ID3D11DeviceContext* _pImmediateContext = nullptr; + IDXGISwapChain* _pSwapChain = nullptr; + ID3D11RenderTargetView* _pRenderTargetView = nullptr; + ID3D11Texture2D* _pDepthStencil = nullptr; + ID3D11DepthStencilView* _pDepthStencilView = nullptr; + + ID3D11ShaderResourceView* _pTextureRV1 = nullptr; + ID3D11ShaderResourceView* _pTextureRV2 = nullptr; + ID3D11InputLayout* _pBatchInputLayout = nullptr; + + DirectX::XMFLOAT4X4 _World; + DirectX::XMFLOAT4X4 _View; + DirectX::XMFLOAT4X4 _Projection; + + RAWMOUSE _last_mouse_state; + camera_movement _camera; + + }; + struct d3d_display_worker_args { + d3d_display_worker_args(uint32_t w, uint32_t h, bool f) : width(w), height(h), fullscreen(f) {} + uint32_t width; + uint32_t height; + bool fullscreen; + }; + struct d3d_display_worker { + d3d_display_worker(d3d_display * obj, d3d_display_worker_args args) : thread(&ace::debug::d3d_display::render_worker, obj, args) {} + ~d3d_display_worker() { thread.join(); } + std::thread thread; + }; + }; +}; + +#endif \ No newline at end of file diff --git a/extensions/common/dispatch.hpp b/extensions/common/dispatch.hpp new file mode 100644 index 0000000000..0a37824b83 --- /dev/null +++ b/extensions/common/dispatch.hpp @@ -0,0 +1,153 @@ +#pragma once + +#include +#include +#include +#include + +#include "shared.hpp" +#include "arguments.hpp" +#include "singleton.hpp" + +namespace ace { + class dispatcher { + public: + dispatcher() : _ready(true) {} + + virtual bool call(const std::string & name_, const arguments & args_, std::string & result_) { + if (_methods.find(name_) == _methods.end()) { + // @TODO: Exceptions + return false; + } + return _methods[name_](args_, result_); + } + + bool add(const std::string & name_, std::function func_) { + if (_methods.find(name_) != _methods.end()) { + // @TODO: Exceptions + return false; + } + _methods[name_] = func_; + + return true; + } + + bool ready() const { return _ready; } + void ready(bool r) { _ready.exchange(r); } + protected: + std::unordered_map < std::string, std::function > _methods; + std::atomic_bool _ready; + }; + class dispatch : public dispatcher, public singleton { }; + + struct dispatch_message { + dispatch_message(const std::string & command_, const arguments & args_, const uint64_t id_) : command(command_), args(args_), id(id_) {} + std::string command; + arguments args; + uint64_t id; + }; + struct dispatch_result { + dispatch_result() {} + dispatch_result(const std::string &res, const uint64_t id_) : message(res), id(id_) {} + std::string message; + uint64_t id; + }; + + class threaded_dispatcher : public dispatcher { + public: + threaded_dispatcher() : _stop(false), _worker(&ace::threaded_dispatcher::monitor, this) { + + } + ~threaded_dispatcher() {} + + bool call(const std::string & name_, const arguments & args_, std::string & result_, bool threaded) { + if (_methods.find(name_) == _methods.end()) { + // @TODO: Exceptions + return false; + } + if (threaded) { + std::lock_guard lock(_messages_lock); + _messages.push(dispatch_message(name_, args_, _message_id)); + + // @TODO: We should provide an interface for this serialization. + std::stringstream ss; + ss << "[\"result_id\", \"" << _message_id << "\" ]"; + result_ = ss.str(); + + _message_id = _message_id + 1; + } else { +#ifdef _DEBUG + if (name_ != "fetch_result") { + LOG(TRACE) << "dispatch[immediate]:\t[" << name_ << "] { " << args_.get() << " }"; + } +#endif + return dispatcher::call(name_, args_, result_); + } + + return true; + } + bool call(const std::string & name_, const arguments & args_, std::string & result_) override { + return call(name_, args_, result_, false); + } + + void push_result(const dispatch_result & result) { + { + std::lock_guard lock(_results_lock); + _results.push(result); + } + } + void push_result(const std::string & result) { + push_result(dispatch_result(result, -1)); + } + void stop() { + std::lock_guard lock(_messages_lock); + _stop = true; + } + protected: + void monitor() { + _ready = false; + while (!_stop) { + { + std::lock_guard lock(_messages_lock); + while (!_messages.empty()) { + if (_ready) { + dispatch_result result; + dispatch_message _message = std::move(_messages.front()); + _messages.pop(); + + result.id = _message.id; + result.message.resize(4096); +#ifdef _DEBUG + if (_message.command != "fetch_result") { + LOG(TRACE) << "dispatch[threaded]:\t[" << _message.command << "]"; + if (_message.args.size() > 0) { + // LOG(TRACE) << "\t{ " << _messages.front().args.get() << " }"; + } + } +#endif + dispatcher::call(_message.command, _message.args, result.message); + { + std::lock_guard lock(_results_lock); + _results.push(result); + } + + + } + } + } + sleep(5); + } + } + std::atomic_bool _stop; + std::queue _results; + std::mutex _results_lock; + + std::queue _messages; + std::mutex _messages_lock; + + std::thread _worker; + + uint64_t _message_id; + }; + class threaded_dispatch : public threaded_dispatcher, public singleton { }; +}; \ No newline at end of file diff --git a/extensions/common/easyloggingc++.hpp b/extensions/common/easyloggingc++.hpp new file mode 100644 index 0000000000..3a5455c4d0 --- /dev/null +++ b/extensions/common/easyloggingc++.hpp @@ -0,0 +1,6718 @@ +// +// Easylogging++ v9.80 +// Single-header only, cross-platform logging library for C++ applications +// +// Copyright (c) 2015 muflihun.com +// +// This library is released under the MIT Licence. +// http://easylogging.muflihun.com/licence.php +// +// easylogging@muflihun.com +// +// https://github.com/easylogging/easyloggingpp +// http://easylogging.muflihun.com +// http://muflihun.com +// +#ifndef EASYLOGGINGPP_H +#define EASYLOGGINGPP_H +// Compilers and C++0x/C++11 Evaluation +#if defined(__GNUC__) +# define ELPP_COMPILER_GCC 1 +# define ELPP_GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define ELPP_CXX0X 1 +# elif(ELPP_GCC_VERSION >= 40801) +# define ELPP_CXX11 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +#endif // defined(__GNUC__) +// Visual C++ +#if defined(_MSC_VER) +# define ELPP_COMPILER_MSVC 1 +# define ELPP_CRT_DBG_WARNINGS 1 +# if (_MSC_VER == 1600) +# define ELPP_CXX0X 1 +# elif(_MSC_VER >= 1700) +# define ELPP_CXX11 1 +# endif // (_MSC_VER == 1600) +#endif // defined(_MSC_VER) +// Clang++ +#if defined(__clang__) && (__clang__ == 1) +# define ELPP_COMPILER_CLANG 1 +# define ELPP_CLANG_VERSION (__clang_major__ * 10000 \ + + __clang_minor__ * 100 \ + + __clang_patchlevel__) +# if (ELPP_CLANG_VERSION >= 30300) +# define ELPP_CXX11 1 +# endif // (ELPP_CLANG_VERSION >= 30300) +#endif // defined(__clang__) && (__clang__ == 1) +// MinGW +#if defined(__MINGW32__) || defined(__MINGW64__) +# define ELPP_MINGW 1 +#endif // defined(__MINGW32__) || defined(__MINGW64__) +// Cygwin +#if defined(__CYGWIN__) && (__CYGWIN__ == 1) +# define ELPP_CYGWIN 1 +#endif // defined(__CYGWIN__) && (__CYGWIN__ == 1) +// Intel C++ +#if defined(__INTEL_COMPILER) +# define ELPP_COMPILER_INTEL 1 +#endif +// Operating System Evaluation +// Windows +#if defined(_WIN32) || defined(_WIN64) +# define ELPP_OS_WINDOWS 1 +#endif // defined(_WIN32) || defined(_WIN64) +// Linux +#if (defined(__linux) || defined(__linux__)) +# define ELPP_OS_LINUX 1 +#endif // (defined(__linux) || defined(__linux__)) +// Mac +#if defined(__APPLE__) +# define ELPP_OS_MAC 1 +#endif // defined(__APPLE__) +// FreeBSD +#if defined(__FreeBSD__) +# define ELPP_OS_FREEBSD 1 +#endif +// Solaris +#if defined(__sun) +# define ELPP_OS_SOLARIS 1 +#endif +// Unix +#if ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS) && (!ELPP_OS_WINDOWS)) +# define ELPP_OS_UNIX 1 +#endif // ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS) && (!ELPP_OS_WINDOWS)) +// Android +#if defined(__ANDROID__) +# define ELPP_OS_ANDROID 1 +#endif // defined(__ANDROID__) +// Evaluating Cygwin as *nix OS +#if !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN +# undef ELPP_OS_UNIX +# undef ELPP_OS_LINUX +# define ELPP_OS_UNIX 1 +# define ELPP_OS_LINUX 1 +#endif // !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN +#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_INFO) +# define ELPP_INTERNAL_DEBUGGING_OUT_INFO std::cout +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_ERROR) +# define ELPP_INTERNAL_DEBUGGING_OUT_ERROR std::cerr +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +#if !defined(ELPP_INTERNAL_DEBUGGING_ENDL) +# define ELPP_INTERNAL_DEBUGGING_ENDL std::endl +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +#if !defined(ELPP_INTERNAL_DEBUGGING_MSG) +# define ELPP_INTERNAL_DEBUGGING_MSG(msg) msg +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +// Internal Assertions and errors +#if !defined(ELPP_DISABLE_ASSERT) +# if (defined(ELPP_DEBUG_ASSERT_FAILURE)) +# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ + std::stringstream internalInfoStream; internalInfoStream << msg; \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ + << "EASYLOGGING++ ASSERTION FAILED (LINE: " << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" \ + << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" << ELPP_INTERNAL_DEBUGGING_ENDL; base::utils::abort(1, \ + "ELPP Assertion failure, please define ELPP_DEBUG_ASSERT_FAILURE"); } +# else +# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ + std::stringstream internalInfoStream; internalInfoStream << msg; \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR\ + << "ASSERTION FAILURE FROM EASYLOGGING++ (LINE: " \ + << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" \ + << ELPP_INTERNAL_DEBUGGING_ENDL; } +# endif // (defined(ELPP_DEBUG_ASSERT_FAILURE)) +#else +# define ELPP_ASSERT(x, y) +#endif //(!defined(ELPP_DISABLE_ASSERT) +#if ELPP_COMPILER_MSVC +# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ + { char buff[256]; strerror_s(buff, 256, errno); \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << buff << " [" << errno << "]";} (void)0 +#else +# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << strerror(errno) << " [" << errno << "]"; (void)0 +#endif // ELPP_COMPILER_MSVC +#if defined(ELPP_DEBUG_ERRORS) +# if !defined(ELPP_INTERNAL_ERROR) +# define ELPP_INTERNAL_ERROR(msg, pe) { \ + std::stringstream internalInfoStream; internalInfoStream << " " << msg; \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ + << "ERROR FROM EASYLOGGING++ (LINE: " << __LINE__ << ") " \ + << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << ELPP_INTERNAL_DEBUGGING_ENDL; \ + if (pe) { ELPP_INTERNAL_DEBUGGING_OUT_ERROR << " "; ELPP_INTERNAL_DEBUGGING_WRITE_PERROR; }} (void)0 +# endif +#else +# undef ELPP_INTERNAL_INFO +# define ELPP_INTERNAL_ERROR(msg, pe) +#endif // defined(ELPP_DEBUG_ERRORS) +#if (defined(ELPP_DEBUG_INFO)) +# if !(defined(ELPP_INTERNAL_INFO_LEVEL)) +# define ELPP_INTERNAL_INFO_LEVEL 9 +# endif // !(defined(ELPP_INTERNAL_INFO_LEVEL)) +# if !defined(ELPP_INTERNAL_INFO) +# define ELPP_INTERNAL_INFO(lvl, msg) { if (lvl <= ELPP_INTERNAL_INFO_LEVEL) { \ + std::stringstream internalInfoStream; internalInfoStream << " " << msg; \ + ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) \ + << ELPP_INTERNAL_DEBUGGING_ENDL; }} +# endif +#else +# undef ELPP_INTERNAL_INFO +# define ELPP_INTERNAL_INFO(lvl, msg) +#endif // (defined(ELPP_DEBUG_INFO)) +#if defined(ELPP_STACKTRACE_ON_CRASH) +# if (ELPP_COMPILER_GCC && !ELPP_MINGW) +# define ELPP_STACKTRACE 1 +# else +# if ELPP_COMPILER_MSVC +# pragma message("Stack trace not available for this compiler") +# else +# warning "Stack trace not available for this compiler"; +# endif // ELPP_COMPILER_MSVC +# endif // ELPP_COMPILER_GCC +#endif // (defined(ELPP_STACKTRACE_ON_CRASH)) +// Miscellaneous macros +#define ELPP_UNUSED(x) (void)x +#if ELPP_OS_UNIX +// Log file permissions for unix-based systems +# define ELPP_LOG_PERMS S_IRUSR | S_IWUSR | S_IXUSR | S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IXOTH +#endif // ELPP_OS_UNIX +#if defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC +# if defined(ELPP_EXPORT_SYMBOLS) +# define ELPP_EXPORT __declspec(dllexport) +# else +# define ELPP_EXPORT __declspec(dllimport) +# endif // defined(ELPP_EXPORT_SYMBOLS) +#else +# define ELPP_EXPORT +#endif // defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC +// Some special functions that are VC++ specific +#undef STRTOK +#undef STRERROR +#undef STRCAT +#undef STRCPY +#if ELPP_CRT_DBG_WARNINGS +# define STRTOK(a, b, c) strtok_s(a, b, c) +# define STRERROR(a, b, c) strerror_s(a, b, c) +# define STRCAT(a, b, len) strcat_s(a, len, b) +# define STRCPY(a, b, len) strcpy_s(a, len, b) +#else +# define STRTOK(a, b, c) strtok(a, b) +# define STRERROR(a, b, c) strerror(c) +# define STRCAT(a, b, len) strcat(a, b) +# define STRCPY(a, b, len) strcpy(a, b) +#endif +// Compiler specific support evaluations +#if (!ELPP_MINGW && !ELPP_COMPILER_CLANG) || defined(ELPP_FORCE_USE_STD_THREAD) +# define ELPP_USE_STD_THREADING 1 +#endif // (!ELPP_MINGW && !ELPP_COMPILER_CLANG) || defined(ELPP_FORCE_USE_STD_THREAD) +#undef ELPP_FINAL +#if ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) +# define ELPP_FINAL +#else +# define ELPP_FINAL final +#endif // ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) +#if defined(ELPP_EXPERIMENTAL_ASYNC) +# define ELPP_ASYNC_LOGGING 1 +#else +# define ELPP_ASYNC_LOGGING 0 +#endif // defined(ELPP_EXPERIMENTAL_ASYNC) +#if defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING +# define ELPP_THREADING_ENABLED 1 +#endif // defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING +// Function macro ELPP_FUNC +#undef ELPP_FUNC +#if ELPP_COMPILER_MSVC // Visual C++ +# define ELPP_FUNC __FUNCSIG__ +#elif ELPP_COMPILER_GCC // GCC +# define ELPP_FUNC __PRETTY_FUNCTION__ +#elif ELPP_COMPILER_INTEL // Intel C++ +# define ELPP_FUNC __PRETTY_FUNCTION__ +#elif ELPP_COMPILER_CLANG // Clang++ +# define ELPP_FUNC __PRETTY_FUNCTION__ +#else +# if defined(__func__) +# define ELPP_FUNC __func__ +# else +# define ELPP_FUNC "" +# endif // defined(__func__) +#endif // defined(_MSC_VER) +#undef ELPP_VARIADIC_TEMPLATES_SUPPORTED +// Keep following line commented until features are fixed +#if ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800) +# define ELPP_VARIADIC_TEMPLATES_SUPPORTED 1 +#endif // ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800) +// Logging Enable/Disable macros +#if (!defined(ELPP_DISABLE_LOGS)) +# define ELPP_LOGGING_ENABLED 1 +#endif // (!defined(ELPP_DISABLE_LOGS)) +#if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG)))) +# define ELPP_DEBUG_LOG 1 +#else +# define ELPP_DEBUG_LOG 0 +#endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG)))) +#if (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_INFO_LOG 1 +#else +# define ELPP_INFO_LOG 0 +#endif // (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_WARNING_LOG 1 +#else +# define ELPP_WARNING_LOG 0 +#endif // (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_ERROR_LOG 1 +#else +# define ELPP_ERROR_LOG 0 +#endif // (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_FATAL_LOG 1 +#else +# define ELPP_FATAL_LOG 0 +#endif // (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_TRACE_LOG 1 +#else +# define ELPP_TRACE_LOG 0 +#endif // (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_VERBOSE_LOG 1 +#else +# define ELPP_VERBOSE_LOG 0 +#endif // (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!(ELPP_CXX0X || ELPP_CXX11)) +# error "Easylogging++ 9.0+ is only compatible with C++0x (or higher) compliant compiler" +#endif // (!(ELPP_CXX0X || ELPP_CXX11)) +// Headers +#if defined(ELPP_SYSLOG) +# include +#endif // defined(ELPP_SYSLOG) +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(ELPP_UNICODE) +# include +# if ELPP_OS_WINDOWS +# include +# endif // ELPP_OS_WINDOWS +#endif // defined(ELPP_UNICODE) +#if ELPP_STACKTRACE +# include +# include +#endif // ELPP_STACKTRACE +#if ELPP_OS_ANDROID +# include +#endif // ELPP_OS_ANDROID +#if ELPP_OS_UNIX +# include +# include +#elif ELPP_OS_WINDOWS +# include +# include +# if defined(WIN32_LEAN_AND_MEAN) +# if defined(ELPP_WINSOCK2) +# include +# else +# include +# endif // defined(ELPP_WINSOCK2) +# endif // defined(WIN32_LEAN_AND_MEAN) +#endif // ELPP_OS_UNIX +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if ELPP_THREADING_ENABLED +# if ELPP_USE_STD_THREADING +# include +# include +# else +# if ELPP_OS_UNIX +# include +# endif // ELPP_OS_UNIX +# endif // ELPP_USE_STD_THREADING +#endif // ELPP_THREADING_ENABLED +#if ELPP_ASYNC_LOGGING +# include +# include +# include +#endif // ELPP_ASYNC_LOGGING +#if defined(ELPP_STL_LOGGING) +// For logging STL based templates +# include +# include +# include +# include +# include +# include +# if defined(ELPP_LOG_STD_ARRAY) +# include +# endif // defined(ELPP_LOG_STD_ARRAY) +# if defined(ELPP_LOG_UNORDERED_MAP) +# include +# endif // defined(ELPP_LOG_UNORDERED_MAP) +# if defined(ELPP_LOG_UNORDERED_SET) +# include +# endif // defined(ELPP_UNORDERED_SET) +#endif // defined(ELPP_STL_LOGGING) +#if defined(ELPP_QT_LOGGING) +// For logging Qt based classes & templates +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif // defined(ELPP_QT_LOGGING) +#if defined(ELPP_BOOST_LOGGING) +// For logging boost based classes & templates +# include +# include +# include +# include +# include +# include +# include +# include +#endif // defined(ELPP_BOOST_LOGGING) +#if defined(ELPP_WXWIDGETS_LOGGING) +// For logging wxWidgets based classes & templates +# include +#endif // defined(ELPP_WXWIDGETS_LOGGING) +// Forward declarations +namespace el { + class Logger; + class LogMessage; + class PerformanceTrackingData; + class Loggers; + class Helpers; + template class Callback; + class LogDispatchCallback; + class PerformanceTrackingCallback; + class LogDispatchData; + namespace base { + class Storage; + class RegisteredLoggers; + class PerformanceTracker; + class MessageBuilder; + class Writer; + class PErrorWriter; + class LogDispatcher; + class DefaultLogBuilder; + class DefaultLogDispatchCallback; +#if ELPP_ASYNC_LOGGING + class AsyncLogDispatchCallback; + class AsyncDispatchWorker; +#endif // ELPP_ASYNC_LOGGING + class DefaultPerformanceTrackingCallback; + } // namespace base +} // namespace el + /// @brief Easylogging++ entry namespace +namespace el { + /// @brief Namespace containing base/internal functionality used by Easylogging++ + namespace base { + /// @brief Data types used by Easylogging++ + namespace type { +#undef ELPP_LITERAL +#undef ELPP_STRLEN +#undef ELPP_COUT +#if defined(ELPP_UNICODE) +# define ELPP_LITERAL(txt) L##txt +# define ELPP_STRLEN wcslen +# if defined ELPP_CUSTOM_COUT +# define ELPP_COUT ELPP_CUSTOM_COUT +# else +# define ELPP_COUT std::wcout +# endif // defined ELPP_CUSTOM_COUT + typedef wchar_t char_t; + typedef std::wstring string_t; + typedef std::wstringstream stringstream_t; + typedef std::wfstream fstream_t; + typedef std::wostream ostream_t; +#else +# define ELPP_LITERAL(txt) txt +# define ELPP_STRLEN strlen +# if defined ELPP_CUSTOM_COUT +# define ELPP_COUT ELPP_CUSTOM_COUT +# else +# define ELPP_COUT std::cout +# endif // defined ELPP_CUSTOM_COUT + typedef char char_t; + typedef std::string string_t; + typedef std::stringstream stringstream_t; + typedef std::fstream fstream_t; + typedef std::ostream ostream_t; +#endif // defined(ELPP_UNICODE) +#if defined(ELPP_CUSTOM_COUT_LINE) +# define ELPP_COUT_LINE(logLine) ELPP_CUSTOM_COUT_LINE(logLine) +#else +# define ELPP_COUT_LINE(logLine) logLine << std::flush +#endif // defined(ELPP_CUSTOM_COUT_LINE) + typedef unsigned short EnumType; + typedef std::shared_ptr StoragePointer; + typedef int VerboseLevel; + typedef std::shared_ptr LogDispatchCallbackPtr; + typedef std::shared_ptr PerformanceTrackingCallbackPtr; + } // namespace type + /// @brief Internal helper class that prevent copy constructor for class + /// + /// @detail When using this class simply inherit it privately + class NoCopy { + protected: + NoCopy(void) {} + private: + NoCopy(const NoCopy&); + NoCopy& operator=(const NoCopy&); + }; + /// @brief Internal helper class that makes all default constructors private. + /// + /// @detail This prevents initializing class making it static unless an explicit constructor is declared. + /// When using this class simply inherit it privately + class StaticClass { + private: + StaticClass(void); + StaticClass(const StaticClass&); + StaticClass& operator=(const StaticClass&); + }; + } // namespace base + /// @brief Represents enumeration for severity level used to determine level of logging + /// + /// @detail With Easylogging++, developers may disable or enable any level regardless of + /// what the severity is. Or they can choose to log using hierarchical logging flag + enum class Level : base::type::EnumType { + /// @brief Generic level that represents all the levels. Useful when setting global configuration for all levels + Global = 1, + /// @brief Information that can be useful to back-trace certain events - mostly useful than debug logs. + Trace = 2, + /// @brief Informational events most useful for developers to debug application + Debug = 4, + /// @brief Severe error information that will presumably abort application + Fatal = 8, + /// @brief Information representing errors in application but application will keep running + Error = 16, + /// @brief Useful when application has potentially harmful situtaions + Warning = 32, + /// @brief Information that can be highly useful and vary with verbose logging level. + Verbose = 64, + /// @brief Mainly useful to represent current progress of application + Info = 128, + /// @brief Represents unknown level + Unknown = 1010 + }; + /// @brief Static class that contains helper functions for el::Level + class LevelHelper : base::StaticClass { + public: + /// @brief Represents minimum valid level. Useful when iterating through enum. + static const base::type::EnumType kMinValid = static_cast(Level::Trace); + /// @brief Represents maximum valid level. This is used internally and you should not need it. + static const base::type::EnumType kMaxValid = static_cast(Level::Info); + /// @brief Casts level to int, useful for iterating through enum. + static base::type::EnumType castToInt(Level level) { + return static_cast(level); + } + /// @brief Casts int(ushort) to level, useful for iterating through enum. + static Level castFromInt(base::type::EnumType l) { + return static_cast(l); + } + /// @brief Converts level to associated const char* + /// @return Upper case string based level. + static const char* convertToString(Level level) { + // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. + if (level == Level::Global) return "GLOBAL"; + if (level == Level::Debug) return "DEBUG"; + if (level == Level::Info) return "INFO"; + if (level == Level::Warning) return "WARNING"; + if (level == Level::Error) return "ERROR"; + if (level == Level::Fatal) return "FATAL"; + if (level == Level::Verbose) return "VERBOSE"; + if (level == Level::Trace) return "TRACE"; + return "UNKNOWN"; + } + /// @brief Converts from levelStr to Level + /// @param levelStr Upper case string based level. + /// Lower case is also valid but providing upper case is recommended. + static Level convertFromString(const char* levelStr) { + if ((strcmp(levelStr, "GLOBAL") == 0) || (strcmp(levelStr, "global") == 0)) + return Level::Global; + if ((strcmp(levelStr, "DEBUG") == 0) || (strcmp(levelStr, "debug") == 0)) + return Level::Debug; + if ((strcmp(levelStr, "INFO") == 0) || (strcmp(levelStr, "info") == 0)) + return Level::Info; + if ((strcmp(levelStr, "WARNING") == 0) || (strcmp(levelStr, "warning") == 0)) + return Level::Warning; + if ((strcmp(levelStr, "ERROR") == 0) || (strcmp(levelStr, "error") == 0)) + return Level::Error; + if ((strcmp(levelStr, "FATAL") == 0) || (strcmp(levelStr, "fatal") == 0)) + return Level::Fatal; + if ((strcmp(levelStr, "VERBOSE") == 0) || (strcmp(levelStr, "verbose") == 0)) + return Level::Verbose; + if ((strcmp(levelStr, "TRACE") == 0) || (strcmp(levelStr, "trace") == 0)) + return Level::Trace; + return Level::Unknown; + } + /// @brief Applies specified function to each level starting from startIndex + /// @param startIndex initial value to start the iteration from. This is passed as pointer and + /// is left-shifted so this can be used inside function (fn) to represent current level. + /// @param fn function to apply with each level. This bool represent whether or not to stop iterating through levels. + static inline void forEachLevel(base::type::EnumType* startIndex, const std::function& fn) { + base::type::EnumType lIndexMax = LevelHelper::kMaxValid; + do { + if (fn()) { + break; + } + *startIndex = static_cast(*startIndex << 1); + } while (*startIndex <= lIndexMax); + } + }; + /// @brief Represents enumeration of ConfigurationType used to configure or access certain aspect + /// of logging + enum class ConfigurationType : base::type::EnumType { + /// @brief Determines whether or not corresponding level and logger of logging is enabled + /// You may disable all logs by using el::Level::Global + Enabled = 1, + /// @brief Whether or not to write corresponding log to log file + ToFile = 2, + /// @brief Whether or not to write corresponding level and logger log to standard output. + /// By standard output meaning termnal, command prompt etc + ToStandardOutput = 4, + /// @brief Determines format of logging corresponding level and logger. + Format = 8, + /// @brief Determines log file (full path) to write logs to for correponding level and logger + Filename = 16, + /// @brief Specifies milliseconds width. Width can be within range (1-6) + MillisecondsWidth = 32, + /// @brief Determines whether or not performance tracking is enabled. + /// + /// @detail This does not depend on logger or level. Performance tracking always uses 'performance' logger + PerformanceTracking = 64, + /// @brief Specifies log file max size. + /// + /// @detail If file size of corresponding log file (for corresponding level) is >= specified size, log file will + /// be truncated and re-initiated. + MaxLogFileSize = 128, + /// @brief Specifies number of log entries to hold until we flush pending log data + LogFlushThreshold = 256, + /// @brief Represents unknown configuration + Unknown = 1010 + }; + /// @brief Static class that contains helper functions for el::ConfigurationType + class ConfigurationTypeHelper : base::StaticClass { + public: + /// @brief Represents minimum valid configuration type. Useful when iterating through enum. + static const base::type::EnumType kMinValid = static_cast(ConfigurationType::Enabled); + /// @brief Represents maximum valid configuration type. This is used internally and you should not need it. + static const base::type::EnumType kMaxValid = static_cast(ConfigurationType::MaxLogFileSize); + /// @brief Casts configuration type to int, useful for iterating through enum. + static base::type::EnumType castToInt(ConfigurationType configurationType) { + return static_cast(configurationType); + } + /// @brief Casts int(ushort) to configurationt type, useful for iterating through enum. + static ConfigurationType castFromInt(base::type::EnumType c) { + return static_cast(c); + } + /// @brief Converts configuration type to associated const char* + /// @returns Upper case string based configuration type. + static const char* convertToString(ConfigurationType configurationType) { + // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. + if (configurationType == ConfigurationType::Enabled) return "ENABLED"; + if (configurationType == ConfigurationType::Filename) return "FILENAME"; + if (configurationType == ConfigurationType::Format) return "FORMAT"; + if (configurationType == ConfigurationType::ToFile) return "TO_FILE"; + if (configurationType == ConfigurationType::ToStandardOutput) return "TO_STANDARD_OUTPUT"; + if (configurationType == ConfigurationType::MillisecondsWidth) return "MILLISECONDS_WIDTH"; + if (configurationType == ConfigurationType::PerformanceTracking) return "PERFORMANCE_TRACKING"; + if (configurationType == ConfigurationType::MaxLogFileSize) return "MAX_LOG_FILE_SIZE"; + if (configurationType == ConfigurationType::LogFlushThreshold) return "LOG_FLUSH_THRESHOLD"; + return "UNKNOWN"; + } + /// @brief Converts from configStr to ConfigurationType + /// @param configStr Upper case string based configuration type. + /// Lower case is also valid but providing upper case is recommended. + static ConfigurationType convertFromString(const char* configStr) { + if ((strcmp(configStr, "ENABLED") == 0) || (strcmp(configStr, "enabled") == 0)) + return ConfigurationType::Enabled; + if ((strcmp(configStr, "TO_FILE") == 0) || (strcmp(configStr, "to_file") == 0)) + return ConfigurationType::ToFile; + if ((strcmp(configStr, "TO_STANDARD_OUTPUT") == 0) || (strcmp(configStr, "to_standard_output") == 0)) + return ConfigurationType::ToStandardOutput; + if ((strcmp(configStr, "FORMAT") == 0) || (strcmp(configStr, "format") == 0)) + return ConfigurationType::Format; + if ((strcmp(configStr, "FILENAME") == 0) || (strcmp(configStr, "filename") == 0)) + return ConfigurationType::Filename; + if ((strcmp(configStr, "MILLISECONDS_WIDTH") == 0) || (strcmp(configStr, "milliseconds_width") == 0)) + return ConfigurationType::MillisecondsWidth; + if ((strcmp(configStr, "PERFORMANCE_TRACKING") == 0) || (strcmp(configStr, "performance_tracking") == 0)) + return ConfigurationType::PerformanceTracking; + if ((strcmp(configStr, "MAX_LOG_FILE_SIZE") == 0) || (strcmp(configStr, "max_log_file_size") == 0)) + return ConfigurationType::MaxLogFileSize; + if ((strcmp(configStr, "LOG_FLUSH_THRESHOLD") == 0) || (strcmp(configStr, "log_flush_threshold") == 0)) + return ConfigurationType::LogFlushThreshold; + return ConfigurationType::Unknown; + } + /// @brief Applies specified function to each configuration type starting from startIndex + /// @param startIndex initial value to start the iteration from. This is passed by pointer and is left-shifted + /// so this can be used inside function (fn) to represent current configuration type. + /// @param fn function to apply with each configuration type. + /// This bool represent whether or not to stop iterating through configurations. + static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function& fn) { + base::type::EnumType cIndexMax = ConfigurationTypeHelper::kMaxValid; + do { + if (fn()) { + break; + } + *startIndex = static_cast(*startIndex << 1); + } while (*startIndex <= cIndexMax); + } + }; + /// @brief Flags used while writing logs. This flags are set by user + enum class LoggingFlag : base::type::EnumType { + /// @brief Makes sure we have new line for each container log entry + NewLineForContainer = 1, + /// @brief Makes sure if -vmodule is used and does not specifies a module, then verbose + /// logging is allowed via that module. + AllowVerboseIfModuleNotSpecified = 2, + /// @brief When handling crashes by default, detailed crash reason will be logged as well + LogDetailedCrashReason = 4, + /// @brief Allows to disable application abortion when logged using FATAL level + DisableApplicationAbortOnFatalLog = 8, + /// @brief Flushes log with every log-entry (performance sensative) - Disabled by default + ImmediateFlush = 16, + /// @brief Enables strict file rolling + StrictLogFileSizeCheck = 32, + /// @brief Make terminal output colorful for supported terminals + ColoredTerminalOutput = 64, + /// @brief Supports use of multiple logging in same macro, e.g, CLOG(INFO, "default", "network") + MultiLoggerSupport = 128, + /// @brief Disables comparing performance tracker's checkpoints + DisablePerformanceTrackingCheckpointComparison = 256, + /// @brief Disable VModules + DisableVModules = 512, + /// @brief Disable VModules extensions + DisableVModulesExtensions = 1024, + /// @brief Enables hierarchical logging + HierarchicalLogging = 2048, + /// @brief Creates logger automatically when not available + CreateLoggerAutomatically = 4096, + /// @brief Adds spaces b/w logs that separated by left-shift operator + AutoSpacing = 8192, + /// @brief Preserves time format and does not convert it to sec, hour etc (performance tracking only) + FixedTimeFormat = 16384 + }; + namespace base { + /// @brief Namespace containing constants used internally. + namespace consts { + // Level log values - These are values that are replaced in place of %level format specifier + static const base::type::char_t* kInfoLevelLogValue = ELPP_LITERAL("INFO "); + static const base::type::char_t* kDebugLevelLogValue = ELPP_LITERAL("DEBUG"); + static const base::type::char_t* kWarningLevelLogValue = ELPP_LITERAL("WARN "); + static const base::type::char_t* kErrorLevelLogValue = ELPP_LITERAL("ERROR"); + static const base::type::char_t* kFatalLevelLogValue = ELPP_LITERAL("FATAL"); + static const base::type::char_t* kVerboseLevelLogValue = ELPP_LITERAL("VER"); + static const base::type::char_t* kTraceLevelLogValue = ELPP_LITERAL("TRACE"); + static const base::type::char_t* kInfoLevelShortLogValue = ELPP_LITERAL("I"); + static const base::type::char_t* kDebugLevelShortLogValue = ELPP_LITERAL("D"); + static const base::type::char_t* kWarningLevelShortLogValue = ELPP_LITERAL("W"); + static const base::type::char_t* kErrorLevelShortLogValue = ELPP_LITERAL("E"); + static const base::type::char_t* kFatalLevelShortLogValue = ELPP_LITERAL("F"); + static const base::type::char_t* kVerboseLevelShortLogValue = ELPP_LITERAL("V"); + static const base::type::char_t* kTraceLevelShortLogValue = ELPP_LITERAL("T"); + // Format specifiers - These are used to define log format + static const base::type::char_t* kAppNameFormatSpecifier = ELPP_LITERAL("%app"); + static const base::type::char_t* kLoggerIdFormatSpecifier = ELPP_LITERAL("%logger"); + static const base::type::char_t* kThreadIdFormatSpecifier = ELPP_LITERAL("%thread"); + static const base::type::char_t* kSeverityLevelFormatSpecifier = ELPP_LITERAL("%level"); + static const base::type::char_t* kSeverityLevelShortFormatSpecifier = ELPP_LITERAL("%levshort"); + static const base::type::char_t* kDateTimeFormatSpecifier = ELPP_LITERAL("%datetime"); + static const base::type::char_t* kLogFileFormatSpecifier = ELPP_LITERAL("%file"); + static const base::type::char_t* kLogFileBaseFormatSpecifier = ELPP_LITERAL("%fbase"); + static const base::type::char_t* kLogLineFormatSpecifier = ELPP_LITERAL("%line"); + static const base::type::char_t* kLogLocationFormatSpecifier = ELPP_LITERAL("%loc"); + static const base::type::char_t* kLogFunctionFormatSpecifier = ELPP_LITERAL("%func"); + static const base::type::char_t* kCurrentUserFormatSpecifier = ELPP_LITERAL("%user"); + static const base::type::char_t* kCurrentHostFormatSpecifier = ELPP_LITERAL("%host"); + static const base::type::char_t* kMessageFormatSpecifier = ELPP_LITERAL("%msg"); + static const base::type::char_t* kVerboseLevelFormatSpecifier = ELPP_LITERAL("%vlevel"); + static const char* kDateTimeFormatSpecifierForFilename = "%datetime"; + // Date/time + static const char* kDays[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; + static const char* kDaysAbbrev[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + static const char* kMonths[12] = { "January", "February", "March", "Apri", "May", "June", "July", "August", + "September", "October", "November", "December" }; + static const char* kMonthsAbbrev[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + static const char* kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g"; + static const char* kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m"; + static const int kYearBase = 1900; + static const char* kAm = "AM"; + static const char* kPm = "PM"; + // Miscellaneous constants + static const char* kDefaultLoggerId = "default"; + static const char* kPerformanceLoggerId = "performance"; + static const char* kSysLogLoggerId = "syslog"; + static const char* kNullPointer = "nullptr"; + static const char kFormatSpecifierChar = '%'; +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED + static const char kFormatSpecifierCharValue = 'v'; +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED + static const unsigned int kMaxLogPerContainer = 100; + static const unsigned int kMaxLogPerCounter = 100000; + static const unsigned int kDefaultMillisecondsWidth = 3; + static const base::type::VerboseLevel kMaxVerboseLevel = 9; + static const char* kUnknownUser = "user"; + static const char* kUnknownHost = "unknown-host"; +#if defined(ELPP_DEFAULT_LOG_FILE) + static const char* kDefaultLogFile = ELPP_DEFAULT_LOG_FILE; +#else +# if ELPP_OS_UNIX +# if ELPP_OS_ANDROID + static const char* kDefaultLogFile = "logs/ace.log"; +# else + static const char* kDefaultLogFile = "logs/ace.log"; +# endif // ELPP_OS_ANDROID +# elif ELPP_OS_WINDOWS + static const char* kDefaultLogFile = "logs\\ace.log"; +# endif // ELPP_OS_UNIX +#endif // defined(ELPP_DEFAULT_LOG_FILE) +#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) + static const char* kDefaultLogFileParam = "--default-log-file"; +#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) +#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) + static const char* kLoggingFlagsParam = "--logging-flags"; +#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) +#if ELPP_OS_WINDOWS + static const char* kFilePathSeperator = "\\"; +#else + static const char* kFilePathSeperator = "/"; +#endif // ELPP_OS_WINDOWS + static const char* kValidLoggerIdSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"; + static const char* kConfigurationComment = "##"; + static const char* kConfigurationLevel = "*"; + static const char* kConfigurationLoggerId = "--"; + static const std::size_t kSourceFilenameMaxLength = 100; + static const std::size_t kSourceLineMaxLength = 10; + static const Level kPerformanceTrackerDefaultLevel = Level::Info; + const struct { + double value; + const base::type::char_t* unit; + } kTimeFormats[] = { + { 1000.0f, ELPP_LITERAL("mis") }, + { 1000.0f, ELPP_LITERAL("ms") }, + { 60.0f, ELPP_LITERAL("seconds") }, + { 60.0f, ELPP_LITERAL("minutes") }, + { 24.0f, ELPP_LITERAL("hours") }, + { 7.0f, ELPP_LITERAL("days") } + }; + static const int kTimeFormatsCount = sizeof(kTimeFormats) / sizeof(kTimeFormats[0]); + const struct { + int numb; + const char* name; + const char* brief; + const char* detail; + } kCrashSignals[] = { + // NOTE: Do not re-order, if you do please check CrashHandler(bool) constructor and CrashHandler::setHandler(..) + { SIGABRT, "SIGABRT", "Abnormal termination", + "Program was abnormally terminated." }, + { SIGFPE, "SIGFPE", "Erroneous arithmetic operation", + "Arithemetic operation issue such as division by zero or operation resulting in overflow." }, + { SIGILL, "SIGILL", "Illegal instruction", + "Generally due to a corruption in the code or to an attempt to execute data." }, + { SIGSEGV, "SIGSEGV", "Invalid access to memory", + "Program is trying to read an invalid (unallocated, deleted or corrupted) or inaccessible memory." }, + { SIGINT, "SIGINT", "Interactive attention signal", + "Interruption generated (generally) by user or operating system." }, + }; + static const int kCrashSignalsCount = sizeof(kCrashSignals) / sizeof(kCrashSignals[0]); + } // namespace consts + } // namespace base + typedef std::function PreRollOutCallback; + namespace base { + static inline void defaultPreRollOutCallback(const char*, std::size_t) {} + /// @brief Enum to represent timestamp unit + enum class TimestampUnit : base::type::EnumType { + Microsecond = 0, Millisecond = 1, Second = 2, Minute = 3, Hour = 4, Day = 5 + }; + /// @brief Format flags used to determine specifiers that are active for performance improvements. + enum class FormatFlags : base::type::EnumType { + DateTime = 1 << 1, LoggerId = 1 << 2, File = 1 << 3, Line = 1 << 4, Location = 1 << 5, Function = 1 << 6, + User = 1 << 7, Host = 1 << 8, LogMessage = 1 << 9, VerboseLevel = 1 << 10, AppName = 1 << 11, ThreadId = 1 << 12, + Level = 1 << 13, FileBase = 1 << 14, LevelShort = 1 << 15 + }; + /// @brief A milliseconds width class containing actual width and offset for date/time + class MillisecondsWidth { + public: + MillisecondsWidth(void) { init(base::consts::kDefaultMillisecondsWidth); } + explicit MillisecondsWidth(int width) { init(width); } + bool operator==(const MillisecondsWidth& msWidth) { return m_width == msWidth.m_width && m_offset == msWidth.m_offset; } + int m_width; unsigned int m_offset; + private: + void init(int width) { + if (width < 1 || width > 6) { + width = base::consts::kDefaultMillisecondsWidth; + } + m_width = width; + switch (m_width) { + case 3: m_offset = 1000; break; + case 4: m_offset = 100; break; + case 5: m_offset = 10; break; + case 6: m_offset = 1; break; + default: m_offset = 1000; break; + } + } + }; + /// @brief Namespace containing utility functions/static classes used internally + namespace utils { + /// @brief Deletes memory safely and points to null + template + static inline + typename std::enable_if::value, void>::type + safeDelete(T*& pointer) { + if (pointer == nullptr) + return; + delete pointer; + pointer = nullptr; + } + /// @brief Gets value of const char* but if it is nullptr, a string nullptr is returned + static inline const char* charPtrVal(const char* pointer) { + return pointer == nullptr ? base::consts::kNullPointer : pointer; + } + /// @brief Aborts application due with user-defined status + static inline void abort(int status, const std::string& reason = std::string()) { + // Both status and reason params are there for debugging with tools like gdb etc + ELPP_UNUSED(status); + ELPP_UNUSED(reason); +#if defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) + // Ignore msvc critical error dialog - break instead (on debug mode) + _asm int 3 +#else + ::abort(); +#endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) + } + /// @brief Bitwise operations for C++11 strong enum class. This casts e into Flag_T and returns value after bitwise operation + /// Use these function as
flag = bitwise::Or(MyEnum::val1, flag);
+ namespace bitwise { + template + static inline base::type::EnumType And(Enum e, base::type::EnumType flag) { + return static_cast(flag) & static_cast(e); + } + template + static inline base::type::EnumType Not(Enum e, base::type::EnumType flag) { + return static_cast(flag) & ~(static_cast(e)); + } + template + static inline base::type::EnumType Or(Enum e, base::type::EnumType flag) { + return static_cast(flag) | static_cast(e); + } + } // namespace bitwise + template + static inline void addFlag(Enum e, base::type::EnumType* flag) { + *flag = base::utils::bitwise::Or(e, *flag); + } + template + static inline void removeFlag(Enum e, base::type::EnumType* flag) { + *flag = base::utils::bitwise::Not(e, *flag); + } + template + static inline bool hasFlag(Enum e, base::type::EnumType flag) { + return base::utils::bitwise::And(e, flag) > 0x0; + } + } // namespace utils + namespace threading { +#if ELPP_THREADING_ENABLED +# if !ELPP_USE_STD_THREADING + namespace internal { + /// @brief A mutex wrapper for compiler that dont yet support std::mutex + class Mutex : base::NoCopy { + public: + Mutex(void) { +# if ELPP_OS_UNIX + pthread_mutex_init(&m_underlyingMutex, nullptr); +# elif ELPP_OS_WINDOWS + InitializeCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + virtual ~Mutex(void) { +# if ELPP_OS_UNIX + pthread_mutex_destroy(&m_underlyingMutex); +# elif ELPP_OS_WINDOWS + DeleteCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + inline void lock(void) { +# if ELPP_OS_UNIX + pthread_mutex_lock(&m_underlyingMutex); +# elif ELPP_OS_WINDOWS + EnterCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + inline bool try_lock(void) { +# if ELPP_OS_UNIX + return (pthread_mutex_trylock(&m_underlyingMutex) == 0); +# elif ELPP_OS_WINDOWS + return TryEnterCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + inline void unlock(void) { +# if ELPP_OS_UNIX + pthread_mutex_unlock(&m_underlyingMutex); +# elif ELPP_OS_WINDOWS + LeaveCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + private: +# if ELPP_OS_UNIX + pthread_mutex_t m_underlyingMutex; +# elif ELPP_OS_WINDOWS + CRITICAL_SECTION m_underlyingMutex; +# endif // ELPP_OS_UNIX + }; + /// @brief Scoped lock for compiler that dont yet support std::lock_guard + template + class ScopedLock : base::NoCopy { + public: + explicit ScopedLock(M& mutex) { + m_mutex = &mutex; + m_mutex->lock(); + } + + virtual ~ScopedLock(void) { + m_mutex->unlock(); + } + private: + M* m_mutex; + ScopedLock(void); + }; + } // namespace internal + /// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned. + static inline std::string getCurrentThreadId(void) { + std::stringstream ss; +# if (ELPP_OS_WINDOWS) + ss << GetCurrentThreadId(); +# endif // (ELPP_OS_WINDOWS) + return ss.str(); + } + static inline void msleep(int) { + // No implementation for non std::thread version + } + typedef base::threading::internal::Mutex Mutex; + typedef base::threading::internal::ScopedLock ScopedLock; +# else + /// @brief Gets ID of currently running threading using std::this_thread::get_id() + static inline std::string getCurrentThreadId(void) { + std::stringstream ss; + ss << std::this_thread::get_id(); + return ss.str(); + } + static inline void msleep(int ms) { + // Only when async logging enabled - this is because async is strict on compiler +#if ELPP_ASYNC_LOGGING + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +#endif // ELPP_ASYNC_LOGGING + } + typedef std::mutex Mutex; + typedef std::lock_guard ScopedLock; +# endif // !ELPP_USE_STD_THREADING +#else + namespace internal { + /// @brief Mutex wrapper used when multi-threading is disabled. + class NoMutex : base::NoCopy { + public: + NoMutex(void) {} + inline void lock(void) {} + inline bool try_lock(void) { return true; } + inline void unlock(void) {} + }; + /// @brief Lock guard wrapper used when multi-threading is disabled. + template + class NoScopedLock : base::NoCopy { + public: + explicit NoScopedLock(Mutex&) { + } + virtual ~NoScopedLock(void) { + } + private: + NoScopedLock(void); + }; + } // namespace internal + static inline std::string getCurrentThreadId(void) { + return std::string(); + } + static inline void msleep(int) { + // No custom implementation + } + typedef base::threading::internal::NoMutex Mutex; + typedef base::threading::internal::NoScopedLock ScopedLock; +#endif // ELPP_THREADING_ENABLED + /// @brief Base of thread safe class, this class is inheritable-only + class ThreadSafe { + public: + virtual inline void acquireLock(void) ELPP_FINAL { m_mutex.lock(); } + virtual inline void releaseLock(void) ELPP_FINAL { m_mutex.unlock(); } + virtual inline base::threading::Mutex& lock(void) ELPP_FINAL { return m_mutex; } + protected: + ThreadSafe(void) {} + virtual ~ThreadSafe(void) {} + private: + base::threading::Mutex m_mutex; + }; + } // namespace threading + namespace utils { + class File : base::StaticClass { + public: + /// @brief Creates new out file stream for specified filename. + /// @return Pointer to newly created fstream or nullptr + static base::type::fstream_t* newFileStream(const std::string& filename) { + base::type::fstream_t *fs = new base::type::fstream_t(filename.c_str(), + base::type::fstream_t::out | base::type::fstream_t::app); +#if defined(ELPP_UNICODE) + std::locale elppUnicodeLocale(""); +#if ELPP_OS_WINDOWS + std::locale elppUnicodeLocaleWindows(elppUnicodeLocale, new std::codecvt_utf8_utf16); + elppUnicodeLocale = elppUnicodeLocaleWindows; +#endif + fs->imbue(elppUnicodeLocale); +#endif // defined(ELPP_UNICODE) + if (fs->is_open()) { + fs->flush(); + } + else { + base::utils::safeDelete(fs); + ELPP_INTERNAL_ERROR("Bad file [" << filename << "]", true); + } + return fs; + } + + /// @brief Gets size of file provided in stream + static std::size_t getSizeOfFile(base::type::fstream_t* fs) { + if (fs == nullptr) { + return 0; + } + std::streampos currPos = fs->tellg(); + fs->seekg(0, fs->end); + std::size_t size = static_cast(fs->tellg()); + fs->seekg(currPos); + return size; + } + + /// @brief Determines whether or not provided path exist in current file system + static inline bool pathExists(const char* path, bool considerFile = false) { + if (path == nullptr) { + return false; + } +#if ELPP_OS_UNIX + ELPP_UNUSED(considerFile); + struct stat st; + return (stat(path, &st) == 0); +#elif ELPP_OS_WINDOWS + DWORD fileType = GetFileAttributesA(path); + if (fileType == INVALID_FILE_ATTRIBUTES) { + return false; + } + return considerFile ? true : ((fileType & FILE_ATTRIBUTE_DIRECTORY) == 0 ? false : true); +#endif // ELPP_OS_UNIX + } + + /// @brief Creates specified path on file system + /// @param path Path to create. + static bool createPath(const std::string& path) { + if (path.empty()) { + return false; + } + if (base::utils::File::pathExists(path.c_str())) { + return true; + } + int status = -1; + + char* currPath = const_cast(path.c_str()); + std::string builtPath = std::string(); +#if ELPP_OS_UNIX + if (path[0] == '/') { + builtPath = "/"; + } + currPath = STRTOK(currPath, base::consts::kFilePathSeperator, 0); +#elif ELPP_OS_WINDOWS + // Use secure functions API + char* nextTok_ = nullptr; + currPath = STRTOK(currPath, base::consts::kFilePathSeperator, &nextTok_); + ELPP_UNUSED(nextTok_); +#endif // ELPP_OS_UNIX + while (currPath != nullptr) { + builtPath.append(currPath); + builtPath.append(base::consts::kFilePathSeperator); +#if ELPP_OS_UNIX + status = mkdir(builtPath.c_str(), ELPP_LOG_PERMS); + currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, 0); +#elif ELPP_OS_WINDOWS + status = _mkdir(builtPath.c_str()); + currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, &nextTok_); +#endif // ELPP_OS_UNIX + } + if (status == -1) { + ELPP_INTERNAL_ERROR("Error while creating path [" << path << "]", true); + return false; + } + return true; + } + /// @brief Extracts path of filename with leading slash + static std::string extractPathFromFilename(const std::string& fullPath, + const char* seperator = base::consts::kFilePathSeperator) { + if ((fullPath == "") || (fullPath.find(seperator) == std::string::npos)) { + return fullPath; + } + std::size_t lastSlashAt = fullPath.find_last_of(seperator); + if (lastSlashAt == 0) { + return std::string(seperator); + } + return fullPath.substr(0, lastSlashAt + 1); + } + /// @brief builds stripped filename and puts it in buff + static void buildStrippedFilename(const char* filename, char buff[], + std::size_t limit = base::consts::kSourceFilenameMaxLength) { + std::size_t sizeOfFilename = strlen(filename); + if (sizeOfFilename >= limit) { + filename += (sizeOfFilename - limit); + if (filename[0] != '.' && filename[1] != '.') { // prepend if not already + filename += 3; // 3 = '..' + STRCAT(buff, "..", limit); + } + } + STRCAT(buff, filename, limit); + } + /// @brief builds base filename and puts it in buff + static void buildBaseFilename(const std::string& fullPath, char buff[], + std::size_t limit = base::consts::kSourceFilenameMaxLength, + const char* seperator = base::consts::kFilePathSeperator) { + const char *filename = fullPath.c_str(); + std::size_t lastSlashAt = fullPath.find_last_of(seperator); + filename += lastSlashAt ? lastSlashAt + 1 : 0; + std::size_t sizeOfFilename = strlen(filename); + if (sizeOfFilename >= limit) { + filename += (sizeOfFilename - limit); + if (filename[0] != '.' && filename[1] != '.') { // prepend if not already + filename += 3; // 3 = '..' + STRCAT(buff, "..", limit); + } + } + STRCAT(buff, filename, limit); + } + }; + /// @brief String utilities helper class used internally. You should not use it. + class Str : base::StaticClass { + public: + /// @brief Checks if character is digit. Dont use libc implementation of it to prevent locale issues. + static inline bool isDigit(char c) { + return c >= '0' && c <= '9'; + } + + /// @brief Matches wildcards, '*' and '?' only supported. + static bool wildCardMatch(const char* str, const char* pattern) { + while (*pattern) { + switch (*pattern) { + case '?': + if (!*str) + return false; + ++str; + ++pattern; + break; + case '*': + if (wildCardMatch(str, pattern + 1)) + return true; + if (*str && wildCardMatch(str + 1, pattern)) + return true; + return false; + break; + default: + if (*str++ != *pattern++) + return false; + break; + } + } + return !*str && !*pattern; + } + + /// @brief Trims string from start + /// @param [in,out] str String to trim + static inline std::string& ltrim(std::string& str) { + str.erase(str.begin(), std::find_if(str.begin(), str.end(), std::not1(std::ptr_fun(&std::isspace)))); + return str; + } + + /// @brief Trim string from end + /// @param [in,out] str String to trim + static inline std::string& rtrim(std::string& str) { + str.erase(std::find_if(str.rbegin(), str.rend(), std::not1(std::ptr_fun(&std::isspace))).base(), str.end()); + return str; + } + + /// @brief Trims string from left and right + /// @param [in,out] str String to trim + static inline std::string& trim(std::string& str) { + return ltrim(rtrim(str)); + } + + /// @brief Determines whether or not str starts with specified string + /// @param str String to check + /// @param start String to check against + /// @return Returns true if starts with specified string, false otherwise + static inline bool startsWith(const std::string& str, const std::string& start) { + return (str.length() >= start.length()) && (str.compare(0, start.length(), start) == 0); + } + + /// @brief Determines whether or not str ends with specified string + /// @param str String to check + /// @param end String to check against + /// @return Returns true if ends with specified string, false otherwise + static inline bool endsWith(const std::string& str, const std::string& end) { + return (str.length() >= end.length()) && (str.compare(str.length() - end.length(), end.length(), end) == 0); + } + + /// @brief Replaces all instances of replaceWhat with 'replaceWith'. Original variable is changed for performance. + /// @param [in,out] str String to replace from + /// @param replaceWhat Character to replace + /// @param replaceWith Character to replace with + /// @return Modified version of str + static inline std::string& replaceAll(std::string& str, char replaceWhat, char replaceWith) { + std::replace(str.begin(), str.end(), replaceWhat, replaceWith); + return str; + } + + /// @brief Replaces all instances of 'replaceWhat' with 'replaceWith'. (String version) Replaces in place + /// @param str String to replace from + /// @param replaceWhat Character to replace + /// @param replaceWith Character to replace with + /// @return Modified (original) str + static inline std::string& replaceAll(std::string& str, const std::string& replaceWhat, // NOLINT + const std::string& replaceWith) { + if (replaceWhat == replaceWith) + return str; + std::size_t foundAt = std::string::npos; + while ((foundAt = str.find(replaceWhat, foundAt + 1)) != std::string::npos) { + str.replace(foundAt, replaceWhat.length(), replaceWith); + } + return str; + } + + static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, // NOLINT + const base::type::string_t& replaceWith) { + std::size_t foundAt = base::type::string_t::npos; + while ((foundAt = str.find(replaceWhat, foundAt + 1)) != base::type::string_t::npos) { + if (foundAt > 0 && str[foundAt - 1] == base::consts::kFormatSpecifierChar) { + str.erase(foundAt > 0 ? foundAt - 1 : 0, 1); + ++foundAt; + } + else { + str.replace(foundAt, replaceWhat.length(), replaceWith); + return; + } + } + } +#if defined(ELPP_UNICODE) + static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, // NOLINT + const std::string& replaceWith) { + replaceFirstWithEscape(str, replaceWhat, base::type::string_t(replaceWith.begin(), replaceWith.end())); + } +#endif // defined(ELPP_UNICODE) + /// @brief Converts string to uppercase + /// @param str String to convert + /// @return Uppercase string + static inline std::string& toUpper(std::string& str) { + std::transform(str.begin(), str.end(), str.begin(), ::toupper); + return str; + } + + /// @brief Compares cstring equality - uses strcmp + static inline bool cStringEq(const char* s1, const char* s2) { + if (s1 == nullptr && s2 == nullptr) return true; + if (s1 == nullptr || s2 == nullptr) return false; + return strcmp(s1, s2) == 0; + } + + /// @brief Compares cstring equality (case-insensitive) - uses toupper(char) + /// Dont use strcasecmp because of CRT (VC++) + static bool cStringCaseEq(const char* s1, const char* s2) { + if (s1 == nullptr && s2 == nullptr) return true; + if (s1 == nullptr || s2 == nullptr) return false; + if (strlen(s1) != strlen(s2)) return false; + while (*s1 != '\0' && *s2 != '\0') { + if (::toupper(*s1) != ::toupper(*s2)) return false; + ++s1; + ++s2; + } + return true; + } + + /// @brief Returns true if c exist in str + static inline bool contains(const char* str, char c) { + for (; *str; ++str) { + if (*str == c) + return true; + } + return false; + } + + static inline char* convertAndAddToBuff(std::size_t n, int len, char* buf, const char* bufLim, bool zeroPadded = true) { + char localBuff[10] = ""; + char* p = localBuff + sizeof(localBuff) - 2; + if (n > 0) { + for (; n > 0 && p > localBuff && len > 0; n /= 10, --len) + *--p = static_cast(n % 10 + '0'); + } + else { + *--p = '0'; + --len; + } + if (zeroPadded) + while (p > localBuff && len-- > 0) *--p = static_cast('0'); + return addToBuff(p, buf, bufLim); + } + + static inline char* addToBuff(const char* str, char* buf, const char* bufLim) { + while ((buf < bufLim) && ((*buf = *str++) != '\0')) + ++buf; + return buf; + } + + static inline char* clearBuff(char buff[], std::size_t lim) { + STRCPY(buff, "", lim); + ELPP_UNUSED(lim); // For *nix we dont have anything using lim in above STRCPY macro + return buff; + } + + /// @brief Converst wchar* to char* + /// NOTE: Need to free return value after use! + static char* wcharPtrToCharPtr(const wchar_t* line) { + std::size_t len_ = wcslen(line) + 1; + char* buff_ = static_cast(malloc(len_ + 1)); +# if ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) + std::wcstombs(buff_, line, len_); +# elif ELPP_OS_WINDOWS + std::size_t convCount_ = 0; + mbstate_t mbState_; + ::memset(static_cast(&mbState_), 0, sizeof(mbState_)); + wcsrtombs_s(&convCount_, buff_, len_, &line, len_, &mbState_); +# endif // ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) + return buff_; + } + }; + /// @brief Operating System helper static class used internally. You should not use it. + class OS : base::StaticClass { + public: +#if ELPP_OS_WINDOWS + /// @brief Gets environment variables for Windows based OS. + /// We are not using getenv(const char*) because of CRT deprecation + /// @param varname Variable name to get environment variable value for + /// @return If variable exist the value of it otherwise nullptr + static const char* getWindowsEnvironmentVariable(const char* varname) { + const DWORD bufferLen = 50; + static char buffer[bufferLen]; + if (GetEnvironmentVariableA(varname, buffer, bufferLen)) { + return buffer; + } + return nullptr; + } +#endif // ELPP_OS_WINDOWS +#if ELPP_OS_ANDROID + /// @brief Reads android property value + static inline std::string getProperty(const char* prop) { + char propVal[PROP_VALUE_MAX + 1]; + int ret = __system_property_get(prop, propVal); + return ret == 0 ? std::string() : std::string(propVal); + } + + /// @brief Reads android device name + static std::string getDeviceName(void) { + std::stringstream ss; + std::string manufacturer = getProperty("ro.product.manufacturer"); + std::string model = getProperty("ro.product.model"); + if (manufacturer.empty() || model.empty()) { + return std::string(); + } + ss << manufacturer << "-" << model; + return ss.str(); + } +#endif // ELPP_OS_ANDROID + + /// @brief Runs command on terminal and returns the output. + /// + /// @detail This is applicable only on unix based systems, for all other OS, an empty string is returned. + /// @param command Bash command + /// @return Result of bash output or empty string if no result found. + static const std::string getBashOutput(const char* command) { +#if (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) + if (command == nullptr) { + return std::string(); + } + FILE* proc = nullptr; + if ((proc = popen(command, "r")) == nullptr) { + ELPP_INTERNAL_ERROR("\nUnable to run command [" << command << "]", true); + return std::string(); + } + char hBuff[4096]; + if (fgets(hBuff, sizeof(hBuff), proc) != nullptr) { + pclose(proc); + if (hBuff[strlen(hBuff) - 1] == '\n') { + hBuff[strlen(hBuff) - 1] = '\0'; + } + return std::string(hBuff); + } + return std::string(); +#else + ELPP_UNUSED(command); + return std::string(); +#endif // (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) + } + + /// @brief Gets environment variable. This is cross-platform and CRT safe (for VC++) + /// @param variableName Environment variable name + /// @param defaultVal If no environment variable or value found the value to return by default + /// @param alternativeBashCommand If environment variable not found what would be alternative bash command + /// in order to look for value user is looking for. E.g, for 'user' alternative command will 'whoami' + static std::string getEnvironmentVariable(const char* variableName, const char* defaultVal, const char* alternativeBashCommand = nullptr) { +#if ELPP_OS_UNIX + const char* val = getenv(variableName); +#elif ELPP_OS_WINDOWS + const char* val = getWindowsEnvironmentVariable(variableName); +#endif // ELPP_OS_UNIX + if ((val == nullptr) || ((strcmp(val, "") == 0))) { +#if ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) + // Try harder on unix-based systems + std::string valBash = base::utils::OS::getBashOutput(alternativeBashCommand); + if (valBash.empty()) { + return std::string(defaultVal); + } + else { + return valBash; + } +#elif ELPP_OS_WINDOWS || ELPP_OS_UNIX + ELPP_UNUSED(alternativeBashCommand); + return std::string(defaultVal); +#endif // ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) + } + return std::string(val); + } + /// @brief Gets current username. + static inline std::string currentUser(void) { +#if ELPP_OS_UNIX && !ELPP_OS_ANDROID + return getEnvironmentVariable("USER", base::consts::kUnknownUser, "whoami"); +#elif ELPP_OS_WINDOWS + return getEnvironmentVariable("USERNAME", base::consts::kUnknownUser); +#elif ELPP_OS_ANDROID + ELPP_UNUSED(base::consts::kUnknownUser); + return std::string("android"); +#else + return std::string(); +#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID + } + + /// @brief Gets current host name or computer name. + /// + /// @detail For android systems this is device name with its manufacturer and model seperated by hyphen + static inline std::string currentHost(void) { +#if ELPP_OS_UNIX && !ELPP_OS_ANDROID + return getEnvironmentVariable("HOSTNAME", base::consts::kUnknownHost, "hostname"); +#elif ELPP_OS_WINDOWS + return getEnvironmentVariable("COMPUTERNAME", base::consts::kUnknownHost); +#elif ELPP_OS_ANDROID + ELPP_UNUSED(base::consts::kUnknownHost); + return getDeviceName(); +#else + return std::string(); +#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID + } + /// @brief Whether or not terminal supports colors + static inline bool termSupportsColor(void) { + std::string term = getEnvironmentVariable("TERM", ""); + return term == "xterm" || term == "xterm-color" || term == "xterm-256color" || + term == "screen" || term == "linux" || term == "cygwin"; + } + }; + extern std::string s_currentUser; + extern std::string s_currentHost; + extern bool s_termSupportsColor; +#define ELPP_INITI_BASIC_DECLR \ + namespace el {\ + namespace base {\ + namespace utils {\ + std::string s_currentUser = el::base::utils::OS::currentUser(); \ + std::string s_currentHost = el::base::utils::OS::currentHost(); \ + bool s_termSupportsColor = el::base::utils::OS::termSupportsColor(); \ + }\ + }\ + } + /// @brief Contains utilities for cross-platform date/time. This class make use of el::base::utils::Str + class DateTime : base::StaticClass { + public: + /// @brief Cross platform gettimeofday for Windows and unix platform. This can be used to determine current millisecond. + /// + /// @detail For unix system it uses gettimeofday(timeval*, timezone*) and for Windows, a seperate implementation is provided + /// @param [in,out] tv Pointer that gets updated + static void gettimeofday(struct timeval* tv) { +#if ELPP_OS_WINDOWS + if (tv != nullptr) { +# if ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) + const unsigned __int64 delta_ = 11644473600000000Ui64; +# else + const unsigned __int64 delta_ = 11644473600000000ULL; +# endif // ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) + const double secOffSet = 0.000001; + const unsigned long usecOffSet = 1000000; + FILETIME fileTime; + GetSystemTimeAsFileTime(&fileTime); + unsigned __int64 present = 0; + present |= fileTime.dwHighDateTime; + present = present << 32; + present |= fileTime.dwLowDateTime; + present /= 10; // mic-sec + // Subtract the difference + present -= delta_; + tv->tv_sec = static_cast(present * secOffSet); + tv->tv_usec = static_cast(present % usecOffSet); + } +#else + ::gettimeofday(tv, nullptr); +#endif // ELPP_OS_WINDOWS + } + + /// @brief Gets current date and time with milliseconds. + /// @param format User provided date/time format + /// @param msWidth A pointer to base::MillisecondsWidth from configuration (non-null) + /// @returns string based date time in specified format. + static inline std::string getDateTime(const char* format, const base::MillisecondsWidth* msWidth) { + struct timeval currTime; + gettimeofday(&currTime); + struct ::tm timeInfo; + buildTimeInfo(&currTime, &timeInfo); + const int kBuffSize = 30; + char buff_[kBuffSize] = ""; + parseFormat(buff_, kBuffSize, format, &timeInfo, static_cast(currTime.tv_usec / msWidth->m_offset), msWidth); + return std::string(buff_); + } + + /// @brief Formats time to get unit accordingly, units like second if > 1000 or minutes if > 60000 etc + static base::type::string_t formatTime(unsigned long long time, base::TimestampUnit timestampUnit) { + double result = static_cast(time); + base::type::EnumType start = static_cast(timestampUnit); + const base::type::char_t* unit = base::consts::kTimeFormats[start].unit; + for (base::type::EnumType i = start; i < base::consts::kTimeFormatsCount - 1; ++i) { + if (result <= base::consts::kTimeFormats[i].value) { + break; + } + result /= base::consts::kTimeFormats[i].value; + unit = base::consts::kTimeFormats[i + 1].unit; + } + base::type::stringstream_t ss; + ss << result << " " << unit; + return ss.str(); + } + + /// @brief Gets time difference in milli/micro second depending on timestampUnit + static inline unsigned long long getTimeDifference(const struct timeval& endTime, const struct timeval& startTime, base::TimestampUnit timestampUnit) { + if (timestampUnit == base::TimestampUnit::Microsecond) { + return static_cast(static_cast(1000000 * endTime.tv_sec + endTime.tv_usec) - + static_cast(1000000 * startTime.tv_sec + startTime.tv_usec)); + } + else { + return static_cast((((endTime.tv_sec - startTime.tv_sec) * 1000000) + (endTime.tv_usec - startTime.tv_usec)) / 1000); + } + } + + private: + static inline struct ::tm* buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo) { +#if ELPP_OS_UNIX + time_t rawTime = currTime->tv_sec; + ::localtime_r(&rawTime, timeInfo); + return timeInfo; +#else +# if ELPP_COMPILER_MSVC + ELPP_UNUSED(currTime); + time_t t; + _time64(&t); + localtime_s(timeInfo, &t); + return timeInfo; +# else + // For any other compilers that don't have CRT warnings issue e.g, MinGW or TDM GCC- we use different method + time_t rawTime = currTime->tv_sec; + struct tm* tmInf = localtime(&rawTime); + *timeInfo = *tmInf; + return timeInfo; +# endif // ELPP_COMPILER_MSVC +#endif // ELPP_OS_UNIX + } + static char* parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo, + std::size_t msec, const base::MillisecondsWidth* msWidth) { + const char* bufLim = buf + bufSz; + for (; *format; ++format) { + if (*format == base::consts::kFormatSpecifierChar) { + switch (*++format) { + case base::consts::kFormatSpecifierChar: // Escape + break; + case '\0': // End + --format; + break; + case 'd': // Day + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mday, 2, buf, bufLim); + continue; + case 'a': // Day of week (short) + buf = base::utils::Str::addToBuff(base::consts::kDaysAbbrev[tInfo->tm_wday], buf, bufLim); + continue; + case 'A': // Day of week (long) + buf = base::utils::Str::addToBuff(base::consts::kDays[tInfo->tm_wday], buf, bufLim); + continue; + case 'M': // month + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mon + 1, 2, buf, bufLim); + continue; + case 'b': // month (short) + buf = base::utils::Str::addToBuff(base::consts::kMonthsAbbrev[tInfo->tm_mon], buf, bufLim); + continue; + case 'B': // month (long) + buf = base::utils::Str::addToBuff(base::consts::kMonths[tInfo->tm_mon], buf, bufLim); + continue; + case 'y': // year (two digits) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 2, buf, bufLim); + continue; + case 'Y': // year (four digits) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 4, buf, bufLim); + continue; + case 'h': // hour (12-hour) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour % 12, 2, buf, bufLim); + continue; + case 'H': // hour (24-hour) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour, 2, buf, bufLim); + continue; + case 'm': // minute + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_min, 2, buf, bufLim); + continue; + case 's': // second + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_sec, 2, buf, bufLim); + continue; + case 'z': // milliseconds + case 'g': + buf = base::utils::Str::convertAndAddToBuff(msec, msWidth->m_width, buf, bufLim); + continue; + case 'F': // AM/PM + buf = base::utils::Str::addToBuff((tInfo->tm_hour >= 12) ? base::consts::kPm : base::consts::kAm, buf, bufLim); + continue; + default: + continue; + } + } + if (buf == bufLim) break; + *buf++ = *format; + } + return buf; + } + }; + /// @brief Command line arguments for application if specified using el::Helpers::setArgs(..) or START_EASYLOGGINGPP(..) + class CommandLineArgs { + public: + CommandLineArgs(void) { + setArgs(0, static_cast(nullptr)); + } + CommandLineArgs(int argc, const char** argv) { + setArgs(argc, argv); + } + CommandLineArgs(int argc, char** argv) { + setArgs(argc, argv); + } + virtual ~CommandLineArgs(void) {} + /// @brief Sets arguments and parses them + inline void setArgs(int argc, const char** argv) { + setArgs(argc, const_cast(argv)); + } + /// @brief Sets arguments and parses them + inline void setArgs(int argc, char** argv) { + m_params.clear(); + m_paramsWithValue.clear(); + if (argc == 0 || argv == nullptr) { + return; + } + m_argc = argc; + m_argv = argv; + for (int i = 1; i < m_argc; ++i) { + const char* v = (strstr(m_argv[i], "=")); + if (v != nullptr && strlen(v) > 0) { + std::string key = std::string(m_argv[i]); + key = key.substr(0, key.find_first_of('=')); + if (hasParamWithValue(key.c_str())) { + ELPP_INTERNAL_INFO(1, "Skipping [" << key << "] arg since it already has value [" + << getParamValue(key.c_str()) << "]"); + } + else { + m_paramsWithValue.insert(std::make_pair(key, std::string(v + 1))); + } + } + if (v == nullptr) { + if (hasParam(m_argv[i])) { + ELPP_INTERNAL_INFO(1, "Skipping [" << m_argv[i] << "] arg since it already exists"); + } + else { + m_params.push_back(std::string(m_argv[i])); + } + } + } + } + /// @brief Returns true if arguments contain paramKey with a value (seperated by '=') + inline bool hasParamWithValue(const char* paramKey) const { + return m_paramsWithValue.find(std::string(paramKey)) != m_paramsWithValue.end(); + } + /// @brief Returns value of arguments + /// @see hasParamWithValue(const char*) + inline const char* getParamValue(const char* paramKey) const { + return m_paramsWithValue.find(std::string(paramKey))->second.c_str(); + } + /// @brief Return true if arguments has a param (not having a value) i,e without '=' + inline bool hasParam(const char* paramKey) const { + return std::find(m_params.begin(), m_params.end(), std::string(paramKey)) != m_params.end(); + } + /// @brief Returns true if no params available. This exclude argv[0] + inline bool empty(void) const { + return m_params.empty() && m_paramsWithValue.empty(); + } + /// @brief Returns total number of arguments. This exclude argv[0] + inline std::size_t size(void) const { + return m_params.size() + m_paramsWithValue.size(); + } + inline friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const CommandLineArgs& c) { + for (int i = 1; i < c.m_argc; ++i) { + os << ELPP_LITERAL("[") << c.m_argv[i] << ELPP_LITERAL("]"); + if (i < c.m_argc - 1) { + os << ELPP_LITERAL(" "); + } + } + return os; + } + + private: + int m_argc; + char** m_argv; + std::map m_paramsWithValue; + std::vector m_params; + }; + /// @brief Abstract registry (aka repository) that provides basic interface for pointer repository specified by T_Ptr type. + /// + /// @detail Most of the functions are virtual final methods but anything implementing this abstract class should implement + /// unregisterAll() and deepCopy(const AbstractRegistry&) and write registerNew() method according to container + /// and few more methods; get() to find element, unregister() to unregister single entry. + /// Please note that this is thread-unsafe and should also implement thread-safety mechanisms in implementation. + template + class AbstractRegistry : public base::threading::ThreadSafe { + public: + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + + /// @brief Default constructor + AbstractRegistry(void) {} + + /// @brief Move constructor that is useful for base classes + AbstractRegistry(AbstractRegistry&& sr) { + if (this == &sr) { + return; + } + unregisterAll(); + m_list = std::move(sr.m_list); + } + + bool operator==(const AbstractRegistry& other) { + if (size() != other.size()) { + return false; + } + for (std::size_t i = 0; i < m_list.size(); ++i) { + if (m_list.at(i) != other.m_list.at(i)) { + return false; + } + } + return true; + } + + bool operator!=(const AbstractRegistry& other) { + if (size() != other.size()) { + return true; + } + for (std::size_t i = 0; i < m_list.size(); ++i) { + if (m_list.at(i) != other.m_list.at(i)) { + return true; + } + } + return false; + } + + /// @brief Assignment move operator + AbstractRegistry& operator=(AbstractRegistry&& sr) { + if (this == &sr) { + return *this; + } + unregisterAll(); + m_list = std::move(sr.m_list); + return *this; + } + + virtual ~AbstractRegistry(void) { + } + + /// @return Iterator pointer from start of repository + virtual inline iterator begin(void) ELPP_FINAL { + return m_list.begin(); + } + + /// @return Iterator pointer from end of repository + virtual inline iterator end(void) ELPP_FINAL { + return m_list.end(); + } + + + /// @return Constant iterator pointer from start of repository + virtual inline const_iterator cbegin(void) const ELPP_FINAL { + return m_list.cbegin(); + } + + /// @return End of repository + virtual inline const_iterator cend(void) const ELPP_FINAL { + return m_list.cend(); + } + + /// @return Whether or not repository is empty + virtual inline bool empty(void) const ELPP_FINAL { + return m_list.empty(); + } + + /// @return Size of repository + virtual inline std::size_t size(void) const ELPP_FINAL { + return m_list.size(); + } + + /// @brief Returns underlying container by reference + virtual inline Container& list(void) ELPP_FINAL { + return m_list; + } + + /// @brief Returns underlying container by constant reference. + virtual inline const Container& list(void) const ELPP_FINAL { + return m_list; + } + + /// @brief Unregisters all the pointers from current repository. + virtual void unregisterAll(void) = 0; + + protected: + virtual void deepCopy(const AbstractRegistry&) = 0; + void reinitDeepCopy(const AbstractRegistry& sr) { + unregisterAll(); + deepCopy(sr); + } + + private: + Container m_list; + }; + + /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (non-predicate version) + /// + /// @detail NOTE: This is thread-unsafe implementation (although it contains lock function, it does not use these functions) + /// of AbstractRegistry. Any implementation of this class should be + /// explicitly (by using lock functions) + template + class Registry : public AbstractRegistry> { + public: + typedef typename Registry::iterator iterator; + typedef typename Registry::const_iterator const_iterator; + + Registry(void) {} + + /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. + Registry(const Registry& sr) : AbstractRegistry>() { + if (this == &sr) { + return; + } + this->reinitDeepCopy(sr); + } + + /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element + /// @see unregisterAll() + /// @see deepCopy(const AbstractRegistry&) + Registry& operator=(const Registry& sr) { + if (this == &sr) { + return *this; + } + this->reinitDeepCopy(sr); + return *this; + } + + virtual ~Registry(void) { + unregisterAll(); + } + + protected: + virtual inline void unregisterAll(void) ELPP_FINAL { + if (!this->empty()) { + for (auto&& curr : this->list()) { + base::utils::safeDelete(curr.second); + } + this->list().clear(); + } + } + + /// @brief Registers new registry to repository. + virtual inline void registerNew(const T_Key& uniqKey, T_Ptr* ptr) ELPP_FINAL { + unregister(uniqKey); + this->list().insert(std::make_pair(uniqKey, ptr)); + } + + /// @brief Unregisters single entry mapped to specified unique key + inline void unregister(const T_Key& uniqKey) { + T_Ptr* existing = get(uniqKey); + if (existing != nullptr) { + base::utils::safeDelete(existing); + this->list().erase(uniqKey); + } + } + + /// @brief Gets pointer from repository. If none found, nullptr is returned. + inline T_Ptr* get(const T_Key& uniqKey) { + iterator it = this->list().find(uniqKey); + return it == this->list().end() + ? nullptr + : it->second; + } + + private: + virtual inline void deepCopy(const AbstractRegistry>& sr) ELPP_FINAL { + for (const_iterator it = sr.cbegin(); it != sr.cend(); ++it) { + registerNew(it->first, new T_Ptr(*it->second)); + } + } + }; + + /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (predicate version) + /// + /// @detail NOTE: This is thread-unsafe implementation of AbstractRegistry. Any implementation of this class + /// should be made thread-safe explicitly + template + class RegistryWithPred : public AbstractRegistry> { + public: + typedef typename RegistryWithPred::iterator iterator; + typedef typename RegistryWithPred::const_iterator const_iterator; + + RegistryWithPred(void) { + } + + virtual ~RegistryWithPred(void) { + unregisterAll(); + } + + /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. + RegistryWithPred(const RegistryWithPred& sr) : AbstractRegistry>() { + if (this == &sr) { + return; + } + this->reinitDeepCopy(sr); + } + + /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element + /// @see unregisterAll() + /// @see deepCopy(const AbstractRegistry&) + RegistryWithPred& operator=(const RegistryWithPred& sr) { + if (this == &sr) { + return *this; + } + this->reinitDeepCopy(sr); + return *this; + } + + friend inline base::type::ostream_t& operator<<(base::type::ostream_t& os, const RegistryWithPred& sr) { + for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { + os << ELPP_LITERAL(" ") << **it << ELPP_LITERAL("\n"); + } + return os; + } + + protected: + virtual inline void unregisterAll(void) ELPP_FINAL { + if (!this->empty()) { + for (auto&& curr : this->list()) { + base::utils::safeDelete(curr); + } + this->list().clear(); + } + } + + virtual void unregister(T_Ptr*& ptr) ELPP_FINAL { + if (ptr) { + iterator iter = this->begin(); + for (; iter != this->end(); ++iter) { + if (ptr == *iter) { + break; + } + } + if (iter != this->end() && *iter != nullptr) { + this->list().erase(iter); + base::utils::safeDelete(*iter); + } + } + } + + virtual inline void registerNew(T_Ptr* ptr) ELPP_FINAL { + this->list().push_back(ptr); + } + + /// @brief Gets pointer from repository with speicifed arguments. Arguments are passed to predicate + /// in order to validate pointer. + template + inline T_Ptr* get(const T& arg1, const T2 arg2) { + iterator iter = std::find_if(this->list().begin(), this->list().end(), Pred(arg1, arg2)); + if (iter != this->list().end() && *iter != nullptr) { + return *iter; + } + return nullptr; + } + + private: + virtual inline void deepCopy(const AbstractRegistry>& sr) { + for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { + registerNew(new T_Ptr(**it)); + } + } + }; + + } // namespace utils + } // namespace base + /// @brief Base of Easylogging++ friendly class + /// + /// @detail After inheriting this class publicly, implement pure-virtual function `void log(std::ostream&) const` + class Loggable { + public: + virtual ~Loggable(void) {} + virtual void log(el::base::type::ostream_t&) const = 0; + private: + friend inline el::base::type::ostream_t& operator<<(el::base::type::ostream_t& os, const Loggable& loggable) { + loggable.log(os); + return os; + } + }; + namespace base { + /// @brief Represents log format containing flags and date format. This is used internally to start initial log + class LogFormat : public Loggable { + public: + LogFormat(void) : + m_level(Level::Unknown), + m_userFormat(base::type::string_t()), + m_format(base::type::string_t()), + m_dateTimeFormat(std::string()), + m_flags(0x0) { + } + + LogFormat(Level level, const base::type::string_t& format) + : m_level(level), m_userFormat(format) { + parseFromFormat(m_userFormat); + } + + LogFormat(const LogFormat& logFormat) { + m_level = logFormat.m_level; + m_userFormat = logFormat.m_userFormat; + m_format = logFormat.m_format; + m_dateTimeFormat = logFormat.m_dateTimeFormat; + m_flags = logFormat.m_flags; + } + + LogFormat(LogFormat&& logFormat) { + m_level = std::move(logFormat.m_level); + m_userFormat = std::move(logFormat.m_userFormat); + m_format = std::move(logFormat.m_format); + m_dateTimeFormat = std::move(logFormat.m_dateTimeFormat); + m_flags = std::move(logFormat.m_flags); + } + + LogFormat& operator=(const LogFormat& logFormat) { + m_level = logFormat.m_level; + m_userFormat = logFormat.m_userFormat; + m_dateTimeFormat = logFormat.m_dateTimeFormat; + m_flags = logFormat.m_flags; + return *this; + } + + virtual ~LogFormat(void) { + } + + inline bool operator==(const LogFormat& other) { + return m_level == other.m_level && m_userFormat == other.m_userFormat && m_format == other.m_format && + m_dateTimeFormat == other.m_dateTimeFormat && m_flags == other.m_flags; + } + + /// @brief Updates format to be used while logging. + /// @param userFormat User provided format + void parseFromFormat(const base::type::string_t& userFormat) { + // We make copy because we will be changing the format + // i.e, removing user provided date format from original format + // and then storing it. + base::type::string_t formatCopy = userFormat; + m_flags = 0x0; + auto conditionalAddFlag = [&](const base::type::char_t* specifier, base::FormatFlags flag) { + std::size_t foundAt = base::type::string_t::npos; + while ((foundAt = formatCopy.find(specifier, foundAt + 1)) != base::type::string_t::npos) { + if (foundAt > 0 && formatCopy[foundAt - 1] == base::consts::kFormatSpecifierChar) { + if (hasFlag(flag)) { + // If we already have flag we remove the escape chars so that '%%' is turned to '%' + // even after specifier resolution - this is because we only replaceFirst specifier + formatCopy.erase(foundAt > 0 ? foundAt - 1 : 0, 1); + ++foundAt; + } + } + else { + if (!hasFlag(flag)) addFlag(flag); + } + } + }; + conditionalAddFlag(base::consts::kAppNameFormatSpecifier, base::FormatFlags::AppName); + conditionalAddFlag(base::consts::kSeverityLevelFormatSpecifier, base::FormatFlags::Level); + conditionalAddFlag(base::consts::kSeverityLevelShortFormatSpecifier, base::FormatFlags::LevelShort); + conditionalAddFlag(base::consts::kLoggerIdFormatSpecifier, base::FormatFlags::LoggerId); + conditionalAddFlag(base::consts::kThreadIdFormatSpecifier, base::FormatFlags::ThreadId); + conditionalAddFlag(base::consts::kLogFileFormatSpecifier, base::FormatFlags::File); + conditionalAddFlag(base::consts::kLogFileBaseFormatSpecifier, base::FormatFlags::FileBase); + conditionalAddFlag(base::consts::kLogLineFormatSpecifier, base::FormatFlags::Line); + conditionalAddFlag(base::consts::kLogLocationFormatSpecifier, base::FormatFlags::Location); + conditionalAddFlag(base::consts::kLogFunctionFormatSpecifier, base::FormatFlags::Function); + conditionalAddFlag(base::consts::kCurrentUserFormatSpecifier, base::FormatFlags::User); + conditionalAddFlag(base::consts::kCurrentHostFormatSpecifier, base::FormatFlags::Host); + conditionalAddFlag(base::consts::kMessageFormatSpecifier, base::FormatFlags::LogMessage); + conditionalAddFlag(base::consts::kVerboseLevelFormatSpecifier, base::FormatFlags::VerboseLevel); + // For date/time we need to extract user's date format first + std::size_t dateIndex = std::string::npos; + if ((dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier)) != std::string::npos) { + while (dateIndex > 0 && formatCopy[dateIndex - 1] == base::consts::kFormatSpecifierChar) { + dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier, dateIndex + 1); + } + if (dateIndex != std::string::npos) { + addFlag(base::FormatFlags::DateTime); + updateDateFormat(dateIndex, formatCopy); + } + } + m_format = formatCopy; + updateFormatSpec(); + } + + inline Level level(void) const { + return m_level; + } + + inline const base::type::string_t& userFormat(void) const { + return m_userFormat; + } + + inline const base::type::string_t& format(void) const { + return m_format; + } + + inline const std::string& dateTimeFormat(void) const { + return m_dateTimeFormat; + } + + inline base::type::EnumType flags(void) const { + return m_flags; + } + + inline bool hasFlag(base::FormatFlags flag) const { + return base::utils::hasFlag(flag, m_flags); + } + + virtual void log(el::base::type::ostream_t& os) const { + os << m_format; + } + + protected: + /// @brief Updates date time format if available in currFormat. + /// @param index Index where %datetime, %date or %time was found + /// @param [in,out] currFormat current format that is being used to format + virtual void updateDateFormat(std::size_t index, base::type::string_t& currFormat) ELPP_FINAL { + if (hasFlag(base::FormatFlags::DateTime)) { + index += ELPP_STRLEN(base::consts::kDateTimeFormatSpecifier); + } + const base::type::char_t* ptr = currFormat.c_str() + index; + if ((currFormat.size() > index) && (ptr[0] == '{')) { + // User has provided format for date/time + ++ptr; + int count = 1; // Start by 1 in order to remove starting brace + std::stringstream ss; + for (; *ptr; ++ptr, ++count) { + if (*ptr == '}') { + ++count; // In order to remove ending brace + break; + } + ss << *ptr; + } + currFormat.erase(index, count); + m_dateTimeFormat = ss.str(); + } + else { + // No format provided, use default + if (hasFlag(base::FormatFlags::DateTime)) { + m_dateTimeFormat = std::string(base::consts::kDefaultDateTimeFormat); + } + } + } + + /// @brief Updates %level from format. This is so that we dont have to do it at log-writing-time. It uses m_format and m_level + virtual void updateFormatSpec(void) ELPP_FINAL { + // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. + if (m_level == Level::Debug) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kDebugLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kDebugLevelShortLogValue); + } + else if (m_level == Level::Info) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kInfoLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kInfoLevelShortLogValue); + } + else if (m_level == Level::Warning) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kWarningLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kWarningLevelShortLogValue); + } + else if (m_level == Level::Error) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kErrorLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kErrorLevelShortLogValue); + } + else if (m_level == Level::Fatal) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kFatalLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kFatalLevelShortLogValue); + } + else if (m_level == Level::Verbose) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kVerboseLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kVerboseLevelShortLogValue); + } + else if (m_level == Level::Trace) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kTraceLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kTraceLevelShortLogValue); + } + if (hasFlag(base::FormatFlags::User)) { + std::string s = base::utils::s_currentUser; + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentUserFormatSpecifier, + base::utils::s_currentUser); + } + if (hasFlag(base::FormatFlags::Host)) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentHostFormatSpecifier, + base::utils::s_currentHost); + } + // Ignore Level::Global and Level::Unknown + } + + inline void addFlag(base::FormatFlags flag) { + base::utils::addFlag(flag, &m_flags); + } + + private: + Level m_level; + base::type::string_t m_userFormat; + base::type::string_t m_format; + std::string m_dateTimeFormat; + base::type::EnumType m_flags; + friend class el::Logger; // To resolve loggerId format specifier easily + }; + } // namespace base + /// @brief Resolving function for format specifier + typedef std::function FormatSpecifierValueResolver; + /// @brief User-provided custom format specifier + /// @see el::Helpers::installCustomFormatSpecifier + /// @see FormatSpecifierValueResolver + class CustomFormatSpecifier { + public: + CustomFormatSpecifier(const char* formatSpecifier, const FormatSpecifierValueResolver& resolver) : + m_formatSpecifier(formatSpecifier), m_resolver(resolver) {} + inline const char* formatSpecifier(void) const { return m_formatSpecifier; } + inline const FormatSpecifierValueResolver& resolver(void) const { return m_resolver; } + inline bool operator==(const char* formatSpecifier) { + return strcmp(m_formatSpecifier, formatSpecifier) == 0; + } + + private: + const char* m_formatSpecifier; + FormatSpecifierValueResolver m_resolver; + }; + /// @brief Represents single configuration that has representing level, configuration type and a string based value. + /// + /// @detail String based value means any value either its boolean, integer or string itself, it will be embedded inside quotes + /// and will be parsed later. + /// + /// Consider some examples below: + /// * el::Configuration confEnabledInfo(el::Level::Info, el::ConfigurationType::Enabled, "true"); + /// * el::Configuration confMaxLogFileSizeInfo(el::Level::Info, el::ConfigurationType::MaxLogFileSize, "2048"); + /// * el::Configuration confFilenameInfo(el::Level::Info, el::ConfigurationType::Filename, "/var/log/my.log"); + class Configuration : public Loggable { + public: + Configuration(const Configuration& c) : + m_level(c.m_level), + m_configurationType(c.m_configurationType), + m_value(c.m_value) { + } + + Configuration& operator=(const Configuration& c) { + m_level = c.m_level; + m_configurationType = c.m_configurationType; + m_value = c.m_value; + return *this; + } + + virtual ~Configuration(void) { + } + + /// @brief Full constructor used to sets value of configuration + Configuration(Level level, ConfigurationType configurationType, const std::string& value) : + m_level(level), + m_configurationType(configurationType), + m_value(value) { + } + + /// @brief Gets level of current configuration + inline Level level(void) const { + return m_level; + } + + /// @brief Gets configuration type of current configuration + inline ConfigurationType configurationType(void) const { + return m_configurationType; + } + + /// @brief Gets string based configuration value + inline const std::string& value(void) const { + return m_value; + } + + /// @brief Set string based configuration value + /// @param value Value to set. Values have to be std::string; For boolean values use "true", "false", for any integral values + /// use them in quotes. They will be parsed when configuring + inline void setValue(const std::string& value) { + m_value = value; + } + + virtual inline void log(el::base::type::ostream_t& os) const { + os << LevelHelper::convertToString(m_level) + << ELPP_LITERAL(" ") << ConfigurationTypeHelper::convertToString(m_configurationType) + << ELPP_LITERAL(" = ") << m_value.c_str(); + } + + /// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. + class Predicate { + public: + Predicate(Level level, ConfigurationType configurationType) : + m_level(level), + m_configurationType(configurationType) { + } + + inline bool operator()(const Configuration* conf) const { + return ((conf != nullptr) && (conf->level() == m_level) && (conf->configurationType() == m_configurationType)); + } + + private: + Level m_level; + ConfigurationType m_configurationType; + }; + + private: + Level m_level; + ConfigurationType m_configurationType; + std::string m_value; + }; + + /// @brief Thread-safe Configuration repository + /// + /// @detail This repository represents configurations for all the levels and configuration type mapped to a value. + class Configurations : public base::utils::RegistryWithPred { + public: + /// @brief Default constructor with empty repository + Configurations(void) : + m_configurationFile(std::string()), + m_isFromFile(false) { + } + + /// @brief Constructor used to set configurations using configuration file. + /// @param configurationFile Full path to configuration file + /// @param useDefaultsForRemaining Lets you set the remaining configurations to default. + /// @param base If provided, this configuration will be based off existing repository that this argument is pointing to. + /// @see parseFromFile(const std::string&, Configurations* base) + /// @see setRemainingToDefault() + Configurations(const std::string& configurationFile, bool useDefaultsForRemaining = true, Configurations* base = nullptr) : + m_configurationFile(configurationFile), + m_isFromFile(false) { + parseFromFile(configurationFile, base); + if (useDefaultsForRemaining) { + setRemainingToDefault(); + } + } + + virtual ~Configurations(void) { + } + + /// @brief Parses configuration from file. + /// @param configurationFile Full path to configuration file + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration file. + /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you + /// do not proceed without successful parse. + inline bool parseFromFile(const std::string& configurationFile, Configurations* base = nullptr) { + // We initial assertion with true because if we have assertion diabled, we want to pass this + // check and if assertion is enabled we will have values re-assigned any way. + bool assertionPassed = true; + ELPP_ASSERT((assertionPassed = base::utils::File::pathExists(configurationFile.c_str(), true)), + "Configuration file [" << configurationFile << "] does not exist!"); + if (!assertionPassed) { + return false; + } + bool success = Parser::parseFromFile(configurationFile, this, base); + m_isFromFile = success; + return success; + } + + /// @brief Parse configurations from configuration string. + /// + /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary + /// new line characters are provided. + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration text. + /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you + /// do not proceed without successful parse. + inline bool parseFromText(const std::string& configurationsString, Configurations* base = nullptr) { + bool success = Parser::parseFromText(configurationsString, this, base); + if (success) { + m_isFromFile = false; + } + return success; + } + + /// @brief Sets configuration based-off an existing configurations. + /// @param base Pointer to existing configurations. + inline void setFromBase(Configurations* base) { + if (base == nullptr || base == this) { + return; + } + base::threading::ScopedLock scopedLock(base->lock()); + for (Configuration*& conf : base->list()) { + set(conf); + } + } + + /// @brief Determines whether or not specified configuration type exists in the repository. + /// + /// @detail Returns as soon as first level is found. + /// @param configurationType Type of configuration to check existence for. + bool hasConfiguration(ConfigurationType configurationType) { + base::type::EnumType lIndex = LevelHelper::kMinValid; + bool result = false; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + if (hasConfiguration(LevelHelper::castFromInt(lIndex), configurationType)) { + result = true; + } + return result; + }); + return result; + } + + /// @brief Determines whether or not specified configuration type exists for specified level + /// @param level Level to check + /// @param configurationType Type of configuration to check existence for. + inline bool hasConfiguration(Level level, ConfigurationType configurationType) { + base::threading::ScopedLock scopedLock(lock()); +#if ELPP_COMPILER_INTEL + // We cant specify template types here, Intel C++ throws compilation error + // "error: type name is not allowed" + return RegistryWithPred::get(level, configurationType) != nullptr; +#else + return RegistryWithPred::get(level, configurationType) != nullptr; +#endif // ELPP_COMPILER_INTEL + } + + /// @brief Sets value of configuration for specified level. + /// + /// @detail Any existing configuration for specified level will be replaced. Also note that configuration types + /// ConfigurationType::MillisecondsWidth and ConfigurationType::PerformanceTracking will be ignored if not set for + /// Level::Global because these configurations are not dependant on level. + /// @param level Level to set configuration for (el::Level). + /// @param configurationType Type of configuration (el::ConfigurationType) + /// @param value A string based value. Regardless of what the data type of configuration is, it will always be string + /// from users' point of view. This is then parsed later to be used internally. + /// @see Configuration::setValue(const std::string& value) + /// @see el::Level + /// @see el::ConfigurationType + inline void set(Level level, ConfigurationType configurationType, const std::string& value) { + base::threading::ScopedLock scopedLock(lock()); + unsafeSet(level, configurationType, value); // This is not unsafe anymore as we have locked mutex + if (level == Level::Global) { + unsafeSetGlobally(configurationType, value, false); // Again this is not unsafe either + } + } + + /// @brief Sets single configuration based on other single configuration. + /// @see set(Level level, ConfigurationType configurationType, const std::string& value) + inline void set(Configuration* conf) { + if (conf == nullptr) { + return; + } + set(conf->level(), conf->configurationType(), conf->value()); + } + + inline Configuration* get(Level level, ConfigurationType configurationType) { + base::threading::ScopedLock scopedLock(lock()); + return RegistryWithPred::get(level, configurationType); + } + + /// @brief Sets configuration for all levels. + /// @param configurationType Type of configuration + /// @param value String based value + /// @see Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) + inline void setGlobally(ConfigurationType configurationType, const std::string& value) { + setGlobally(configurationType, value, false); + } + + /// @brief Clears repository so that all the configurations are unset + inline void clear(void) { + base::threading::ScopedLock scopedLock(lock()); + unregisterAll(); + } + + /// @brief Gets configuration file used in parsing this configurations. + /// + /// @detail If this repository was set manually or by text this returns empty string. + inline const std::string& configurationFile(void) const { + return m_configurationFile; + } + + /// @brief Sets configurations to "factory based" configurations. + void setToDefault(void) { + setGlobally(ConfigurationType::Enabled, std::string("true"), true); +#if !defined(ELPP_NO_DEFAULT_LOG_FILE) + setGlobally(ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile), true); +#else + ELPP_UNUSED(base::consts::kDefaultLogFile); +#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) + setGlobally(ConfigurationType::ToFile, std::string("true"), true); + setGlobally(ConfigurationType::ToStandardOutput, std::string("true"), true); + setGlobally(ConfigurationType::MillisecondsWidth, std::string("3"), true); + setGlobally(ConfigurationType::PerformanceTracking, std::string("true"), true); + setGlobally(ConfigurationType::MaxLogFileSize, std::string("0"), true); + setGlobally(ConfigurationType::LogFlushThreshold, std::string("0"), true); + + setGlobally(ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"), true); + set(Level::Debug, ConfigurationType::Format, std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); + // INFO and WARNING are set to default by Level::Global + set(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + set(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + set(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); + set(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg")); + } + + /// @brief Lets you set the remaining configurations to default. + /// + /// @detail By remaining, it means that the level/type a configuration does not exist for. + /// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets + /// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is set to default i.e, + /// true. If you dont do this explicitley (either by calling this function or by using second param in Constructor + /// and try to access a value, an error is thrown + void setRemainingToDefault(void) { + base::threading::ScopedLock scopedLock(lock()); + unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("true")); +#if !defined(ELPP_NO_DEFAULT_LOG_FILE) + unsafeSetIfNotExist(Level::Global, ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile)); +#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) + unsafeSetIfNotExist(Level::Global, ConfigurationType::ToFile, std::string("true")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::ToStandardOutput, std::string("true")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::MillisecondsWidth, std::string("3")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::PerformanceTracking, std::string("true")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::MaxLogFileSize, std::string("0")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + unsafeSetIfNotExist(Level::Debug, ConfigurationType::Format, + std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); + // INFO and WARNING are set to default by Level::Global + unsafeSetIfNotExist(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + unsafeSetIfNotExist(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + unsafeSetIfNotExist(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); + unsafeSetIfNotExist(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg")); + } + + /// @brief Parser used internally to parse configurations from file or text. + /// + /// @detail This class makes use of base::utils::Str. + /// You should not need this unless you are working on some tool for Easylogging++ + class Parser : base::StaticClass { + public: + /// @brief Parses configuration from file. + /// @param configurationFile Full path to configuration file + /// @param sender Sender configurations pointer. Usually 'this' is used from calling class + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration file. + /// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you + /// do not proceed without successful parse. + static bool parseFromFile(const std::string& configurationFile, Configurations* sender, Configurations* base = nullptr) { + sender->setFromBase(base); + std::ifstream fileStream_(configurationFile.c_str(), std::ifstream::in); + ELPP_ASSERT(fileStream_.is_open(), "Unable to open configuration file [" << configurationFile << "] for parsing."); + bool parsedSuccessfully = false; + std::string line = std::string(); + Level currLevel = Level::Unknown; + std::string currConfigStr = std::string(); + std::string currLevelStr = std::string(); + while (fileStream_.good()) { + std::getline(fileStream_, line); + parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); + ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); + } + return parsedSuccessfully; + } + + /// @brief Parse configurations from configuration string. + /// + /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary + /// new line characters are provided. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you + /// do not proceed without successful parse (This is recommended) + /// @param configurationsString + /// @param sender Sender configurations pointer. Usually 'this' is used from calling class + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration text. + /// @return True if successfully parsed, false otherwise. + static bool parseFromText(const std::string& configurationsString, Configurations* sender, Configurations* base = nullptr) { + sender->setFromBase(base); + bool parsedSuccessfully = false; + std::stringstream ss(configurationsString); + std::string line = std::string(); + Level currLevel = Level::Unknown; + std::string currConfigStr = std::string(); + std::string currLevelStr = std::string(); + while (std::getline(ss, line)) { + parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); + ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); + } + return parsedSuccessfully; + } + + private: + friend class el::Loggers; + static void ignoreComments(std::string* line) { + std::size_t foundAt = 0; + std::size_t quotesStart = line->find("\""); + std::size_t quotesEnd = std::string::npos; + if (quotesStart != std::string::npos) { + quotesEnd = line->find("\"", quotesStart + 1); + while (quotesEnd != std::string::npos && line->at(quotesEnd - 1) == '\\') { + // Do not erase slash yet - we will erase it in parseLine(..) while loop + quotesEnd = line->find("\"", quotesEnd + 2); + } + } + if ((foundAt = line->find(base::consts::kConfigurationComment)) != std::string::npos) { + if (foundAt < quotesEnd) { + foundAt = line->find(base::consts::kConfigurationComment, quotesEnd + 1); + } + *line = line->substr(0, foundAt); + } + } + static inline bool isLevel(const std::string& line) { + return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLevel)); + } + + static inline bool isComment(const std::string& line) { + return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationComment)); + } + + static inline bool isConfig(const std::string& line) { + std::size_t assignment = line.find('='); + return line != "" && + (line[0] >= 65 || line[0] <= 90 || line[0] >= 97 || line[0] <= 122) && + (assignment != std::string::npos) && + (line.size() > assignment); + } + + static bool parseLine(std::string* line, std::string* currConfigStr, std::string* currLevelStr, Level* currLevel, Configurations* conf) { + ConfigurationType currConfig = ConfigurationType::Unknown; + std::string currValue = std::string(); + *line = base::utils::Str::trim(*line); + if (isComment(*line)) return true; + ignoreComments(line); + *line = base::utils::Str::trim(*line); + if (line->empty()) { + // Comment ignored + return true; + } + if (isLevel(*line)) { + if (line->size() <= 2) { + return true; + } + *currLevelStr = line->substr(1, line->size() - 2); + *currLevelStr = base::utils::Str::toUpper(*currLevelStr); + *currLevelStr = base::utils::Str::trim(*currLevelStr); + *currLevel = LevelHelper::convertFromString(currLevelStr->c_str()); + return true; + } + if (isConfig(*line)) { + std::size_t assignment = line->find('='); + *currConfigStr = line->substr(0, assignment); + *currConfigStr = base::utils::Str::toUpper(*currConfigStr); + *currConfigStr = base::utils::Str::trim(*currConfigStr); + currConfig = ConfigurationTypeHelper::convertFromString(currConfigStr->c_str()); + currValue = line->substr(assignment + 1); + currValue = base::utils::Str::trim(currValue); + std::size_t quotesStart = currValue.find("\"", 0); + std::size_t quotesEnd = std::string::npos; + if (quotesStart != std::string::npos) { + quotesEnd = currValue.find("\"", quotesStart + 1); + while (quotesEnd != std::string::npos && currValue.at(quotesEnd - 1) == '\\') { + currValue = currValue.erase(quotesEnd - 1, 1); + quotesEnd = currValue.find("\"", quotesEnd + 2); + } + } + if (quotesStart != std::string::npos && quotesEnd != std::string::npos) { + // Quote provided - check and strip if valid + ELPP_ASSERT((quotesStart < quotesEnd), "Configuration error - No ending quote found in [" + << currConfigStr << "]"); + ELPP_ASSERT((quotesStart + 1 != quotesEnd), "Empty configuration value for [" << currConfigStr << "]"); + if ((quotesStart != quotesEnd) && (quotesStart + 1 != quotesEnd)) { + // Explicit check in case if assertion is disabled + currValue = currValue.substr(quotesStart + 1, quotesEnd - 1); + } + } + } + ELPP_ASSERT(*currLevel != Level::Unknown, "Unrecognized severity level [" << *currLevelStr << "]"); + ELPP_ASSERT(currConfig != ConfigurationType::Unknown, "Unrecognized configuration [" << *currConfigStr << "]"); + if (*currLevel == Level::Unknown || currConfig == ConfigurationType::Unknown) { + return false; // unrecognizable level or config + } + conf->set(*currLevel, currConfig, currValue); + return true; + } + }; + + private: + std::string m_configurationFile; + bool m_isFromFile; + friend class el::Loggers; + + /// @brief Unsafely sets configuration if does not already exist + void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value) { + Configuration* conf = RegistryWithPred::get(level, configurationType); + if (conf == nullptr) { + unsafeSet(level, configurationType, value); + } + } + + /// @brief Thread unsafe set + void unsafeSet(Level level, ConfigurationType configurationType, const std::string& value) { + Configuration* conf = RegistryWithPred::get(level, configurationType); + if (conf == nullptr) { + registerNew(new Configuration(level, configurationType, value)); + } + else { + conf->setValue(value); + } + if (level == Level::Global) { + unsafeSetGlobally(configurationType, value, false); + } + } + + /// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true + /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) + void setGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel) { + if (includeGlobalLevel) { + set(Level::Global, configurationType, value); + } + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + set(LevelHelper::castFromInt(lIndex), configurationType, value); + return false; // Do not break lambda function yet as we need to set all levels regardless + }); + } + + /// @brief Sets configurations (Unsafely) for all levels including Level::Global if includeGlobalLevel is true + /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) + void unsafeSetGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel) { + if (includeGlobalLevel) { + unsafeSet(Level::Global, configurationType, value); + } + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + unsafeSet(LevelHelper::castFromInt(lIndex), configurationType, value); + return false; // Do not break lambda function yet as we need to set all levels regardless + }); + } + }; + + namespace base { + typedef std::shared_ptr FileStreamPtr; + typedef std::map LogStreamsReferenceMap; + /// @brief Configurations with data types. + /// + /// @detail el::Configurations have string based values. This is whats used internally in order to read correct configurations. + /// This is to perform faster while writing logs using correct configurations. + /// + /// This is thread safe and final class containing non-virtual destructor (means nothing should inherit this class) + class TypedConfigurations : public base::threading::ThreadSafe { + public: + /// @brief Constructor to initialize (construct) the object off el::Configurations + /// @param configurations Configurations pointer/reference to base this typed configurations off. + /// @param logStreamsReference Use ELPP->registeredLoggers()->logStreamsReference() + TypedConfigurations(Configurations* configurations, base::LogStreamsReferenceMap* logStreamsReference) { + m_configurations = configurations; + m_logStreamsReference = logStreamsReference; + build(m_configurations); + } + + TypedConfigurations(const TypedConfigurations& other) { + this->m_configurations = other.m_configurations; + this->m_logStreamsReference = other.m_logStreamsReference; + build(m_configurations); + } + + virtual ~TypedConfigurations(void) { + } + + const Configurations* configurations(void) const { + return m_configurations; + } + + inline bool enabled(Level level) { + return getConfigByVal(level, &m_enabledMap, "enabled"); + } + + inline bool toFile(Level level) { + return getConfigByVal(level, &m_toFileMap, "toFile"); + } + + inline const std::string& filename(Level level) { + return getConfigByRef(level, &m_filenameMap, "filename"); + } + + inline bool toStandardOutput(Level level) { + return getConfigByVal(level, &m_toStandardOutputMap, "toStandardOutput"); + } + + inline const base::LogFormat& logFormat(Level level) { + return getConfigByRef(level, &m_logFormatMap, "logFormat"); + } + + inline const base::MillisecondsWidth& millisecondsWidth(Level level = Level::Global) { + return getConfigByRef(level, &m_millisecondsWidthMap, "millisecondsWidth"); + } + + inline bool performanceTracking(Level level = Level::Global) { + return getConfigByVal(level, &m_performanceTrackingMap, "performanceTracking"); + } + + inline base::type::fstream_t* fileStream(Level level) { + return getConfigByRef(level, &m_fileStreamMap, "fileStream").get(); + } + + inline std::size_t maxLogFileSize(Level level) { + return getConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); + } + + inline std::size_t logFlushThreshold(Level level) { + return getConfigByVal(level, &m_logFlushThresholdMap, "logFlushThreshold"); + } + + private: + Configurations* m_configurations; + std::map m_enabledMap; + std::map m_toFileMap; + std::map m_filenameMap; + std::map m_toStandardOutputMap; + std::map m_logFormatMap; + std::map m_millisecondsWidthMap; + std::map m_performanceTrackingMap; + std::map m_fileStreamMap; + std::map m_maxLogFileSizeMap; + std::map m_logFlushThresholdMap; + base::LogStreamsReferenceMap* m_logStreamsReference; + + friend class el::Helpers; + friend class el::base::MessageBuilder; + friend class el::base::Writer; + friend class el::base::DefaultLogDispatchCallback; + friend class el::base::LogDispatcher; + + template + inline Conf_T getConfigByVal(Level level, const std::map* confMap, const char* confName) { + base::threading::ScopedLock scopedLock(lock()); + return unsafeGetConfigByVal(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope + } + + template + inline Conf_T& getConfigByRef(Level level, std::map* confMap, const char* confName) { + base::threading::ScopedLock scopedLock(lock()); + return unsafeGetConfigByRef(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope + } + + template + inline Conf_T unsafeGetConfigByVal(Level level, const std::map* confMap, const char* confName) { + ELPP_UNUSED(confName); + typename std::map::const_iterator it = confMap->find(level); + if (it == confMap->end()) { + try { + return confMap->at(Level::Global); + } + catch (...) { + ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" + << LevelHelper::convertToString(level) << "]" + << std::endl << "Please ensure you have properly configured logger.", false); + return Conf_T(); + } + } + return it->second; + } + + template + inline Conf_T& unsafeGetConfigByRef(Level level, std::map* confMap, const char* confName) { + ELPP_UNUSED(confName); + typename std::map::iterator it = confMap->find(level); + if (it == confMap->end()) { + try { + return confMap->at(Level::Global); + } + catch (...) { + ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" + << LevelHelper::convertToString(level) << "]" + << std::endl << "Please ensure you have properly configured logger.", false); + } + } + return it->second; + } + + template + void setValue(Level level, const Conf_T& value, std::map* confMap, bool includeGlobalLevel = true) { + // If map is empty and we are allowed to add into generic level (Level::Global), do it! + if (confMap->empty() && includeGlobalLevel) { + confMap->insert(std::make_pair(Level::Global, value)); + return; + } + // If same value exist in generic level already, dont add it to explicit level + typename std::map::iterator it = confMap->find(Level::Global); + if (it != confMap->end() && it->second == value) { + return; + } + // Now make sure we dont double up values if we really need to add it to explicit level + it = confMap->find(level); + if (it == confMap->end()) { + // Value not found for level, add new + confMap->insert(std::make_pair(level, value)); + } + else { + // Value found, just update value + confMap->at(level) = value; + } + } + + void build(Configurations* configurations) { + base::threading::ScopedLock scopedLock(lock()); + auto getBool = [](std::string boolStr) -> bool { // Pass by value for trimming + base::utils::Str::trim(boolStr); + return (boolStr == "TRUE" || boolStr == "true" || boolStr == "1"); + }; + std::vector withFileSizeLimit; + for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { + Configuration* conf = *it; + // We cannot use switch on strong enums because Intel C++ dont support them yet + if (conf->configurationType() == ConfigurationType::Enabled) { + setValue(conf->level(), getBool(conf->value()), &m_enabledMap); + } + else if (conf->configurationType() == ConfigurationType::ToFile) { + setValue(conf->level(), getBool(conf->value()), &m_toFileMap); + } + else if (conf->configurationType() == ConfigurationType::ToStandardOutput) { + setValue(conf->level(), getBool(conf->value()), &m_toStandardOutputMap); + } + else if (conf->configurationType() == ConfigurationType::Filename) { + // We do not yet configure filename but we will configure in another + // loop. This is because if file cannot be created, we will force ToFile + // to be false. Because configuring logger is not necessarily performance + // sensative operation, we can live with another loop; (by the way this loop + // is not very heavy either) + } + else if (conf->configurationType() == ConfigurationType::Format) { + setValue(conf->level(), base::LogFormat(conf->level(), + base::type::string_t(conf->value().begin(), conf->value().end())), &m_logFormatMap); + } + else if (conf->configurationType() == ConfigurationType::MillisecondsWidth) { + setValue(Level::Global, + base::MillisecondsWidth(static_cast(getULong(conf->value()))), &m_millisecondsWidthMap); + } + else if (conf->configurationType() == ConfigurationType::PerformanceTracking) { + setValue(Level::Global, getBool(conf->value()), &m_performanceTrackingMap); + } + else if (conf->configurationType() == ConfigurationType::MaxLogFileSize) { + setValue(conf->level(), static_cast(getULong(conf->value())), &m_maxLogFileSizeMap); +#if !defined(ELPP_NO_DEFAULT_LOG_FILE) + withFileSizeLimit.push_back(conf); +#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) + } + else if (conf->configurationType() == ConfigurationType::LogFlushThreshold) { + setValue(conf->level(), static_cast(getULong(conf->value())), &m_logFlushThresholdMap); + } + } + // As mentioned early, we will now set filename configuration in separate loop to deal with non-existent files + for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { + Configuration* conf = *it; + if (conf->configurationType() == ConfigurationType::Filename) { + insertFile(conf->level(), conf->value()); + } + } + for (std::vector::iterator conf = withFileSizeLimit.begin(); + conf != withFileSizeLimit.end(); ++conf) { + // This is not unsafe as mutex is locked in currect scope + unsafeValidateFileRolling((*conf)->level(), base::defaultPreRollOutCallback); + } + } + + unsigned long getULong(std::string confVal) { + bool valid = true; + base::utils::Str::trim(confVal); + valid = !confVal.empty() && std::find_if(confVal.begin(), confVal.end(), + [](char c) { return !base::utils::Str::isDigit(c); }) == confVal.end(); + if (!valid) { + valid = false; + ELPP_ASSERT(valid, "Configuration value not a valid integer [" << confVal << "]"); + return 0; + } + return atol(confVal.c_str()); + } + + std::string resolveFilename(const std::string& filename) { + std::string resultingFilename = filename; + std::size_t dateIndex = std::string::npos; + std::string dateTimeFormatSpecifierStr = std::string(base::consts::kDateTimeFormatSpecifierForFilename); + if ((dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str())) != std::string::npos) { + while (dateIndex > 0 && resultingFilename[dateIndex - 1] == base::consts::kFormatSpecifierChar) { + dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str(), dateIndex + 1); + } + if (dateIndex != std::string::npos) { + const char* ptr = resultingFilename.c_str() + dateIndex; + // Goto end of specifier + ptr += dateTimeFormatSpecifierStr.size(); + std::string fmt; + if ((resultingFilename.size() > dateIndex) && (ptr[0] == '{')) { + // User has provided format for date/time + ++ptr; + int count = 1; // Start by 1 in order to remove starting brace + std::stringstream ss; + for (; *ptr; ++ptr, ++count) { + if (*ptr == '}') { + ++count; // In order to remove ending brace + break; + } + ss << *ptr; + } + resultingFilename.erase(dateIndex + dateTimeFormatSpecifierStr.size(), count); + fmt = ss.str(); + } + else { + fmt = std::string(base::consts::kDefaultDateTimeFormatInFilename); + } + base::MillisecondsWidth msWidth(3); + std::string now = base::utils::DateTime::getDateTime(fmt.c_str(), &msWidth); + base::utils::Str::replaceAll(now, '/', '-'); // Replace path element since we are dealing with filename + base::utils::Str::replaceAll(resultingFilename, dateTimeFormatSpecifierStr, now); + } + } + return resultingFilename; + } + + void insertFile(Level level, const std::string& fullFilename) { + std::string resolvedFilename = resolveFilename(fullFilename); + if (resolvedFilename.empty()) { + std::cerr << "Could not load empty file for logging, please re-check your configurations for level [" + << LevelHelper::convertToString(level) << "]"; + } + std::string filePath = base::utils::File::extractPathFromFilename(resolvedFilename, base::consts::kFilePathSeperator); + if (filePath.size() < resolvedFilename.size()) { + base::utils::File::createPath(filePath); + } + auto create = [&](Level level) { + base::LogStreamsReferenceMap::iterator filestreamIter = m_logStreamsReference->find(resolvedFilename); + base::type::fstream_t* fs = nullptr; + if (filestreamIter == m_logStreamsReference->end()) { + // We need a completely new stream, nothing to share with + fs = base::utils::File::newFileStream(resolvedFilename); + m_filenameMap.insert(std::make_pair(level, resolvedFilename)); + m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(fs))); + m_logStreamsReference->insert(std::make_pair(resolvedFilename, base::FileStreamPtr(m_fileStreamMap.at(level)))); + } + else { + // Woops! we have an existing one, share it! + m_filenameMap.insert(std::make_pair(level, filestreamIter->first)); + m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(filestreamIter->second))); + fs = filestreamIter->second.get(); + } + if (fs == nullptr) { + // We display bad file error from newFileStream() + ELPP_INTERNAL_ERROR("Setting [TO_FILE] of [" + << LevelHelper::convertToString(level) << "] to FALSE", false); + setValue(level, false, &m_toFileMap); + } + }; + // If we dont have file conf for any level, create it for Level::Global first + // otherwise create for specified level + create(m_filenameMap.empty() && m_fileStreamMap.empty() ? Level::Global : level); + } + + bool unsafeValidateFileRolling(Level level, const PreRollOutCallback& PreRollOutCallback) { + base::type::fstream_t* fs = unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get(); + if (fs == nullptr) { + return true; + } + std::size_t maxLogFileSize = unsafeGetConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); + std::size_t currFileSize = base::utils::File::getSizeOfFile(fs); + if (maxLogFileSize != 0 && currFileSize >= maxLogFileSize) { + std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename"); + ELPP_INTERNAL_INFO(1, "Truncating log file [" << fname << "] as a result of configurations for level [" + << LevelHelper::convertToString(level) << "]"); + fs->close(); + PreRollOutCallback(fname.c_str(), currFileSize); + fs->open(fname, std::fstream::out | std::fstream::trunc); + return true; + } + return false; + } + + bool validateFileRolling(Level level, const PreRollOutCallback& PreRollOutCallback) { + base::threading::ScopedLock scopedLock(lock()); + return unsafeValidateFileRolling(level, PreRollOutCallback); + } + }; + /// @brief Class that keeps record of current line hit for occasional logging + class HitCounter { + public: + HitCounter(void) : + m_filename(""), + m_lineNumber(0), + m_hitCounts(0) { + } + + HitCounter(const char* filename, unsigned long int lineNumber) : + m_filename(filename), + m_lineNumber(lineNumber), + m_hitCounts(0) { + } + + HitCounter(const HitCounter& hitCounter) : + m_filename(hitCounter.m_filename), + m_lineNumber(hitCounter.m_lineNumber), + m_hitCounts(hitCounter.m_hitCounts) { + } + + HitCounter& operator=(const HitCounter& hitCounter) { + m_filename = hitCounter.m_filename; + m_lineNumber = hitCounter.m_lineNumber; + m_hitCounts = hitCounter.m_hitCounts; + return *this; + } + + virtual ~HitCounter(void) { + } + + /// @brief Resets location of current hit counter + inline void resetLocation(const char* filename, unsigned long int lineNumber) { + m_filename = filename; + m_lineNumber = lineNumber; + } + + /// @brief Validates hit counts and resets it if necessary + inline void validateHitCounts(std::size_t n) { + if (m_hitCounts >= base::consts::kMaxLogPerCounter) { + m_hitCounts = (n >= 1 ? base::consts::kMaxLogPerCounter % n : 0); + } + ++m_hitCounts; + } + + inline const char* filename(void) const { + return m_filename; + } + + inline unsigned long int lineNumber(void) const { + return m_lineNumber; + } + + inline std::size_t hitCounts(void) const { + return m_hitCounts; + } + + inline void increment(void) { + ++m_hitCounts; + } + + class Predicate { + public: + Predicate(const char* filename, unsigned long int lineNumber) + : m_filename(filename), + m_lineNumber(lineNumber) { + } + inline bool operator()(const HitCounter* counter) { + return ((counter != nullptr) && + (strcmp(counter->m_filename, m_filename) == 0) && + (counter->m_lineNumber == m_lineNumber)); + } + + private: + const char* m_filename; + unsigned long int m_lineNumber; + }; + + private: + const char* m_filename; + unsigned long int m_lineNumber; + std::size_t m_hitCounts; + }; + /// @brief Repository for hit counters used across the application + class RegisteredHitCounters : public base::utils::RegistryWithPred { + public: + /// @brief Validates counter for every N, i.e, registers new if does not exist otherwise updates original one + /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned + bool validateEveryN(const char* filename, unsigned long int lineNumber, std::size_t n) { + base::threading::ScopedLock scopedLock(lock()); + base::HitCounter* counter = get(filename, lineNumber); + if (counter == nullptr) { + registerNew(counter = new base::HitCounter(filename, lineNumber)); + } + counter->validateHitCounts(n); + bool result = (n >= 1 && counter->hitCounts() != 0 && counter->hitCounts() % n == 0); + return result; + } + + /// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one + /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned + bool validateAfterN(const char* filename, unsigned long int lineNumber, std::size_t n) { + base::threading::ScopedLock scopedLock(lock()); + base::HitCounter* counter = get(filename, lineNumber); + if (counter == nullptr) { + registerNew(counter = new base::HitCounter(filename, lineNumber)); + } + // Do not use validateHitCounts here since we do not want to reset counter here + // Note the >= instead of > because we are incrementing + // after this check + if (counter->hitCounts() >= n) + return true; + counter->increment(); + return false; + } + + /// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one + /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned + bool validateNTimes(const char* filename, unsigned long int lineNumber, std::size_t n) { + base::threading::ScopedLock scopedLock(lock()); + base::HitCounter* counter = get(filename, lineNumber); + if (counter == nullptr) { + registerNew(counter = new base::HitCounter(filename, lineNumber)); + } + counter->increment(); + // Do not use validateHitCounts here since we do not want to reset counter here + if (counter->hitCounts() <= n) + return true; + return false; + } + + /// @brief Gets hit counter registered at specified position + inline const base::HitCounter* getCounter(const char* filename, unsigned long int lineNumber) { + base::threading::ScopedLock scopedLock(lock()); + return get(filename, lineNumber); + } + }; + /// @brief Action to be taken for dispatching + enum class DispatchAction : base::type::EnumType { + None = 1, NormalLog = 2, SysLog = 4 + }; + } // namespace base + template + class Callback : protected base::threading::ThreadSafe { + public: + Callback(void) : m_enabled(true) {} + inline bool enabled(void) const { return m_enabled; } + inline void setEnabled(bool enabled) { + base::threading::ScopedLock scopedLock(lock()); + m_enabled = enabled; + } + protected: + virtual void handle(const T* handlePtr) = 0; + private: + bool m_enabled; + }; + class LogDispatchData { + public: + LogDispatchData() : m_logMessage(nullptr), m_dispatchAction(base::DispatchAction::None) {} + inline const LogMessage* logMessage(void) const { return m_logMessage; } + inline base::DispatchAction dispatchAction(void) const { return m_dispatchAction; } + private: + LogMessage* m_logMessage; + base::DispatchAction m_dispatchAction; + friend class base::LogDispatcher; + + inline void setLogMessage(LogMessage* logMessage) { m_logMessage = logMessage; } + inline void setDispatchAction(base::DispatchAction dispatchAction) { m_dispatchAction = dispatchAction; } + }; + class LogDispatchCallback : public Callback { + private: + friend class base::LogDispatcher; + }; + class PerformanceTrackingCallback : public Callback { + private: + friend class base::PerformanceTracker; + }; + class LogBuilder : base::NoCopy { + public: + virtual ~LogBuilder(void) { ELPP_INTERNAL_INFO(3, "Destroying log builder...") } + virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0; + void convertToColoredOutput(base::type::string_t* logLine, Level level) { + if (!base::utils::s_termSupportsColor) return; + const base::type::char_t* resetColor = ELPP_LITERAL("\x1b[0m"); + if (level == Level::Error || level == Level::Fatal) + *logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor; + else if (level == Level::Warning) + *logLine = ELPP_LITERAL("\x1b[33m") + *logLine + resetColor; + } + private: + friend class el::base::DefaultLogDispatchCallback; + }; + typedef std::shared_ptr LogBuilderPtr; + /// @brief Represents a logger holding ID and configurations we need to write logs + /// + /// @detail This class does not write logs itself instead its used by writer to read configuations from. + class Logger : public base::threading::ThreadSafe, public Loggable { + public: + Logger(const std::string& id, base::LogStreamsReferenceMap* logStreamsReference) : + m_id(id), + m_typedConfigurations(nullptr), + m_parentApplicationName(std::string()), + m_isConfigured(false), + m_logStreamsReference(logStreamsReference) { + initUnflushedCount(); + } + + Logger(const std::string& id, const Configurations& configurations, base::LogStreamsReferenceMap* logStreamsReference) : + m_id(id), + m_typedConfigurations(nullptr), + m_parentApplicationName(std::string()), + m_isConfigured(false), + m_logStreamsReference(logStreamsReference) { + initUnflushedCount(); + configure(configurations); + } + + Logger(const Logger& logger) { + base::utils::safeDelete(m_typedConfigurations); + m_id = logger.m_id; + m_typedConfigurations = logger.m_typedConfigurations; + m_parentApplicationName = logger.m_parentApplicationName; + m_isConfigured = logger.m_isConfigured; + m_configurations = logger.m_configurations; + m_unflushedCount = logger.m_unflushedCount; + m_logStreamsReference = logger.m_logStreamsReference; + } + + Logger& operator=(const Logger& logger) { + base::utils::safeDelete(m_typedConfigurations); + m_id = logger.m_id; + m_typedConfigurations = logger.m_typedConfigurations; + m_parentApplicationName = logger.m_parentApplicationName; + m_isConfigured = logger.m_isConfigured; + m_configurations = logger.m_configurations; + m_unflushedCount = logger.m_unflushedCount; + m_logStreamsReference = logger.m_logStreamsReference; + return *this; + } + + virtual ~Logger(void) { + base::utils::safeDelete(m_typedConfigurations); + } + + virtual inline void log(el::base::type::ostream_t& os) const { + os << m_id.c_str(); + } + + /// @brief Configures the logger using specified configurations. + void configure(const Configurations& configurations) { + m_isConfigured = false; // we set it to false in case if we fail + initUnflushedCount(); + if (m_typedConfigurations != nullptr) { + Configurations* c = const_cast(m_typedConfigurations->configurations()); + if (c->hasConfiguration(Level::Global, ConfigurationType::Filename)) { + // This check is definitely needed for cases like ELPP_NO_DEFAULT_LOG_FILE + flush(); + } + } + base::threading::ScopedLock scopedLock(lock()); + if (m_configurations != configurations) { + m_configurations.setFromBase(const_cast(&configurations)); + } + base::utils::safeDelete(m_typedConfigurations); + m_typedConfigurations = new base::TypedConfigurations(&m_configurations, m_logStreamsReference); + resolveLoggerFormatSpec(); + m_isConfigured = true; + } + + /// @brief Reconfigures logger using existing configurations + inline void reconfigure(void) { + ELPP_INTERNAL_INFO(1, "Reconfiguring logger [" << m_id << "]"); + configure(m_configurations); + } + + inline const std::string& id(void) const { + return m_id; + } + + inline const std::string& parentApplicationName(void) const { + return m_parentApplicationName; + } + + inline void setParentApplicationName(const std::string& parentApplicationName) { + m_parentApplicationName = parentApplicationName; + } + + inline Configurations* configurations(void) { + return &m_configurations; + } + + inline base::TypedConfigurations* typedConfigurations(void) { + return m_typedConfigurations; + } + + static inline bool isValidId(const std::string& id) { + for (std::string::const_iterator it = id.begin(); it != id.end(); ++it) { + if (!base::utils::Str::contains(base::consts::kValidLoggerIdSymbols, *it)) { + return false; + } + } + return true; + } + /// @brief Flushes logger to sync all log files for all levels + inline void flush(void) { + ELPP_INTERNAL_INFO(3, "Flushing logger [" << m_id << "] all levels"); + base::threading::ScopedLock scopedLock(lock()); + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + flush(LevelHelper::castFromInt(lIndex), nullptr); + return false; + }); + } + + inline void flush(Level level, base::type::fstream_t* fs) { + if (fs == nullptr && m_typedConfigurations->toFile(level)) { + fs = m_typedConfigurations->fileStream(level); + } + if (fs != nullptr) { + fs->flush(); + m_unflushedCount.find(level)->second = 0; + } + } + + inline bool isFlushNeeded(Level level) { + return ++m_unflushedCount.find(level)->second >= m_typedConfigurations->logFlushThreshold(level); + } + + inline LogBuilder* logBuilder(void) const { + return m_logBuilder.get(); + } + + inline void setLogBuilder(const LogBuilderPtr& logBuilder) { + m_logBuilder = logBuilder; + } + + inline bool enabled(Level level) const { + return m_typedConfigurations->enabled(level); + } + +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED +# define LOGGER_LEVEL_WRITERS_SIGNATURES(FUNCTION_NAME)\ + template \ + inline void FUNCTION_NAME(const char*, const T&, const Args&...);\ + template \ + inline void FUNCTION_NAME(const T&); + + template + inline void verbose(int, const char*, const T&, const Args&...); + + template + inline void verbose(int, const T&); + + LOGGER_LEVEL_WRITERS_SIGNATURES(info) + LOGGER_LEVEL_WRITERS_SIGNATURES(debug) + LOGGER_LEVEL_WRITERS_SIGNATURES(warn) + LOGGER_LEVEL_WRITERS_SIGNATURES(error) + LOGGER_LEVEL_WRITERS_SIGNATURES(fatal) + LOGGER_LEVEL_WRITERS_SIGNATURES(trace) +# undef LOGGER_LEVEL_WRITERS_SIGNATURES +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED + private: + std::string m_id; + base::TypedConfigurations* m_typedConfigurations; + base::type::stringstream_t m_stream; + std::string m_parentApplicationName; + bool m_isConfigured; + Configurations m_configurations; + std::map m_unflushedCount; + base::LogStreamsReferenceMap* m_logStreamsReference; + LogBuilderPtr m_logBuilder; + + friend class el::LogMessage; + friend class el::Loggers; + friend class el::Helpers; + friend class el::base::RegisteredLoggers; + friend class el::base::DefaultLogDispatchCallback; + friend class el::base::MessageBuilder; + friend class el::base::Writer; + friend class el::base::PErrorWriter; + friend class el::base::Storage; + friend class el::base::PerformanceTracker; + friend class el::base::LogDispatcher; + + Logger(void); + +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED + template + void log_(Level, int, const char*, const T&, const Args&...); + + template + inline void log_(Level, int, const T&); + + template + void log(Level, const char*, const T&, const Args&...); + + template + inline void log(Level, const T&); +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED + + void initUnflushedCount(void) { + m_unflushedCount.clear(); + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + m_unflushedCount.insert(std::make_pair(LevelHelper::castFromInt(lIndex), 0)); + return false; + }); + } + + inline base::type::stringstream_t& stream(void) { + return m_stream; + } + + void resolveLoggerFormatSpec(void) const { + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + base::LogFormat* logFormat = + const_cast(&m_typedConfigurations->logFormat(LevelHelper::castFromInt(lIndex))); + base::utils::Str::replaceFirstWithEscape(logFormat->m_format, base::consts::kLoggerIdFormatSpecifier, m_id); + return false; + }); + } + }; + namespace base { + /// @brief Loggers repository + class RegisteredLoggers : public base::utils::Registry { + public: + explicit RegisteredLoggers(const LogBuilderPtr& defaultLogBuilder) : + m_defaultLogBuilder(defaultLogBuilder) { + m_defaultConfigurations.setToDefault(); + } + + virtual ~RegisteredLoggers(void) { + flushAll(); + } + + inline void setDefaultConfigurations(const Configurations& configurations) { + base::threading::ScopedLock scopedLock(lock()); + m_defaultConfigurations.setFromBase(const_cast(&configurations)); + } + + inline Configurations* defaultConfigurations(void) { + return &m_defaultConfigurations; + } + + Logger* get(const std::string& id, bool forceCreation = true) { + base::threading::ScopedLock scopedLock(lock()); + Logger* logger_ = base::utils::Registry::get(id); + if (logger_ == nullptr && forceCreation) { + bool validId = Logger::isValidId(id); + if (!validId) { + ELPP_ASSERT(validId, "Invalid logger ID [" << id << "]. Not registering this logger."); + return nullptr; + } + logger_ = new Logger(id, m_defaultConfigurations, &m_logStreamsReference); + logger_->m_logBuilder = m_defaultLogBuilder; + registerNew(id, logger_); + } + return logger_; + } + + bool remove(const std::string& id) { + if (id == "default") { + return false; + } + Logger* logger = base::utils::Registry::get(id); + if (logger != nullptr) { + unregister(logger); + } + return true; + } + + inline bool has(const std::string& id) { + return get(id, false) != nullptr; + } + + inline void unregister(Logger*& logger) { + base::threading::ScopedLock scopedLock(lock()); + base::utils::Registry::unregister(logger->id()); + } + + inline base::LogStreamsReferenceMap* logStreamsReference(void) { + return &m_logStreamsReference; + } + + inline void flushAll(void) { + ELPP_INTERNAL_INFO(1, "Flushing all log files"); + base::threading::ScopedLock scopedLock(lock()); + for (base::LogStreamsReferenceMap::iterator it = m_logStreamsReference.begin(); + it != m_logStreamsReference.end(); ++it) { + if (it->second.get() == nullptr) continue; + it->second->flush(); + } + } + + private: + LogBuilderPtr m_defaultLogBuilder; + Configurations m_defaultConfigurations; + base::LogStreamsReferenceMap m_logStreamsReference; + friend class el::base::Storage; + }; + /// @brief Represents registries for verbose logging + class VRegistry : base::NoCopy, public base::threading::ThreadSafe { + public: + explicit VRegistry(base::type::VerboseLevel level, base::type::EnumType* pFlags) : m_level(level), m_pFlags(pFlags) { + } + + /// @brief Sets verbose level. Accepted range is 0-9 + inline void setLevel(base::type::VerboseLevel level) { + base::threading::ScopedLock scopedLock(lock()); + if (level < 0) + m_level = 0; + else if (level > 9) + m_level = base::consts::kMaxVerboseLevel; + else + m_level = level; + } + + inline base::type::VerboseLevel level(void) const { + return m_level; + } + + inline void clearModules(void) { + base::threading::ScopedLock scopedLock(lock()); + m_modules.clear(); + } + + void setModules(const char* modules) { + base::threading::ScopedLock scopedLock(lock()); + auto addSuffix = [](std::stringstream& ss, const char* sfx, const char* prev) { + if (prev != nullptr && base::utils::Str::endsWith(ss.str(), std::string(prev))) { + std::string chr(ss.str().substr(0, ss.str().size() - strlen(prev))); + ss.str(std::string("")); + ss << chr; + } + if (base::utils::Str::endsWith(ss.str(), std::string(sfx))) { + std::string chr(ss.str().substr(0, ss.str().size() - strlen(sfx))); + ss.str(std::string("")); + ss << chr; + } + ss << sfx; + }; + auto insert = [&](std::stringstream& ss, base::type::VerboseLevel level) { + if (!base::utils::hasFlag(LoggingFlag::DisableVModulesExtensions, *m_pFlags)) { + addSuffix(ss, ".h", nullptr); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".c", ".h"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".cpp", ".c"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".cc", ".cpp"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".cxx", ".cc"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".-inl.h", ".cxx"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".hxx", ".-inl.h"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".hpp", ".hxx"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".hh", ".hpp"); + } + m_modules.insert(std::make_pair(ss.str(), level)); + }; + bool isMod = true; + bool isLevel = false; + std::stringstream ss; + int level = -1; + for (; *modules; ++modules) { + switch (*modules) { + case '=': + isLevel = true; + isMod = false; + break; + case ',': + isLevel = false; + isMod = true; + if (!ss.str().empty() && level != -1) { + insert(ss, level); + ss.str(std::string("")); + level = -1; + } + break; + default: + if (isMod) { + ss << *modules; + } + else if (isLevel) { + if (isdigit(*modules)) { + level = static_cast(*modules) - 48; + } + } + break; + } + } + if (!ss.str().empty() && level != -1) { + insert(ss, level); + } + } + + bool allowed(base::type::VerboseLevel vlevel, const char* file) { + base::threading::ScopedLock scopedLock(lock()); + if (m_modules.empty() || file == nullptr) { + return vlevel <= m_level; + } + else { + std::map::iterator it = m_modules.begin(); + for (; it != m_modules.end(); ++it) { + if (base::utils::Str::wildCardMatch(file, it->first.c_str())) { + return vlevel <= it->second; + } + } + if (base::utils::hasFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified, *m_pFlags)) { + return true; + } + return false; + } + } + + inline const std::map& modules(void) const { + return m_modules; + } + + void setFromArgs(const base::utils::CommandLineArgs* commandLineArgs) { + if (commandLineArgs->hasParam("-v") || commandLineArgs->hasParam("--verbose") || + commandLineArgs->hasParam("-V") || commandLineArgs->hasParam("--VERBOSE")) { + setLevel(base::consts::kMaxVerboseLevel); + } + else if (commandLineArgs->hasParamWithValue("--v")) { + setLevel(atoi(commandLineArgs->getParamValue("--v"))); + } + else if (commandLineArgs->hasParamWithValue("--V")) { + setLevel(atoi(commandLineArgs->getParamValue("--V"))); + } + else if ((commandLineArgs->hasParamWithValue("-vmodule")) && vModulesEnabled()) { + setModules(commandLineArgs->getParamValue("-vmodule")); + } + else if (commandLineArgs->hasParamWithValue("-VMODULE") && vModulesEnabled()) { + setModules(commandLineArgs->getParamValue("-VMODULE")); + } + } + + /// @brief Whether or not vModules enabled + inline bool vModulesEnabled(void) { + return !base::utils::hasFlag(LoggingFlag::DisableVModules, *m_pFlags); + } + + private: + base::type::VerboseLevel m_level; + base::type::EnumType* m_pFlags; + std::map m_modules; + }; + } // namespace base + class LogMessage { + public: + LogMessage(Level level, const std::string& file, unsigned long int line, const std::string& func, + base::type::VerboseLevel verboseLevel, Logger* logger) : + m_level(level), m_file(file), m_line(line), m_func(func), + m_verboseLevel(verboseLevel), m_logger(logger), m_message(std::move(logger->stream().str())) { + } + inline Level level(void) const { return m_level; } + inline const std::string& file(void) const { return m_file; } + inline unsigned long int line(void) const { return m_line; } // NOLINT + inline const std::string& func(void) const { return m_func; } + inline base::type::VerboseLevel verboseLevel(void) const { return m_verboseLevel; } + inline Logger* logger(void) const { return m_logger; } + inline const base::type::string_t& message(void) const { return m_message; } + private: + Level m_level; + std::string m_file; + unsigned long int m_line; + std::string m_func; + base::type::VerboseLevel m_verboseLevel; + Logger* m_logger; + base::type::string_t m_message; + }; + namespace base { +#if ELPP_ASYNC_LOGGING + class AsyncLogItem { + public: + explicit AsyncLogItem(const LogMessage& logMessage, const LogDispatchData& data, const base::type::string_t& logLine) + : m_logMessage(logMessage), m_dispatchData(data), m_logLine(logLine) {} + virtual ~AsyncLogItem() {} + inline LogMessage* logMessage(void) { return &m_logMessage; } + inline LogDispatchData* data(void) { return &m_dispatchData; } + inline base::type::string_t logLine(void) { return m_logLine; } + private: + LogMessage m_logMessage; + LogDispatchData m_dispatchData; + base::type::string_t m_logLine; + }; + class AsyncLogQueue : public base::threading::ThreadSafe { + public: + virtual ~AsyncLogQueue() { + ELPP_INTERNAL_INFO(6, "~AsyncLogQueue"); + } + + inline AsyncLogItem next(void) { + base::threading::ScopedLock scopedLock(lock()); + AsyncLogItem result = m_queue.front(); + m_queue.pop(); + return result; + } + + inline void push(const AsyncLogItem& item) { + base::threading::ScopedLock scopedLock(lock()); + m_queue.push(item); + } + inline void pop(void) { + base::threading::ScopedLock scopedLock(lock()); + m_queue.pop(); + } + inline AsyncLogItem front(void) { + base::threading::ScopedLock scopedLock(lock()); + return m_queue.front(); + } + inline bool empty(void) { + base::threading::ScopedLock scopedLock(lock()); + return m_queue.empty(); + } + private: + std::queue m_queue; + }; + class IWorker { + public: + virtual ~IWorker() {} + virtual void start() = 0; + }; +#endif // ELPP_ASYNC_LOGGING + /// @brief Easylogging++ management storage + class Storage : base::NoCopy, public base::threading::ThreadSafe { + public: +#if ELPP_ASYNC_LOGGING + Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker) : +#else + explicit Storage(const LogBuilderPtr& defaultLogBuilder) : +#endif // ELPP_ASYNC_LOGGING + m_registeredHitCounters(new base::RegisteredHitCounters()), + m_registeredLoggers(new base::RegisteredLoggers(defaultLogBuilder)), + m_flags(0x0), + m_vRegistry(new base::VRegistry(0, &m_flags)), +#if ELPP_ASYNC_LOGGING + m_asyncLogQueue(new base::AsyncLogQueue()), + m_asyncDispatchWorker(asyncDispatchWorker), +#endif // ELPP_ASYNC_LOGGING + m_preRollOutCallback(base::defaultPreRollOutCallback) { + // Register default logger + m_registeredLoggers->get(std::string(base::consts::kDefaultLoggerId)); + // Register performance logger and reconfigure format + Logger* performanceLogger = m_registeredLoggers->get(std::string(base::consts::kPerformanceLoggerId)); + performanceLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%datetime %level %msg")); + performanceLogger->reconfigure(); +#if defined(ELPP_SYSLOG) + // Register syslog logger and reconfigure format + Logger* sysLogLogger = m_registeredLoggers->get(std::string(base::consts::kSysLogLoggerId)); + sysLogLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%level: %msg")); + sysLogLogger->reconfigure(); +#else + ELPP_UNUSED(base::consts::kSysLogLoggerId); +#endif // defined(ELPP_SYSLOG) + addFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified); +#if ELPP_ASYNC_LOGGING + installLogDispatchCallback(std::string("AsyncLogDispatchCallback")); +#else + installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); +#endif // ELPP_ASYNC_LOGGING + installPerformanceTrackingCallback(std::string("DefaultPerformanceTrackingCallback")); + ELPP_INTERNAL_INFO(1, "Easylogging++ has been initialized"); +#if ELPP_ASYNC_LOGGING + m_asyncDispatchWorker->start(); +#endif // ELPP_ASYNC_LOGGING + } + + virtual ~Storage(void) { + ELPP_INTERNAL_INFO(4, "Destroying storage"); +#if ELPP_ASYNC_LOGGING + ELPP_INTERNAL_INFO(5, "Replacing log dispatch callback to synchronous"); + uninstallLogDispatchCallback(std::string("AsyncLogDispatchCallback")); + installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); + ELPP_INTERNAL_INFO(5, "Destroying asyncDispatchWorker"); + base::utils::safeDelete(m_asyncDispatchWorker); + ELPP_INTERNAL_INFO(5, "Destroying asyncLogQueue"); + base::utils::safeDelete(m_asyncLogQueue); +#endif // ELPP_ASYNC_LOGGING + ELPP_INTERNAL_INFO(5, "Destroying registeredHitCounters"); + base::utils::safeDelete(m_registeredHitCounters); + ELPP_INTERNAL_INFO(5, "Destroying registeredLoggers"); + base::utils::safeDelete(m_registeredLoggers); + ELPP_INTERNAL_INFO(5, "Destroying vRegistry"); + base::utils::safeDelete(m_vRegistry); + } + + inline bool validateEveryNCounter(const char* filename, unsigned long int lineNumber, std::size_t occasion) { + return hitCounters()->validateEveryN(filename, lineNumber, occasion); + } + + inline bool validateAfterNCounter(const char* filename, unsigned long int lineNumber, std::size_t n) { // NOLINT + return hitCounters()->validateAfterN(filename, lineNumber, n); + } + + inline bool validateNTimesCounter(const char* filename, unsigned long int lineNumber, std::size_t n) { // NOLINT + return hitCounters()->validateNTimes(filename, lineNumber, n); + } + + inline base::RegisteredHitCounters* hitCounters(void) const { + return m_registeredHitCounters; + } + + inline base::RegisteredLoggers* registeredLoggers(void) const { + return m_registeredLoggers; + } + + inline base::VRegistry* vRegistry(void) const { + return m_vRegistry; + } + +#if ELPP_ASYNC_LOGGING + inline base::AsyncLogQueue* asyncLogQueue(void) const { + return m_asyncLogQueue; + } +#endif // ELPP_ASYNC_LOGGING + + inline const base::utils::CommandLineArgs* commandLineArgs(void) const { + return &m_commandLineArgs; + } + + inline void addFlag(LoggingFlag flag) { + base::utils::addFlag(flag, &m_flags); + } + + inline void removeFlag(LoggingFlag flag) { + base::utils::removeFlag(flag, &m_flags); + } + + inline bool hasFlag(LoggingFlag flag) const { + return base::utils::hasFlag(flag, m_flags); + } + + inline base::type::EnumType flags(void) const { + return m_flags; + } + + inline void setFlags(base::type::EnumType flags) { + m_flags = flags; + } + + inline void setPreRollOutCallback(const PreRollOutCallback& callback) { + m_preRollOutCallback = callback; + } + + inline void unsetPreRollOutCallback(void) { + m_preRollOutCallback = base::defaultPreRollOutCallback; + } + + inline PreRollOutCallback& preRollOutCallback(void) { + return m_preRollOutCallback; + } + + inline bool hasCustomFormatSpecifier(const char* formatSpecifier) { + base::threading::ScopedLock scopedLock(lock()); + return std::find(m_customFormatSpecifiers.begin(), m_customFormatSpecifiers.end(), + formatSpecifier) != m_customFormatSpecifiers.end(); + } + + inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { + if (hasCustomFormatSpecifier(customFormatSpecifier.formatSpecifier())) { + return; + } + base::threading::ScopedLock scopedLock(lock()); + m_customFormatSpecifiers.push_back(customFormatSpecifier); + } + + inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier) { + base::threading::ScopedLock scopedLock(lock()); + std::vector::iterator it = std::find(m_customFormatSpecifiers.begin(), + m_customFormatSpecifiers.end(), formatSpecifier); + if (it != m_customFormatSpecifiers.end() && strcmp(formatSpecifier, it->formatSpecifier()) == 0) { + m_customFormatSpecifiers.erase(it); + return true; + } + return false; + } + + const std::vector* customFormatSpecifiers(void) const { + return &m_customFormatSpecifiers; + } + + inline void setLoggingLevel(Level level) { + m_loggingLevel = level; + } + + template + inline bool installLogDispatchCallback(const std::string& id) { + return installCallback(id, &m_logDispatchCallbacks); + } + + template + inline void uninstallLogDispatchCallback(const std::string& id) { + uninstallCallback(id, &m_logDispatchCallbacks); + } + template + inline T* logDispatchCallback(const std::string& id) { + return callback(id, &m_logDispatchCallbacks); + } + + template + inline bool installPerformanceTrackingCallback(const std::string& id) { + return installCallback(id, &m_performanceTrackingCallbacks); + } + + template + inline void uninstallPerformanceTrackingCallback(const std::string& id) { + uninstallCallback(id, &m_performanceTrackingCallbacks); + } + + template + inline T* performanceTrackingCallback(const std::string& id) { + return callback(id, &m_performanceTrackingCallbacks); + } + private: + base::RegisteredHitCounters* m_registeredHitCounters; + base::RegisteredLoggers* m_registeredLoggers; + base::type::EnumType m_flags; + base::VRegistry* m_vRegistry; +#if ELPP_ASYNC_LOGGING + base::AsyncLogQueue* m_asyncLogQueue; + base::IWorker* m_asyncDispatchWorker; +#endif // ELPP_ASYNC_LOGGING + base::utils::CommandLineArgs m_commandLineArgs; + PreRollOutCallback m_preRollOutCallback; + std::map m_logDispatchCallbacks; + std::map m_performanceTrackingCallbacks; + std::vector m_customFormatSpecifiers; + Level m_loggingLevel; + + friend class el::Helpers; + friend class el::base::DefaultLogDispatchCallback; + friend class el::LogBuilder; + friend class el::base::MessageBuilder; + friend class el::base::Writer; + friend class el::base::PerformanceTracker; + friend class el::base::LogDispatcher; + + void setApplicationArguments(int argc, char** argv) { + m_commandLineArgs.setArgs(argc, argv); + m_vRegistry->setFromArgs(commandLineArgs()); + // default log file +#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) + if (m_commandLineArgs.hasParamWithValue(base::consts::kDefaultLogFileParam)) { + Configurations c; + c.setGlobally(ConfigurationType::Filename, std::string(m_commandLineArgs.getParamValue(base::consts::kDefaultLogFileParam))); + registeredLoggers()->setDefaultConfigurations(c); + for (base::RegisteredLoggers::iterator it = registeredLoggers()->begin(); + it != registeredLoggers()->end(); ++it) { + it->second->configure(c); + } + } +#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) +#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) + if (m_commandLineArgs.hasParamWithValue(base::consts::kLoggingFlagsParam)) { + m_flags = atoi(m_commandLineArgs.getParamValue(base::consts::kLoggingFlagsParam)); + } +#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) + } + + inline void setApplicationArguments(int argc, const char** argv) { + setApplicationArguments(argc, const_cast(argv)); + } + + template + inline bool installCallback(const std::string& id, std::map* mapT) { + if (mapT->find(id) == mapT->end()) { + mapT->insert(std::make_pair(id, TPtr(new T()))); + return true; + } + return false; + } + + template + inline void uninstallCallback(const std::string& id, std::map* mapT) { + if (mapT->find(id) != mapT->end()) { + mapT->erase(id); + } + } + + template + inline T* callback(const std::string& id, std::map* mapT) { + typename std::map::iterator iter = mapT->find(id); + if (iter != mapT->end()) { + return static_cast(iter->second.get()); + } + return nullptr; + } + }; + extern ELPP_EXPORT base::type::StoragePointer elStorage; +#define ELPP el::base::elStorage + class DefaultLogDispatchCallback : public LogDispatchCallback { + protected: + void handle(const LogDispatchData* data) { + m_data = data; + dispatch(std::move(m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(), + m_data->dispatchAction() == base::DispatchAction::NormalLog))); + } + private: + const LogDispatchData* m_data; + void dispatch(base::type::string_t&& logLine) { + if (m_data->dispatchAction() == base::DispatchAction::NormalLog) { + if (m_data->logMessage()->logger()->m_typedConfigurations->toFile(m_data->logMessage()->level())) { + base::type::fstream_t* fs = m_data->logMessage()->logger()->m_typedConfigurations->fileStream(m_data->logMessage()->level()); + if (fs != nullptr) { + fs->write(logLine.c_str(), logLine.size()); + if (fs->fail()) { + ELPP_INTERNAL_ERROR("Unable to write log to file [" + << m_data->logMessage()->logger()->m_typedConfigurations->filename(m_data->logMessage()->level()) << "].\n" + << "Few possible reasons (could be something else):\n" << " * Permission denied\n" + << " * Disk full\n" << " * Disk is not writable", true); + } + else { + if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (m_data->logMessage()->logger()->isFlushNeeded(m_data->logMessage()->level()))) { + m_data->logMessage()->logger()->flush(m_data->logMessage()->level(), fs); + } + } + } + else { + ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(m_data->logMessage()->level()) << "] " + << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " + << m_data->logMessage()->logger()->id() << "]", false); + } + } + if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) { + if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) + m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, m_data->logMessage()->level()); + ELPP_COUT << ELPP_COUT_LINE(logLine); + } + } +#if defined(ELPP_SYSLOG) + else if (m_data->dispatchAction() == base::DispatchAction::SysLog) { + // Determine syslog priority + int sysLogPriority = 0; + if (m_data->logMessage()->level() == Level::Fatal) + sysLogPriority = LOG_EMERG; + else if (m_data->logMessage()->level() == Level::Error) + sysLogPriority = LOG_ERR; + else if (m_data->logMessage()->level() == Level::Warning) + sysLogPriority = LOG_WARNING; + else if (m_data->logMessage()->level() == Level::Info) + sysLogPriority = LOG_INFO; + else if (m_data->logMessage()->level() == Level::Debug) + sysLogPriority = LOG_DEBUG; + else + sysLogPriority = LOG_NOTICE; +# if defined(ELPP_UNICODE) + char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); + syslog(sysLogPriority, "%s", line); + free(line); +# else + syslog(sysLogPriority, "%s", logLine.c_str()); +# endif + } +#endif // defined(ELPP_SYSLOG) + } + }; +#if ELPP_ASYNC_LOGGING + class AsyncLogDispatchCallback : public LogDispatchCallback { + protected: + void handle(const LogDispatchData* data) { + base::type::string_t logLine = data->logMessage()->logger()->logBuilder()->build(data->logMessage(), data->dispatchAction() == base::DispatchAction::NormalLog); + if (data->dispatchAction() == base::DispatchAction::NormalLog && data->logMessage()->logger()->typedConfigurations()->toStandardOutput(data->logMessage()->level())) { + if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) + data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, data->logMessage()->level()); + ELPP_COUT << ELPP_COUT_LINE(logLine); + } + // Save resources and only queue if we want to write to file otherwise just ignore handler + if (data->logMessage()->logger()->typedConfigurations()->toFile(data->logMessage()->level())) { + ELPP->asyncLogQueue()->push(AsyncLogItem(*(data->logMessage()), *data, logLine)); + } + } + }; + class AsyncDispatchWorker : public base::IWorker, public base::threading::ThreadSafe { + public: + AsyncDispatchWorker() { + setContinueRunning(false); + } + + virtual ~AsyncDispatchWorker() { + setContinueRunning(false); + ELPP_INTERNAL_INFO(6, "Stopping dispatch worker - Cleaning log queue"); + clean(); + ELPP_INTERNAL_INFO(6, "Log queue cleaned"); + } + + inline bool clean() { + std::mutex m; + std::unique_lock lk(m); + cv.wait(lk, [] { return !ELPP->asyncLogQueue()->empty(); }); + emptyQueue(); + lk.unlock(); + cv.notify_one(); + return ELPP->asyncLogQueue()->empty(); + } + + inline void emptyQueue() { + while (!ELPP->asyncLogQueue()->empty()) { + AsyncLogItem data = ELPP->asyncLogQueue()->next(); + handle(&data); + base::threading::msleep(100); + } + } + + virtual inline void start() { + base::threading::msleep(5000); // Wait extra few seconds + setContinueRunning(true); + std::thread t1(&AsyncDispatchWorker::runner, this); + t1.join(); + } + + void handle(AsyncLogItem* logItem) { + LogDispatchData* data = logItem->data(); + LogMessage* logMessage = logItem->logMessage(); + Logger* logger = logMessage->logger(); + base::TypedConfigurations* conf = logger->typedConfigurations(); + base::type::string_t logLine = logItem->logLine(); + if (data->dispatchAction() == base::DispatchAction::NormalLog) { + if (conf->toFile(logMessage->level())) { + base::type::fstream_t* fs = conf->fileStream(logMessage->level()); + if (fs != nullptr) { + fs->write(logLine.c_str(), logLine.size()); + if (fs->fail()) { + ELPP_INTERNAL_ERROR("Unable to write log to file [" + << conf->filename(logMessage->level()) << "].\n" + << "Few possible reasons (could be something else):\n" << " * Permission denied\n" + << " * Disk full\n" << " * Disk is not writable", true); + } + else { + if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (logger->isFlushNeeded(logMessage->level()))) { + logger->flush(logMessage->level(), fs); + } + } + } + else { + ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(logMessage->level()) << "] " + << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " << logger->id() << "]", false); + } + } + } +# if defined(ELPP_SYSLOG) + else if (data->dispatchAction() == base::DispatchAction::SysLog) { + // Determine syslog priority + int sysLogPriority = 0; + if (logMessage->level() == Level::Fatal) + sysLogPriority = LOG_EMERG; + else if (logMessage->level() == Level::Error) + sysLogPriority = LOG_ERR; + else if (logMessage->level() == Level::Warning) + sysLogPriority = LOG_WARNING; + else if (logMessage->level() == Level::Info) + sysLogPriority = LOG_INFO; + else if (logMessage->level() == Level::Debug) + sysLogPriority = LOG_DEBUG; + else + sysLogPriority = LOG_NOTICE; +# if defined(ELPP_UNICODE) + char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); + syslog(sysLogPriority, "%s", line); + free(line); +# else + syslog(sysLogPriority, "%s", logLine.c_str()); +# endif + } +# endif // defined(ELPP_SYSLOG) + } + + void run() { + while (continueRunning()) { + emptyQueue(); + base::threading::msleep(10); // 10ms + } + } + + static void* runner(void *context) { + static_cast(context)->run(); + return NULL; + } + + void setContinueRunning(bool value) { + base::threading::ScopedLock scopedLock(m_continueRunningMutex); + m_continueRunning = value; + } + bool continueRunning(void) { + return m_continueRunning; + } + private: + std::condition_variable cv; + bool m_continueRunning; + base::threading::Mutex m_continueRunningMutex; + }; +#endif // ELPP_ASYNC_LOGGING + } // namespace base + namespace base { + class DefaultLogBuilder : public LogBuilder { + public: + base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const { + base::TypedConfigurations* tc = logMessage->logger()->typedConfigurations(); + const base::LogFormat* logFormat = &tc->logFormat(logMessage->level()); + base::type::string_t logLine = logFormat->format(); + char buff[base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength] = ""; + const char* bufLim = buff + sizeof(buff); + if (logFormat->hasFlag(base::FormatFlags::AppName)) { + // App name + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kAppNameFormatSpecifier, + logMessage->logger()->parentApplicationName()); + } + if (logFormat->hasFlag(base::FormatFlags::ThreadId)) { + // Thread ID + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kThreadIdFormatSpecifier, + base::threading::getCurrentThreadId()); + } + if (logFormat->hasFlag(base::FormatFlags::DateTime)) { + // DateTime + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kDateTimeFormatSpecifier, + base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(), + &tc->millisecondsWidth(logMessage->level()))); + } + if (logFormat->hasFlag(base::FormatFlags::Function)) { + // Function + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFunctionFormatSpecifier, logMessage->func()); + } + if (logFormat->hasFlag(base::FormatFlags::File)) { + // File + char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); + base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); + buf = base::utils::Str::addToBuff(buff, buf, bufLim); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::FileBase)) { + // FileBase + char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); + base::utils::File::buildBaseFilename(logMessage->file(), buff); + buf = base::utils::Str::addToBuff(buff, buf, bufLim); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileBaseFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::Line)) { + // Line + char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceLineMaxLength); + buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), + base::consts::kSourceLineMaxLength, buf, bufLim, false); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLineFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::Location)) { + // Location + char* buf = base::utils::Str::clearBuff(buff, + base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength); + base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); + buf = base::utils::Str::addToBuff(buff, buf, bufLim); + buf = base::utils::Str::addToBuff(":", buf, bufLim); + buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), + base::consts::kSourceLineMaxLength, buf, bufLim, false); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLocationFormatSpecifier, std::string(buff)); + } + if (logMessage->level() == Level::Verbose && logFormat->hasFlag(base::FormatFlags::VerboseLevel)) { + // Verbose level + char* buf = base::utils::Str::clearBuff(buff, 1); + buf = base::utils::Str::convertAndAddToBuff(logMessage->verboseLevel(), 1, buf, bufLim, false); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kVerboseLevelFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::LogMessage)) { + // Log message + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kMessageFormatSpecifier, logMessage->message()); + } +#if !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) + for (std::vector::const_iterator it = ELPP->customFormatSpecifiers()->begin(); + it != ELPP->customFormatSpecifiers()->end(); ++it) { + std::string fs(it->formatSpecifier()); + base::type::string_t wcsFormatSpecifier(fs.begin(), fs.end()); + base::utils::Str::replaceFirstWithEscape(logLine, wcsFormatSpecifier, std::string(it->resolver()())); + } +#endif // !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) + if (appendNewLine) logLine += ELPP_LITERAL("\n"); + return logLine; + } + }; + /// @brief Dispatches log messages + class LogDispatcher : base::NoCopy { + public: + LogDispatcher(bool proceed, LogMessage&& logMessage, base::DispatchAction dispatchAction) : + m_proceed(proceed), + m_logMessage(std::move(logMessage)), + m_dispatchAction(std::move(dispatchAction)) { + } + + void dispatch(void) { + if (m_proceed && m_dispatchAction == base::DispatchAction::None) { + m_proceed = false; + } + if (!m_proceed) { + return; + } + // We minimize the time of ELPP's lock - this lock is released after log is written + base::threading::ScopedLock scopedLock(ELPP->lock()); + base::TypedConfigurations* tc = m_logMessage.logger()->m_typedConfigurations; + if (ELPP->hasFlag(LoggingFlag::StrictLogFileSizeCheck)) { + tc->validateFileRolling(m_logMessage.level(), ELPP->preRollOutCallback()); + } + LogDispatchCallback* callback = nullptr; + LogDispatchData data; + for (const std::pair& h + : ELPP->m_logDispatchCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + data.setLogMessage(&m_logMessage); + data.setDispatchAction(m_dispatchAction); + callback->acquireLock(); + callback->handle(&data); + callback->releaseLock(); + } + } + } + + private: + bool m_proceed; + LogMessage m_logMessage; + base::DispatchAction m_dispatchAction; + }; +#if defined(ELPP_STL_LOGGING) + /// @brief Workarounds to write some STL logs + /// + /// @detail There is workaround needed to loop through some stl containers. In order to do that, we need iterable containers + /// of same type and provide iterator interface and pass it on to writeIterator(). + /// Remember, this is passed by value in constructor so that we dont change original containers. + /// This operation is as expensive as Big-O(std::min(class_.size(), base::consts::kMaxLogPerContainer)) + namespace workarounds { + /// @brief Abstract IterableContainer template that provides interface for iterable classes of type T + template + class IterableContainer { + public: + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + IterableContainer(void) {} + virtual ~IterableContainer(void) {} + iterator begin(void) { return getContainer().begin(); } + iterator end(void) { return getContainer().end(); } + private: + virtual Container& getContainer(void) = 0; + }; + /// @brief Implements IterableContainer and provides iterable std::priority_queue class + template, typename Comparator = std::less> + class IterablePriorityQueue : public IterableContainer, public std::priority_queue { + public: + IterablePriorityQueue(std::priority_queue queue_) { + std::size_t count_ = 0; + while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { + this->push(queue_.top()); + queue_.pop(); + } + } + private: + inline Container& getContainer(void) { + return this->c; + } + }; + /// @brief Implements IterableContainer and provides iterable std::queue class + template> + class IterableQueue : public IterableContainer, public std::queue { + public: + IterableQueue(std::queue queue_) { + std::size_t count_ = 0; + while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { + this->push(queue_.front()); + queue_.pop(); + } + } + private: + inline Container& getContainer(void) { + return this->c; + } + }; + /// @brief Implements IterableContainer and provides iterable std::stack class + template> + class IterableStack : public IterableContainer, public std::stack { + public: + IterableStack(std::stack stack_) { + std::size_t count_ = 0; + while (++count_ < base::consts::kMaxLogPerContainer && !stack_.empty()) { + this->push(stack_.top()); + stack_.pop(); + } + } + private: + inline Container& getContainer(void) { + return this->c; + } + }; + } // namespace workarounds +#endif // defined(ELPP_STL_LOGGING) + // Log message builder + class MessageBuilder { + public: + MessageBuilder(void) : m_logger(nullptr), m_containerLogSeperator(ELPP_LITERAL("")) {} + void initialize(Logger* logger) { + m_logger = logger; + m_containerLogSeperator = ELPP->hasFlag(LoggingFlag::NewLineForContainer) ? + ELPP_LITERAL("\n ") : ELPP_LITERAL(", "); + } + +# define ELPP_SIMPLE_LOG(LOG_TYPE)\ + inline MessageBuilder& operator<<(LOG_TYPE msg) {\ + m_logger->stream() << msg;\ + if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) {\ + m_logger->stream() << " ";\ + }\ + return *this;\ + } + + inline MessageBuilder& operator<<(const std::string& msg) { + return operator<<(msg.c_str()); + } + ELPP_SIMPLE_LOG(char) + ELPP_SIMPLE_LOG(bool) + ELPP_SIMPLE_LOG(signed short) + ELPP_SIMPLE_LOG(unsigned short) + ELPP_SIMPLE_LOG(signed int) + ELPP_SIMPLE_LOG(unsigned int) + ELPP_SIMPLE_LOG(signed long) + ELPP_SIMPLE_LOG(unsigned long) + ELPP_SIMPLE_LOG(float) + ELPP_SIMPLE_LOG(double) + ELPP_SIMPLE_LOG(char*) + ELPP_SIMPLE_LOG(const char*) + ELPP_SIMPLE_LOG(const void*) + ELPP_SIMPLE_LOG(long double) + inline MessageBuilder& operator<<(const std::wstring& msg) { + return operator<<(msg.c_str()); + } + inline MessageBuilder& operator<<(const wchar_t* msg) { + if (msg == nullptr) { + m_logger->stream() << base::consts::kNullPointer; + return *this; + } +# if defined(ELPP_UNICODE) + m_logger->stream() << msg; +# else + char* buff_ = base::utils::Str::wcharPtrToCharPtr(msg); + m_logger->stream() << buff_; + free(buff_); +# endif + if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { + m_logger->stream() << " "; + } + return *this; + } + // ostream manipulators + inline MessageBuilder& operator<<(std::ostream& (*OStreamMani)(std::ostream&)) { + m_logger->stream() << OStreamMani; + return *this; + } +#define ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(temp) \ + template \ + inline MessageBuilder& operator<<(const temp& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } +#define ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(temp) \ + template \ + inline MessageBuilder& operator<<(const temp& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } +#define ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(temp) \ + template \ + inline MessageBuilder& operator<<(const temp& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } +#define ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(temp) \ + template \ + inline MessageBuilder& operator<<(const temp& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } +#define ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(temp) \ + template \ + inline MessageBuilder& operator<<(const temp& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } + +#if defined(ELPP_STL_LOGGING) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::vector) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::list) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::deque) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::set) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::multiset) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::map) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::multimap) + template + inline MessageBuilder& operator<<(const std::queue& queue_) { + base::workarounds::IterableQueue iterableQueue_ = + static_cast >(queue_); + return writeIterator(iterableQueue_.begin(), iterableQueue_.end(), iterableQueue_.size()); + } + template + inline MessageBuilder& operator<<(const std::stack& stack_) { + base::workarounds::IterableStack iterableStack_ = + static_cast >(stack_); + return writeIterator(iterableStack_.begin(), iterableStack_.end(), iterableStack_.size()); + } + template + inline MessageBuilder& operator<<(const std::priority_queue& priorityQueue_) { + base::workarounds::IterablePriorityQueue iterablePriorityQueue_ = + static_cast >(priorityQueue_); + return writeIterator(iterablePriorityQueue_.begin(), iterablePriorityQueue_.end(), iterablePriorityQueue_.size()); + } + template + inline MessageBuilder& operator<<(const std::pair& pair_) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast(pair_.first)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast(pair_.second)); + m_logger->stream() << ELPP_LITERAL(")"); + return *this; + } + template + inline MessageBuilder& operator<<(const std::bitset& bitset_) { + m_logger->stream() << ELPP_LITERAL("["); + operator << (bitset_.to_string()); + m_logger->stream() << ELPP_LITERAL("]"); + return *this; + } +# if defined(ELPP_LOG_STD_ARRAY) + template + inline MessageBuilder& operator<<(const std::array& array) { + return writeIterator(array.begin(), array.end(), array.size()); + } +# endif // defined(ELPP_LOG_STD_ARRAY) +# if defined(ELPP_LOG_UNORDERED_MAP) + ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_map) + ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_multimap) +# endif // defined(ELPP_LOG_UNORDERED_MAP) +# if defined(ELPP_LOG_UNORDERED_SET) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_set) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_multiset) +# endif // defined(ELPP_LOG_UNORDERED_SET) +#endif // defined(ELPP_STL_LOGGING) +#if defined(ELPP_QT_LOGGING) + inline MessageBuilder& operator<<(const QString& msg) { +# if defined(ELPP_UNICODE) + m_logger->stream() << msg.toStdWString(); +# else + m_logger->stream() << msg.toStdString(); +# endif // defined(ELPP_UNICODE) + return *this; + } + inline MessageBuilder& operator<<(const QByteArray& msg) { + return operator << (QString(msg)); + } + inline MessageBuilder& operator<<(const QStringRef& msg) { + return operator<<(msg.toString()); + } + inline MessageBuilder& operator<<(qint64 msg) { +# if defined(ELPP_UNICODE) + m_logger->stream() << QString::number(msg).toStdWString(); +# else + m_logger->stream() << QString::number(msg).toStdString(); +# endif // defined(ELPP_UNICODE) + return *this; + } + inline MessageBuilder& operator<<(quint64 msg) { +# if defined(ELPP_UNICODE) + m_logger->stream() << QString::number(msg).toStdWString(); +# else + m_logger->stream() << QString::number(msg).toStdString(); +# endif // defined(ELPP_UNICODE) + return *this; + } + inline MessageBuilder& operator<<(QChar msg) { + m_logger->stream() << msg.toLatin1(); + return *this; + } + inline MessageBuilder& operator<<(const QLatin1String& msg) { + m_logger->stream() << msg.latin1(); + return *this; + } + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QList) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QVector) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QQueue) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QSet) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QLinkedList) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QStack) + template + inline MessageBuilder& operator<<(const QPair& pair_) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast(pair_.first)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast(pair_.second)); + m_logger->stream() << ELPP_LITERAL(")"); + return *this; + } + template + inline MessageBuilder& operator<<(const QMap& map_) { + m_logger->stream() << ELPP_LITERAL("["); + QList keys = map_.keys(); + typename QList::const_iterator begin = keys.begin(); + typename QList::const_iterator end = keys.end(); + int max_ = static_cast(base::consts::kMaxLogPerContainer); // to prevent warning + for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast(*begin)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast(map_.value(*begin))); + m_logger->stream() << ELPP_LITERAL(")"); + m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); + } + if (begin != end) { + m_logger->stream() << ELPP_LITERAL("..."); + } + m_logger->stream() << ELPP_LITERAL("]"); + return *this; + } + template + inline MessageBuilder& operator<<(const QMultiMap& map_) { + operator << (static_cast>(map_)); + return *this; + } + template + inline MessageBuilder& operator<<(const QHash& hash_) { + m_logger->stream() << ELPP_LITERAL("["); + QList keys = hash_.keys(); + typename QList::const_iterator begin = keys.begin(); + typename QList::const_iterator end = keys.end(); + int max_ = static_cast(base::consts::kMaxLogPerContainer); // prevent type warning + for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast(*begin)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast(hash_.value(*begin))); + m_logger->stream() << ELPP_LITERAL(")"); + m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); + } + if (begin != end) { + m_logger->stream() << ELPP_LITERAL("..."); + } + m_logger->stream() << ELPP_LITERAL("]"); + return *this; + } + template + inline MessageBuilder& operator<<(const QMultiHash& multiHash_) { + operator << (static_cast>(multiHash_)); + return *this; + } +#endif // defined(ELPP_QT_LOGGING) +#if defined(ELPP_BOOST_LOGGING) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::vector) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::stable_vector) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::list) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::deque) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::map) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::flat_map) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::set) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::flat_set) +#endif // defined(ELPP_BOOST_LOGGING) + + /// @brief Macro used internally that can be used externally to make containers easylogging++ friendly + /// + /// @detail This macro expands to write an ostream& operator<< for container. This container is expected to + /// have begin() and end() methods that return respective iterators + /// @param ContainerType Type of container e.g, MyList from WX_DECLARE_LIST(int, MyList); in wxwidgets + /// @param SizeMethod Method used to get size of container. + /// @param ElementInstance Instance of element to be fed out. Insance name is "elem". See WXELPP_ENABLED macro + /// for an example usage +#define MAKE_CONTAINERELPP_FRIENDLY(ContainerType, SizeMethod, ElementInstance) \ + el::base::type::ostream_t& operator<<(el::base::type::ostream_t& ss, const ContainerType& container) {\ + const el::base::type::char_t* sep = ELPP->hasFlag(el::LoggingFlag::NewLineForContainer) ? \ + ELPP_LITERAL("\n ") : ELPP_LITERAL(", ");\ + ContainerType::const_iterator elem = container.begin();\ + ContainerType::const_iterator endElem = container.end();\ + std::size_t size_ = container.SizeMethod; \ + ss << ELPP_LITERAL("[");\ + for (std::size_t i = 0; elem != endElem && i < el::base::consts::kMaxLogPerContainer; ++i, ++elem) { \ + ss << ElementInstance;\ + ss << ((i < size_ - 1) ? sep : ELPP_LITERAL(""));\ + }\ + if (elem != endElem) {\ + ss << ELPP_LITERAL("...");\ + }\ + ss << ELPP_LITERAL("]");\ + return ss;\ + } +#if defined(ELPP_WXWIDGETS_LOGGING) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(wxVector) +# define ELPP_WX_PTR_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), *(*elem)) +# define ELPP_WX_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), (*elem)) +# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), \ + ELPP_LITERAL("(") << elem->first << ELPP_LITERAL(", ") << elem->second << ELPP_LITERAL(")") +#else +# define ELPP_WX_PTR_ENABLED(ContainerType) +# define ELPP_WX_ENABLED(ContainerType) +# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) +#endif // defined(ELPP_WXWIDGETS_LOGGING) + // Other classes + template + ELPP_SIMPLE_LOG(const Class&) +#undef ELPP_SIMPLE_LOG +#undef ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG + private: + Logger* m_logger; + const base::type::char_t* m_containerLogSeperator; + + template + inline MessageBuilder& writeIterator(Iterator begin_, Iterator end_, std::size_t size_) { + m_logger->stream() << ELPP_LITERAL("["); + for (std::size_t i = 0; begin_ != end_ && i < base::consts::kMaxLogPerContainer; ++i, ++begin_) { + operator << (*begin_); + m_logger->stream() << ((i < size_ - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); + } + if (begin_ != end_) { + m_logger->stream() << ELPP_LITERAL("..."); + } + m_logger->stream() << ELPP_LITERAL("]"); + if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { + m_logger->stream() << " "; + } + return *this; + } + }; + /// @brief Writes nothing - Used when certain log is disabled + class NullWriter : base::NoCopy { + public: + NullWriter(void) {} + + // Null manipulator + inline NullWriter& operator<<(std::ostream& (*)(std::ostream&)) { + return *this; + } + + template + inline NullWriter& operator<<(const T&) { + return *this; + } + }; + /// @brief Main entry point of each logging + class Writer : base::NoCopy { + public: + Writer(Level level, const char* file, unsigned long int line, + const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, + base::type::VerboseLevel verboseLevel = 0) : + m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel), + m_proceed(false), m_dispatchAction(dispatchAction) { + } + + virtual ~Writer(void) { + processDispatch(); + } + + template + inline Writer& operator<<(const T& log) { +#if ELPP_LOGGING_ENABLED + if (m_proceed) { + m_messageBuilder << log; + } +#endif // ELPP_LOGGING_ENABLED + return *this; + } + + inline Writer& operator<<(std::ostream& (*log)(std::ostream&)) { +#if ELPP_LOGGING_ENABLED + if (m_proceed) { + m_messageBuilder << log; + } +#endif // ELPP_LOGGING_ENABLED + return *this; + } + + Writer& construct(Logger* logger, bool needLock = true) { + m_logger = logger; + initializeLogger(logger->id(), false, needLock); + m_messageBuilder.initialize(m_logger); + return *this; + } + + Writer& construct(int count, const char* loggerIds, ...) { + if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { + va_list loggersList; + va_start(loggersList, loggerIds); + const char* id = loggerIds; + for (int i = 0; i < count; ++i) { + m_loggerIds.push_back(std::string(id)); + id = va_arg(loggersList, const char*); + } + va_end(loggersList); + initializeLogger(m_loggerIds.at(0)); + } + else { + initializeLogger(std::string(loggerIds)); + } + m_messageBuilder.initialize(m_logger); + return *this; + } + protected: + Level m_level; + const char* m_file; + const unsigned long int m_line; + const char* m_func; + base::type::VerboseLevel m_verboseLevel; + Logger* m_logger; + bool m_proceed; + base::MessageBuilder m_messageBuilder; + base::DispatchAction m_dispatchAction; + std::vector m_loggerIds; + friend class el::Helpers; + + void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true) { + if (lookup) { + m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically)); + } + if (m_logger == nullptr) { + ELPP->acquireLock(); + if (!ELPP->registeredLoggers()->has(std::string(base::consts::kDefaultLoggerId))) { + // Somehow default logger has been unregistered. Not good! Register again + ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId)); + } + ELPP->releaseLock(); // Need to unlock it for next writer + Writer(Level::Debug, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) + << "Logger [" << loggerId << "] is not registered yet!"; + m_proceed = false; + } + else { + if (needLock) { + m_logger->acquireLock(); // This should not be unlocked by checking m_proceed because + // m_proceed can be changed by lines below + } + if (ELPP->hasFlag(LoggingFlag::HierarchicalLogging)) { + m_proceed = m_level == Level::Verbose ? m_logger->enabled(m_level) : + LevelHelper::castToInt(m_level) >= LevelHelper::castToInt(ELPP->m_loggingLevel); + } + else { + m_proceed = m_logger->enabled(m_level); + } + } + } + + void processDispatch() { +#if ELPP_LOGGING_ENABLED + if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { + bool firstDispatched = false; + base::type::string_t logMessage; + std::size_t i = 0; + do { + if (m_proceed) { + if (firstDispatched) { + m_logger->stream() << logMessage; + } + else { + firstDispatched = true; + if (m_loggerIds.size() > 1) { + logMessage = m_logger->stream().str(); + } + } + triggerDispatch(); + } + else if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } + if (i + 1 < m_loggerIds.size()) { + initializeLogger(m_loggerIds.at(i + 1)); + } + } while (++i < m_loggerIds.size()); + } + else { + if (m_proceed) { + triggerDispatch(); + } + else if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } + } +#else + if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } +#endif // ELPP_LOGGING_ENABLED + } + + void triggerDispatch(void) { + if (m_proceed) { + base::LogDispatcher(m_proceed, LogMessage(m_level, m_file, m_line, m_func, m_verboseLevel, + m_logger), m_dispatchAction).dispatch(); + } + if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } + if (m_proceed && m_level == Level::Fatal + && !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) { + base::Writer(Level::Warning, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) + << "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]"; + std::stringstream reasonStream; + reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]" + << " If you wish to disable 'abort on fatal log' please use " + << "el::Helpers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog)"; + base::utils::abort(1, reasonStream.str()); + } + m_proceed = false; + } + }; + class PErrorWriter : public base::Writer { + public: + PErrorWriter(Level level, const char* file, unsigned long int line, + const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, + base::type::VerboseLevel verboseLevel = 0) : + base::Writer(level, file, line, func, dispatchAction, verboseLevel) { + } + + virtual ~PErrorWriter(void) { + if (m_proceed) { +#if ELPP_COMPILER_MSVC + char buff[256]; + strerror_s(buff, 256, errno); + m_logger->stream() << ": " << buff << " [" << errno << "]"; +#else + m_logger->stream() << ": " << strerror(errno) << " [" << errno << "]"; +#endif + } + } + }; + } // namespace base + // Logging from Logger class. Why this is here? Because we have Storage and Writer class available +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED + template + void Logger::log_(Level level, int vlevel, const char* s, const T& value, const Args&... args) { + base::MessageBuilder b; + b.initialize(this); + while (*s) { + if (*s == base::consts::kFormatSpecifierChar) { + if (*(s + 1) == base::consts::kFormatSpecifierChar) { + ++s; + } + else { + if (*(s + 1) == base::consts::kFormatSpecifierCharValue) { + ++s; + b << value; + log_(level, vlevel, ++s, args...); + return; + } + } + } + b << *s++; + } + ELPP_INTERNAL_ERROR("Too many arguments provided. Unable to handle. Please provide more format specifiers", false); + } + template + inline void Logger::log_(Level level, int vlevel, const T& log) { + if (level == Level::Verbose) { + if (ELPP->vRegistry()->allowed(vlevel, __FILE__)) { + base::Writer(Level::Verbose, "FILE", 0, "FUNCTION", + base::DispatchAction::NormalLog, vlevel).construct(this, false) << log; + } + else { + stream().str(ELPP_LITERAL("")); + } + } + else { + base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log; + } + } + template + void Logger::log(Level level, const char* s, const T& value, const Args&... args) { + base::threading::ScopedLock scopedLock(lock()); + log_(level, 0, s, value, args...); + } + template + inline void Logger::log(Level level, const T& log) { + base::threading::ScopedLock scopedLock(lock()); + log_(level, 0, log); + } +# if ELPP_VERBOSE_LOG + template + inline void Logger::verbose(int vlevel, const char* s, const T& value, const Args&... args) { + base::threading::ScopedLock scopedLock(lock()); + log_(el::Level::Verbose, vlevel, s, value, args...); + } + template + inline void Logger::verbose(int vlevel, const T& log) { + base::threading::ScopedLock scopedLock(lock()); + log_(el::Level::Verbose, vlevel, log); + } +# else + template + inline void Logger::verbose(int, const char*, const T&, const Args&...) { + return; + } + template + inline void Logger::verbose(int, const T&) { + return; + } +# endif // ELPP_VERBOSE_LOG +# define LOGGER_LEVEL_WRITERS(FUNCTION_NAME, LOG_LEVEL)\ + template \ + inline void Logger::FUNCTION_NAME(const char* s, const T& value, const Args&... args) {\ + log(LOG_LEVEL, s, value, args...);\ + }\ + template \ + inline void Logger::FUNCTION_NAME(const T& value) {\ + log(LOG_LEVEL, value);\ + } +# define LOGGER_LEVEL_WRITERS_DISABLED(FUNCTION_NAME, LOG_LEVEL)\ + template \ + inline void Logger::FUNCTION_NAME(const char*, const T&, const Args&...) {\ + return;\ + }\ + template \ + inline void Logger::FUNCTION_NAME(const T&) {\ + return;\ + } + +# if ELPP_INFO_LOG + LOGGER_LEVEL_WRITERS(info, Level::Info) +# else + LOGGER_LEVEL_WRITERS_DISABLED(info, Level::Info) +# endif // ELPP_INFO_LOG +# if ELPP_DEBUG_LOG + LOGGER_LEVEL_WRITERS(debug, Level::Debug) +# else + LOGGER_LEVEL_WRITERS_DISABLED(debug, Level::Debug) +# endif // ELPP_DEBUG_LOG +# if ELPP_WARNING_LOG + LOGGER_LEVEL_WRITERS(warn, Level::Warning) +# else + LOGGER_LEVEL_WRITERS_DISABLED(warn, Level::Warning) +# endif // ELPP_WARNING_LOG +# if ELPP_ERROR_LOG + LOGGER_LEVEL_WRITERS(error, Level::Error) +# else + LOGGER_LEVEL_WRITERS_DISABLED(error, Level::Error) +# endif // ELPP_ERROR_LOG +# if ELPP_FATAL_LOG + LOGGER_LEVEL_WRITERS(fatal, Level::Fatal) +# else + LOGGER_LEVEL_WRITERS_DISABLED(fatal, Level::Fatal) +# endif // ELPP_FATAL_LOG +# if ELPP_TRACE_LOG + LOGGER_LEVEL_WRITERS(trace, Level::Trace) +# else + LOGGER_LEVEL_WRITERS_DISABLED(trace, Level::Trace) +# endif // ELPP_TRACE_LOG +# undef LOGGER_LEVEL_WRITERS +# undef LOGGER_LEVEL_WRITERS_DISABLED +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED +#if ELPP_COMPILER_MSVC +# define ELPP_VARIADIC_FUNC_MSVC(variadicFunction, variadicArgs) variadicFunction variadicArgs +# define ELPP_VARIADIC_FUNC_MSVC_RUN(variadicFunction, ...) ELPP_VARIADIC_FUNC_MSVC(variadicFunction, (__VA_ARGS__)) +# define el_getVALength(...) ELPP_VARIADIC_FUNC_MSVC_RUN(el_resolveVALength, 0, ## __VA_ARGS__,\ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +#else +# if ELPP_COMPILER_CLANG +# define el_getVALength(...) el_resolveVALength(0, __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +# else +# define el_getVALength(...) el_resolveVALength(0, ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +# endif // ELPP_COMPILER_CLANG +#endif // ELPP_COMPILER_MSVC +#define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N +#define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) if (condition) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \ + if (ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion)) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \ + if (ELPP->validateAfterNCounter(__FILE__, __LINE__, n)) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \ + if (ELPP->validateNTimesCounter(__FILE__, __LINE__, n)) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#undef ELPP_CURR_FILE_PERFORMANCE_LOGGER +#if defined(ELPP_PERFORMANCE_LOGGER) +# define ELPP_CURR_FILE_PERFORMANCE_LOGGER ELPP_PERFORMANCE_LOGGER +#else +# define ELPP_CURR_FILE_PERFORMANCE_LOGGER el::base::consts::kPerformanceLoggerId +#endif + class PerformanceTrackingData { + public: + enum class DataType : base::type::EnumType { + Checkpoint = 1, Complete = 2 + }; + // Do not use constructor, will run into multiple definition error, use init(PerformanceTracker*) + explicit PerformanceTrackingData(DataType dataType) : m_performanceTracker(nullptr), + m_dataType(dataType), m_file(""), m_line(0), m_func("") {} + inline const std::string* blockName(void) const; + inline const struct timeval* startTime(void) const; + inline const struct timeval* endTime(void) const; + inline const struct timeval* lastCheckpointTime(void) const; + inline const base::PerformanceTracker* performanceTracker(void) const { return m_performanceTracker; } + inline PerformanceTrackingData::DataType dataType(void) const { return m_dataType; } + inline bool firstCheckpoint(void) const { return m_firstCheckpoint; } + inline std::string checkpointId(void) const { return m_checkpointId; } + inline const char* file(void) const { return m_file; } + inline unsigned long int line(void) const { return m_line; } + inline const char* func(void) const { return m_func; } + inline const base::type::string_t* formattedTimeTaken() const { return &m_formattedTimeTaken; } + inline const std::string& loggerId(void) const; + private: + base::PerformanceTracker* m_performanceTracker; + base::type::string_t m_formattedTimeTaken; + PerformanceTrackingData::DataType m_dataType; + bool m_firstCheckpoint; + std::string m_checkpointId; + const char* m_file; + unsigned long int m_line; + const char* m_func; + inline void init(base::PerformanceTracker* performanceTracker, bool firstCheckpoint = false) { + m_performanceTracker = performanceTracker; + m_firstCheckpoint = firstCheckpoint; + } + + friend class el::base::PerformanceTracker; + }; + namespace base { + /// @brief Represents performanceTracker block of code that conditionally adds performance status to log + /// either when goes outside the scope of when checkpoint() is called + class PerformanceTracker : public base::threading::ThreadSafe, public Loggable { + public: + PerformanceTracker(const std::string& blockName, + base::TimestampUnit timestampUnit = base::TimestampUnit::Millisecond, + const std::string& loggerId = std::string(ELPP_CURR_FILE_PERFORMANCE_LOGGER), + bool scopedLog = true, Level level = base::consts::kPerformanceTrackerDefaultLevel) : + m_blockName(blockName), m_timestampUnit(timestampUnit), m_loggerId(loggerId), m_scopedLog(scopedLog), + m_level(level), m_hasChecked(false), m_lastCheckpointId(std::string()), m_enabled(false) { +#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + // We store it locally so that if user happen to change configuration by the end of scope + // or before calling checkpoint, we still depend on state of configuraton at time of construction + el::Logger* loggerPtr = ELPP->registeredLoggers()->get(loggerId, false); + m_enabled = loggerPtr != nullptr && loggerPtr->m_typedConfigurations->performanceTracking(m_level); + if (m_enabled) { + base::utils::DateTime::gettimeofday(&m_startTime); + } +#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + } + /// @brief Copy constructor + PerformanceTracker(const PerformanceTracker& t) : + m_blockName(t.m_blockName), m_timestampUnit(t.m_timestampUnit), m_loggerId(t.m_loggerId), m_scopedLog(t.m_scopedLog), + m_level(t.m_level), m_hasChecked(t.m_hasChecked), m_lastCheckpointId(t.m_lastCheckpointId), m_enabled(t.m_enabled), + m_startTime(t.m_startTime), m_endTime(t.m_endTime), m_lastCheckpointTime(t.m_lastCheckpointTime) { + } + virtual ~PerformanceTracker(void) { +#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + if (m_enabled) { + base::threading::ScopedLock scopedLock(lock()); + if (m_scopedLog) { + base::utils::DateTime::gettimeofday(&m_endTime); + base::type::string_t formattedTime = getFormattedTimeTaken(); + PerformanceTrackingData data(PerformanceTrackingData::DataType::Complete); + data.init(this); + data.m_formattedTimeTaken = formattedTime; + PerformanceTrackingCallback* callback = nullptr; + for (const std::pair& h + : ELPP->m_performanceTrackingCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + callback->acquireLock(); + callback->handle(&data); + callback->releaseLock(); + } + } + } + } +#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) + } + /// @brief A checkpoint for current performanceTracker block. + void checkpoint(const std::string& id = std::string(), const char* file = __FILE__, unsigned long int line = __LINE__, const char* func = "") { +#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + if (m_enabled) { + base::threading::ScopedLock scopedLock(lock()); + base::utils::DateTime::gettimeofday(&m_endTime); + base::type::string_t formattedTime = m_hasChecked ? getFormattedTimeTaken(m_lastCheckpointTime) : ELPP_LITERAL(""); + PerformanceTrackingData data(PerformanceTrackingData::DataType::Checkpoint); + data.init(this); + data.m_checkpointId = id; + data.m_file = file; + data.m_line = line; + data.m_func = func; + data.m_formattedTimeTaken = formattedTime; + PerformanceTrackingCallback* callback = nullptr; + for (const std::pair& h + : ELPP->m_performanceTrackingCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + callback->acquireLock(); + callback->handle(&data); + callback->releaseLock(); + } + } + base::utils::DateTime::gettimeofday(&m_lastCheckpointTime); + m_hasChecked = true; + m_lastCheckpointId = id; + } +#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + ELPP_UNUSED(id); + ELPP_UNUSED(file); + ELPP_UNUSED(line); + ELPP_UNUSED(func); + } + inline Level level(void) const { return m_level; } + private: + std::string m_blockName; + base::TimestampUnit m_timestampUnit; + std::string m_loggerId; + bool m_scopedLog; + Level m_level; + bool m_hasChecked; + std::string m_lastCheckpointId; + bool m_enabled; + struct timeval m_startTime, m_endTime, m_lastCheckpointTime; + + PerformanceTracker(void); + + friend class el::PerformanceTrackingData; + friend class base::DefaultPerformanceTrackingCallback; + + const inline base::type::string_t getFormattedTimeTaken() const { + return getFormattedTimeTaken(m_startTime); + } + + const base::type::string_t getFormattedTimeTaken(struct timeval startTime) const { + if (ELPP->hasFlag(LoggingFlag::FixedTimeFormat)) { + base::type::stringstream_t ss; + ss << base::utils::DateTime::getTimeDifference(m_endTime, + startTime, m_timestampUnit) << " " << base::consts::kTimeFormats[static_cast(m_timestampUnit)].unit; + return ss.str(); + } + return base::utils::DateTime::formatTime(base::utils::DateTime::getTimeDifference(m_endTime, + startTime, m_timestampUnit), m_timestampUnit); + } + + virtual inline void log(el::base::type::ostream_t& os) const { + os << getFormattedTimeTaken(); + } + }; + class DefaultPerformanceTrackingCallback : public PerformanceTrackingCallback { + protected: + void handle(const PerformanceTrackingData* data) { + m_data = data; + base::type::stringstream_t ss; + if (m_data->dataType() == PerformanceTrackingData::DataType::Complete) { + ss << ELPP_LITERAL("Executed [") << m_data->blockName()->c_str() << ELPP_LITERAL("] in [") << *m_data->formattedTimeTaken() << ELPP_LITERAL("]"); + } + else { + ss << ELPP_LITERAL("Performance checkpoint"); + if (!m_data->checkpointId().empty()) { + ss << ELPP_LITERAL(" [") << m_data->checkpointId().c_str() << ELPP_LITERAL("]"); + } + ss << ELPP_LITERAL(" for block [") << m_data->blockName()->c_str() << ELPP_LITERAL("] : [") << *m_data->performanceTracker(); + if (!ELPP->hasFlag(LoggingFlag::DisablePerformanceTrackingCheckpointComparison) && m_data->performanceTracker()->m_hasChecked) { + ss << ELPP_LITERAL(" ([") << *m_data->formattedTimeTaken() << ELPP_LITERAL("] from "); + if (m_data->performanceTracker()->m_lastCheckpointId.empty()) { + ss << ELPP_LITERAL("last checkpoint"); + } + else { + ss << ELPP_LITERAL("checkpoint '") << m_data->performanceTracker()->m_lastCheckpointId.c_str() << ELPP_LITERAL("'"); + } + ss << ELPP_LITERAL(")]"); + } + else { + ss << ELPP_LITERAL("]"); + } + } + el::base::Writer(m_data->performanceTracker()->level(), m_data->file(), m_data->line(), m_data->func()).construct(1, m_data->loggerId().c_str()) << ss.str(); + } + private: + const PerformanceTrackingData* m_data; + }; + } // namespace base + inline const std::string* PerformanceTrackingData::blockName() const { + return const_cast(&m_performanceTracker->m_blockName); + } + inline const struct timeval* PerformanceTrackingData::startTime() const { + return const_cast(&m_performanceTracker->m_startTime); + } + inline const struct timeval* PerformanceTrackingData::endTime() const { + return const_cast(&m_performanceTracker->m_endTime); + } + inline const struct timeval* PerformanceTrackingData::lastCheckpointTime() const { + return const_cast(&m_performanceTracker->m_lastCheckpointTime); + } + inline const std::string& PerformanceTrackingData::loggerId(void) const { return m_performanceTracker->m_loggerId; } + namespace base { + /// @brief Contains some internal debugging tools like crash handler and stack tracer + namespace debug { + class StackTrace : base::NoCopy { + public: + static const std::size_t kMaxStack = 64; + static const std::size_t kStackStart = 2; // We want to skip c'tor and StackTrace::generateNew() + class StackTraceEntry { + public: + StackTraceEntry(std::size_t index, const char* loc, const char* demang, const char* hex, const char* addr) { + m_index = index; + m_location = std::string(loc); + m_demangled = std::string(demang); + m_hex = std::string(hex); + m_addr = std::string(addr); + } + StackTraceEntry(std::size_t index, char* loc) { + m_index = index; + m_location = std::string(loc); + } + std::size_t m_index; + std::string m_location; + std::string m_demangled; + std::string m_hex; + std::string m_addr; + friend std::ostream& operator<<(std::ostream& ss, const StackTraceEntry& si) { + ss << "[" << si.m_index << "] " << si.m_location << (si.m_demangled.empty() ? "" : ":") << si.m_demangled + << (si.m_hex.empty() ? "" : "+") << si.m_hex << si.m_addr; + return ss; + } + + private: + StackTraceEntry(void); + }; + + StackTrace(void) { + generateNew(); + } + + virtual ~StackTrace(void) { + } + + inline std::vector& getLatestStack(void) { + return m_stack; + } + + friend inline std::ostream& operator<<(std::ostream& os, const StackTrace& st) { + std::vector::const_iterator it = st.m_stack.begin(); + while (it != st.m_stack.end()) { + os << " " << *it++ << "\n"; + } + return os; + } + + private: + std::vector m_stack; + + void generateNew(void) { +#if ELPP_STACKTRACE + m_stack.clear(); + void* stack[kMaxStack]; + std::size_t size = backtrace(stack, kMaxStack); + char** strings = backtrace_symbols(stack, size); + if (size > kStackStart) { // Skip StackTrace c'tor and generateNew + for (std::size_t i = kStackStart; i < size; ++i) { + char* mangName = nullptr; + char* hex = nullptr; + char* addr = nullptr; + for (char* c = strings[i]; *c; ++c) { + switch (*c) { + case '(': + mangName = c; + break; + case '+': + hex = c; + break; + case ')': + addr = c; + break; + } + } + // Perform demangling if parsed properly + if (mangName != nullptr && hex != nullptr && addr != nullptr && mangName < hex) { + *mangName++ = '\0'; + *hex++ = '\0'; + *addr++ = '\0'; + int status = 0; + char* demangName = abi::__cxa_demangle(mangName, 0, 0, &status); + // if demangling is successful, output the demangled function name + if (status == 0) { + // Success (see http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html) + StackTraceEntry entry(i - 1, strings[i], demangName, hex, addr); + m_stack.push_back(entry); + } + else { + // Not successful - we will use mangled name + StackTraceEntry entry(i - 1, strings[i], mangName, hex, addr); + m_stack.push_back(entry); + } + free(demangName); + } + else { + StackTraceEntry entry(i - 1, strings[i]); + m_stack.push_back(entry); + } + } + } + free(strings); +#else + ELPP_INTERNAL_INFO(1, "Stacktrace generation not supported for selected compiler"); +#endif // ELPP_STACKTRACE + } + }; + static std::string crashReason(int sig) { + std::stringstream ss; + bool foundReason = false; + for (int i = 0; i < base::consts::kCrashSignalsCount; ++i) { + if (base::consts::kCrashSignals[i].numb == sig) { + ss << "Application has crashed due to [" << base::consts::kCrashSignals[i].name << "] signal"; + if (ELPP->hasFlag(el::LoggingFlag::LogDetailedCrashReason)) { + ss << std::endl << + " " << base::consts::kCrashSignals[i].brief << std::endl << + " " << base::consts::kCrashSignals[i].detail; + } + foundReason = true; + } + } + if (!foundReason) { + ss << "Application has crashed due to unknown signal [" << sig << "]"; + } + return ss.str(); + } + /// @brief Logs reason of crash from sig + static void logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char* logger) { + std::stringstream ss; + ss << "CRASH HANDLED; "; + ss << crashReason(sig); +#if ELPP_STACKTRACE + if (stackTraceIfAvailable) { + ss << std::endl << " ======= Backtrace: =========" << std::endl << base::debug::StackTrace(); + } +#else + ELPP_UNUSED(stackTraceIfAvailable); +#endif // ELPP_STACKTRACE + ELPP_WRITE_LOG(el::base::Writer, level, base::DispatchAction::NormalLog, logger) << ss.str(); + } + static inline void crashAbort(int sig) { + base::utils::abort(sig); + } + /// @brief Default application crash handler + /// + /// @detail This function writes log using 'default' logger, prints stack trace for GCC based compilers and aborts program. + static inline void defaultCrashHandler(int sig) { + base::debug::logCrashReason(sig, true, Level::Fatal, base::consts::kDefaultLoggerId); + base::debug::crashAbort(sig); + } + /// @brief Handles unexpected crashes + class CrashHandler : base::NoCopy { + public: + typedef void(*Handler)(int); + + explicit CrashHandler(bool useDefault) { + if (useDefault) { + setHandler(defaultCrashHandler); + } + } + explicit CrashHandler(const Handler& cHandler) { + setHandler(cHandler); + } + void setHandler(const Handler& cHandler) { + m_handler = cHandler; +#if defined(ELPP_HANDLE_SIGABRT) + int i = 0; // SIGABRT is at base::consts::kCrashSignals[0] +#else + int i = 1; +#endif // defined(ELPP_HANDLE_SIGABRT) + for (; i < base::consts::kCrashSignalsCount; ++i) { + m_handler = signal(base::consts::kCrashSignals[i].numb, cHandler); + } + } + + private: + Handler m_handler; + }; + } // namespace debug + } // namespace base + extern base::debug::CrashHandler elCrashHandler; +#define MAKE_LOGGABLE(ClassType, ClassInstance, OutputStreamInstance) \ + el::base::type::ostream_t& operator<<(el::base::type::ostream_t& OutputStreamInstance, const ClassType& ClassInstance) + /// @brief Initializes syslog with process ID, options and facility. calls closelog() on d'tor + class SysLogInitializer { + public: + SysLogInitializer(const char* processIdent, int options = 0, int facility = 0) { +#if defined(ELPP_SYSLOG) + openlog(processIdent, options, facility); +#else + ELPP_UNUSED(processIdent); + ELPP_UNUSED(options); + ELPP_UNUSED(facility); +#endif // defined(ELPP_SYSLOG) + } + virtual ~SysLogInitializer(void) { +#if defined(ELPP_SYSLOG) + closelog(); +#endif // defined(ELPP_SYSLOG) + } + }; +#define ELPP_INITIALIZE_SYSLOG(id, opt, fac) el::SysLogInitializer elSyslogInit(id, opt, fac) + /// @brief Static helpers for developers + class Helpers : base::StaticClass { + public: + /// @brief Shares logging repository (base::Storage) + static inline void setStorage(base::type::StoragePointer storage) { + ELPP = storage; + } + /// @return Main storage repository + static inline base::type::StoragePointer storage() { + return ELPP; + } + /// @brief Sets application arguments and figures out whats active for logging and whats not. + static inline void setArgs(int argc, char** argv) { + ELPP->setApplicationArguments(argc, argv); + } + /// @copydoc setArgs(int argc, char** argv) + static inline void setArgs(int argc, const char** argv) { + ELPP->setApplicationArguments(argc, const_cast(argv)); + } + /// @brief Overrides default crash handler and installs custom handler. + /// @param crashHandler A functor with no return type that takes single int argument. + /// Handler is a typedef with specification: void (*Handler)(int) + static inline void setCrashHandler(const el::base::debug::CrashHandler::Handler& crashHandler) { + el::elCrashHandler.setHandler(crashHandler); + } + /// @brief Abort due to crash with signal in parameter + /// @param sig Crash signal + static inline void crashAbort(int sig, const char* sourceFile = "", unsigned int long line = 0) { + std::stringstream ss; + ss << base::debug::crashReason(sig).c_str(); + ss << " - [Called el::Helpers::crashAbort(" << sig << ")]"; + if (sourceFile != nullptr && strlen(sourceFile) > 0) { + ss << " - Source: " << sourceFile; + if (line > 0) + ss << ":" << line; + else + ss << " (line number not specified)"; + } + base::utils::abort(sig, ss.str()); + } + /// @brief Logs reason of crash as per sig + /// @param sig Crash signal + /// @param stackTraceIfAvailable Includes stack trace if available + /// @param level Logging level + /// @param logger Logger to use for logging + static inline void logCrashReason(int sig, bool stackTraceIfAvailable = false, + Level level = Level::Fatal, const char* logger = base::consts::kDefaultLoggerId) { + el::base::debug::logCrashReason(sig, stackTraceIfAvailable, level, logger); + } + /// @brief Installs pre rollout callback, this callback is triggered when log file is about to be rolled out + /// (can be useful for backing up) + static inline void installPreRollOutCallback(const PreRollOutCallback& callback) { + ELPP->setPreRollOutCallback(callback); + } + /// @brief Uninstalls pre rollout callback + static inline void uninstallPreRollOutCallback(void) { + ELPP->unsetPreRollOutCallback(); + } + /// @brief Installs post log dispatch callback, this callback is triggered when log is dispatched + template + static inline bool installLogDispatchCallback(const std::string& id) { + return ELPP->installLogDispatchCallback(id); + } + /// @brief Uninstalls log dispatch callback + template + static inline void uninstallLogDispatchCallback(const std::string& id) { + ELPP->uninstallLogDispatchCallback(id); + } + template + static inline T* logDispatchCallback(const std::string& id) { + return ELPP->logDispatchCallback(id); + } + /// @brief Installs post performance tracking callback, this callback is triggered when performance tracking is finished + template + static inline bool installPerformanceTrackingCallback(const std::string& id) { + return ELPP->installPerformanceTrackingCallback(id); + } + /// @brief Uninstalls post performance tracking handler + template + static inline void uninstallPerformanceTrackingCallback(const std::string& id) { + ELPP->uninstallPerformanceTrackingCallback(id); + } + template + static inline T* performanceTrackingCallback(const std::string& id) { + return ELPP->performanceTrackingCallback(id); + } + /// @brief Converts template to std::string - useful for loggable classes to log containers within log(std::ostream&) const + template + static std::string convertTemplateToStdString(const T& templ) { + el::Logger* logger = + ELPP->registeredLoggers()->get(el::base::consts::kDefaultLoggerId); + if (logger == nullptr) { + return std::string(); + } + base::MessageBuilder b; + b.initialize(logger); + logger->acquireLock(); + b << templ; +#if defined(ELPP_UNICODE) + std::string s = std::string(logger->stream().str().begin(), logger->stream().str().end()); +#else + std::string s = logger->stream().str(); +#endif // defined(ELPP_UNICODE) + logger->stream().str(ELPP_LITERAL("")); + logger->releaseLock(); + return s; + } + /// @brief Returns command line arguments (pointer) provided to easylogging++ + static inline const el::base::utils::CommandLineArgs* commandLineArgs(void) { + return ELPP->commandLineArgs(); + } + /// @brief Installs user defined format specifier and handler + static inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { + ELPP->installCustomFormatSpecifier(customFormatSpecifier); + } + /// @brief Uninstalls user defined format specifier and handler + static inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier) { + return ELPP->uninstallCustomFormatSpecifier(formatSpecifier); + } + /// @brief Returns true if custom format specifier is installed + static inline bool hasCustomFormatSpecifier(const char* formatSpecifier) { + return ELPP->hasCustomFormatSpecifier(formatSpecifier); + } + static inline void validateFileRolling(Logger* logger, Level level) { + if (logger == nullptr) return; + logger->m_typedConfigurations->validateFileRolling(level, ELPP->preRollOutCallback()); + } + }; + /// @brief Static helpers to deal with loggers and their configurations + class Loggers : base::StaticClass { + public: + /// @brief Gets existing or registers new logger + static inline Logger* getLogger(const std::string& identity, bool registerIfNotAvailable = true) { + base::threading::ScopedLock scopedLock(ELPP->lock()); + return ELPP->registeredLoggers()->get(identity, registerIfNotAvailable); + } + /// @brief Unregisters logger - use it only when you know what you are doing, you may unregister + /// loggers initialized / used by third-party libs. + static inline bool unregisterLogger(const std::string& identity) { + base::threading::ScopedLock scopedLock(ELPP->lock()); + return ELPP->registeredLoggers()->remove(identity); + } + /// @brief Whether or not logger with id is registered + static inline bool hasLogger(const std::string& identity) { + base::threading::ScopedLock scopedLock(ELPP->lock()); + return ELPP->registeredLoggers()->has(identity); + } + /// @brief Reconfigures specified logger with new configurations + static inline Logger* reconfigureLogger(Logger* logger, const Configurations& configurations) { + if (!logger) return nullptr; + logger->configure(configurations); + return logger; + } + /// @brief Reconfigures logger with new configurations after looking it up using identity + static inline Logger* reconfigureLogger(const std::string& identity, const Configurations& configurations) { + return Loggers::reconfigureLogger(Loggers::getLogger(identity), configurations); + } + /// @brief Reconfigures logger's single configuration + static inline Logger* reconfigureLogger(const std::string& identity, ConfigurationType configurationType, + const std::string& value) { + Logger* logger = Loggers::getLogger(identity); + if (logger == nullptr) { + return nullptr; + } + logger->configurations()->set(Level::Global, configurationType, value); + logger->reconfigure(); + return logger; + } + /// @brief Reconfigures all the existing loggers with new configurations + static inline void reconfigureAllLoggers(const Configurations& configurations) { + for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); + it != ELPP->registeredLoggers()->end(); ++it) { + Loggers::reconfigureLogger(it->second, configurations); + } + } + /// @brief Reconfigures single configuration for all the loggers + static inline void reconfigureAllLoggers(ConfigurationType configurationType, const std::string& value) { + reconfigureAllLoggers(Level::Global, configurationType, value); + } + /// @brief Reconfigures single configuration for all the loggers for specified level + static inline void reconfigureAllLoggers(Level level, ConfigurationType configurationType, + const std::string& value) { + for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); + it != ELPP->registeredLoggers()->end(); ++it) { + Logger* logger = it->second; + logger->configurations()->set(level, configurationType, value); + logger->reconfigure(); + } + } + /// @brief Sets default configurations. This configuration is used for future (and conditionally for existing) loggers + static inline void setDefaultConfigurations(const Configurations& configurations, bool reconfigureExistingLoggers = false) { + ELPP->registeredLoggers()->setDefaultConfigurations(configurations); + if (reconfigureExistingLoggers) { + Loggers::reconfigureAllLoggers(configurations); + } + } + /// @brief Returns current default + static inline const Configurations* defaultConfigurations(void) { + return ELPP->registeredLoggers()->defaultConfigurations(); + } + /// @brief Returns log stream reference pointer if needed by user + static inline const base::LogStreamsReferenceMap* logStreamsReference(void) { + return ELPP->registeredLoggers()->logStreamsReference(); + } + /// @brief Default typed configuration based on existing defaultConf + static base::TypedConfigurations defaultTypedConfigurations(void) { + return base::TypedConfigurations( + ELPP->registeredLoggers()->defaultConfigurations(), + ELPP->registeredLoggers()->logStreamsReference()); + } + /// @brief Populates all logger IDs in current repository. + /// @param [out] targetList List of fill up. + static inline std::vector* populateAllLoggerIds(std::vector* targetList) { + targetList->clear(); + for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->list().begin(); + it != ELPP->registeredLoggers()->list().end(); ++it) { + targetList->push_back(it->first); + } + return targetList; + } + /// @brief Sets configurations from global configuration file. + static void configureFromGlobal(const char* globalConfigurationFilePath) { + std::ifstream gcfStream(globalConfigurationFilePath, std::ifstream::in); + ELPP_ASSERT(gcfStream.is_open(), "Unable to open global configuration file [" << globalConfigurationFilePath + << "] for parsing."); + std::string line = std::string(); + std::stringstream ss; + Logger* logger = nullptr; + auto configure = [&](void) { + ELPP_INTERNAL_INFO(8, "Configuring logger: '" << logger->id() << "' with configurations \n" << ss.str() + << "\n--------------"); + Configurations c; + c.parseFromText(ss.str()); + logger->configure(c); + }; + while (gcfStream.good()) { + std::getline(gcfStream, line); + ELPP_INTERNAL_INFO(1, "Parsing line: " << line); + base::utils::Str::trim(line); + if (Configurations::Parser::isComment(line)) continue; + Configurations::Parser::ignoreComments(&line); + base::utils::Str::trim(line); + if (line.size() > 2 && base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLoggerId))) { + if (!ss.str().empty() && logger != nullptr) { + configure(); + } + ss.str(std::string("")); + line = line.substr(2); + base::utils::Str::trim(line); + if (line.size() > 1) { + ELPP_INTERNAL_INFO(1, "Getting logger: '" << line << "'"); + logger = getLogger(line); + } + } + else { + ss << line << "\n"; + } + } + if (!ss.str().empty() && logger != nullptr) { + configure(); + } + } + /// @brief Configures loggers using command line arg. Ensure you have already set command line args, + /// @return False if invalid argument or argument with no value provided, true if attempted to configure logger. + /// If true is returned that does not mean it has been configured successfully, it only means that it + /// has attempeted to configure logger using configuration file provided in argument + static inline bool configureFromArg(const char* argKey) { +#if defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) + ELPP_UNUSED(argKey); +#else + if (!Helpers::commandLineArgs()->hasParamWithValue(argKey)) { + return false; + } + configureFromGlobal(Helpers::commandLineArgs()->getParamValue(argKey)); +#endif // defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) + return true; + } + /// @brief Flushes all loggers for all levels - Be careful if you dont know how many loggers are registered + static inline void flushAll(void) { + ELPP->registeredLoggers()->flushAll(); + } + /// @brief Adds logging flag used internally. + static inline void addFlag(LoggingFlag flag) { + ELPP->addFlag(flag); + } + /// @brief Removes logging flag used internally. + static inline void removeFlag(LoggingFlag flag) { + ELPP->removeFlag(flag); + } + /// @brief Determines whether or not certain flag is active + static inline bool hasFlag(LoggingFlag flag) { + return ELPP->hasFlag(flag); + } + /// @brief Adds flag and removes it when scope goes out + class ScopedAddFlag { + public: + ScopedAddFlag(LoggingFlag flag) : m_flag(flag) { Loggers::addFlag(m_flag); } + ~ScopedAddFlag(void) { Loggers::removeFlag(m_flag); } + private: + LoggingFlag m_flag; + }; + /// @brief Removes flag and add it when scope goes out + class ScopedRemoveFlag { + public: + ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag) { Loggers::removeFlag(m_flag); } + ~ScopedRemoveFlag(void) { Loggers::addFlag(m_flag); } + private: + LoggingFlag m_flag; + }; + /// @brief Sets hierarchy for logging. Needs to enable logging flag (HierarchicalLogging) + static inline void setLoggingLevel(Level level) { + ELPP->setLoggingLevel(level); + } + /// @brief Sets verbose level on the fly + static inline void setVerboseLevel(base::type::VerboseLevel level) { + ELPP->vRegistry()->setLevel(level); + } + /// @brief Gets current verbose level + static inline base::type::VerboseLevel verboseLevel(void) { + return ELPP->vRegistry()->level(); + } + /// @brief Sets vmodules as specified (on the fly) + static inline void setVModules(const char* modules) { + if (ELPP->vRegistry()->vModulesEnabled()) { + ELPP->vRegistry()->setModules(modules); + } + } + /// @brief Clears vmodules + static inline void clearVModules(void) { + ELPP->vRegistry()->clearModules(); + } + }; + class VersionInfo : base::StaticClass { + public: + /// @brief Current version number + static inline const std::string version(void) { return std::string("9.80"); } + /// @brief Release date of current version + static inline const std::string releaseDate(void) { return std::string("08-01-2015 0850hrs"); } + }; +} // namespace el +#undef VLOG_IS_ON + /// @brief Determines whether verbose logging is on for specified level current file. +#define VLOG_IS_ON(verboseLevel) (ELPP->vRegistry()->allowed(verboseLevel, __FILE__)) +#undef TIMED_BLOCK +#undef TIMED_SCOPE +#undef TIMED_FUNC +#undef ELPP_MIN_UNIT +#if defined(ELPP_PERFORMANCE_MICROSECONDS) +# define ELPP_MIN_UNIT el::base::TimestampUnit::Microsecond +#else +# define ELPP_MIN_UNIT el::base::TimestampUnit::Millisecond +#endif // (defined(ELPP_PERFORMANCE_MICROSECONDS)) + /// @brief Performance tracked scope. Performance gets written when goes out of scope using + /// 'performance' logger. + /// + /// @detail Please note in order to check the performance at a certain time you can use obj.checkpoint(); + /// @see el::base::PerformanceTracker + /// @see el::base::PerformanceTracker::checkpoint + // Note: Do not surround this definition with null macro because of obj instance +#define TIMED_SCOPE(obj, blockname) el::base::PerformanceTracker obj(blockname, ELPP_MIN_UNIT) +#define TIMED_BLOCK(obj, blockName) for (struct { int i; el::base::PerformanceTracker timer; } obj = { 0, \ + el::base::PerformanceTracker(blockName, ELPP_MIN_UNIT) }; obj.i < 1; ++obj.i) + /// @brief Performance tracked function. Performance gets written when goes out of scope using + /// 'performance' logger. + /// + /// @detail Please note in order to check the performance at a certain time you can use obj.checkpoint(); + /// @see el::base::PerformanceTracker + /// @see el::base::PerformanceTracker::checkpoint +#define TIMED_FUNC(obj) TIMED_SCOPE(obj, ELPP_FUNC) +#undef PERFORMANCE_CHECKPOINT +#undef PERFORMANCE_CHECKPOINT_WITH_ID +#define PERFORMANCE_CHECKPOINT(obj) obj.checkpoint(std::string(), __FILE__, __LINE__, ELPP_FUNC) +#define PERFORMANCE_CHECKPOINT_WITH_ID(obj, id) obj.checkpoint(id, __FILE__, __LINE__, ELPP_FUNC) +#undef ELPP_COUNTER +#undef ELPP_COUNTER_POS + /// @brief Gets hit counter for file/line +#define ELPP_COUNTER (ELPP->hitCounters()->getCounter(__FILE__, __LINE__)) + /// @brief Gets hit counter position for file/line, -1 if not registered yet +#define ELPP_COUNTER_POS (ELPP_COUNTER == nullptr ? -1 : ELPP_COUNTER->hitCounts()) + // Undef levels to support LOG(LEVEL) +#undef INFO +#undef WARNING +#undef DEBUG +#undef ERROR +#undef FATAL +#undef TRACE +#undef VERBOSE + // Undef existing +#undef CINFO +#undef CWARNING +#undef CDEBUG +#undef CFATAL +#undef CERROR +#undef CTRACE +#undef CVERBOSE +#undef CINFO_IF +#undef CWARNING_IF +#undef CDEBUG_IF +#undef CERROR_IF +#undef CFATAL_IF +#undef CTRACE_IF +#undef CVERBOSE_IF +#undef CINFO_EVERY_N +#undef CWARNING_EVERY_N +#undef CDEBUG_EVERY_N +#undef CERROR_EVERY_N +#undef CFATAL_EVERY_N +#undef CTRACE_EVERY_N +#undef CVERBOSE_EVERY_N +#undef CINFO_AFTER_N +#undef CWARNING_AFTER_N +#undef CDEBUG_AFTER_N +#undef CERROR_AFTER_N +#undef CFATAL_AFTER_N +#undef CTRACE_AFTER_N +#undef CVERBOSE_AFTER_N +#undef CINFO_N_TIMES +#undef CWARNING_N_TIMES +#undef CDEBUG_N_TIMES +#undef CERROR_N_TIMES +#undef CFATAL_N_TIMES +#undef CTRACE_N_TIMES +#undef CVERBOSE_N_TIMES + // Normal logs +#if ELPP_INFO_LOG +# define CINFO(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE(writer, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel)) writer(\ + el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#else +# define CVERBOSE(writer, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // Conditional logs +#if ELPP_INFO_LOG +# define CINFO_IF(writer, condition_, dispatchAction, ...) \ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel) && (condition_)) writer( \ + el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#else +# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // Occasional logs +#if ELPP_INFO_LOG +# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...)\ + CVERBOSE_IF(writer, ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion), vlevel, dispatchAction, __VA_ARGS__) +#else +# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // After N logs +#if ELPP_INFO_LOG +# define CINFO_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...)\ + CVERBOSE_IF(writer, ELPP->validateAfterNCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) +#else +# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // N Times logs +#if ELPP_INFO_LOG +# define CINFO_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...)\ + CVERBOSE_IF(writer, ELPP->validateNTimesCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) +#else +# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // + // Custom Loggers - Requires (level, dispatchAction, loggerId/s) + // + // undef existing +#undef CLOG +#undef CLOG_VERBOSE +#undef CVLOG +#undef CLOG_IF +#undef CLOG_VERBOSE_IF +#undef CVLOG_IF +#undef CLOG_EVERY_N +#undef CVLOG_EVERY_N +#undef CLOG_AFTER_N +#undef CVLOG_AFTER_N +#undef CLOG_N_TIMES +#undef CVLOG_N_TIMES + // Normal logs +#define CLOG(LEVEL, ...)\ + C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG(vlevel, ...) CVERBOSE(el::base::Writer, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) + // Conditional logs +#define CLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_IF(condition, vlevel, ...)\ + CVERBOSE_IF(el::base::Writer, condition, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) + // Hit counts based logs +#define CLOG_EVERY_N(n, LEVEL, ...)\ + C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_EVERY_N(n, vlevel, ...)\ + CVERBOSE_EVERY_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CLOG_AFTER_N(n, LEVEL, ...)\ + C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_AFTER_N(n, vlevel, ...)\ + CVERBOSE_AFTER_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CLOG_N_TIMES(n, LEVEL, ...)\ + C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_N_TIMES(n, vlevel, ...)\ + CVERBOSE_N_TIMES(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) + // + // Default Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros + // + // undef existing +#undef LOG +#undef VLOG +#undef LOG_IF +#undef VLOG_IF +#undef LOG_EVERY_N +#undef VLOG_EVERY_N +#undef LOG_AFTER_N +#undef VLOG_AFTER_N +#undef LOG_N_TIMES +#undef VLOG_N_TIMES +#undef ELPP_CURR_FILE_LOGGER_ID +#if defined(ELPP_DEFAULT_LOGGER) +# define ELPP_CURR_FILE_LOGGER_ID ELPP_DEFAULT_LOGGER +#else +# define ELPP_CURR_FILE_LOGGER_ID el::base::consts::kDefaultLoggerId +#endif +#undef ELPP_TRACE +#define ELPP_TRACE CLOG(TRACE, ELPP_CURR_FILE_LOGGER_ID) + // Normal logs +#define LOG(LEVEL) CLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG(vlevel) CVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Conditional logs +#define LOG_IF(condition, LEVEL) CLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_IF(condition, vlevel) CVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Hit counts based logs +#define LOG_EVERY_N(n, LEVEL) CLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_EVERY_N(n, vlevel) CVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define LOG_AFTER_N(n, LEVEL) CLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_AFTER_N(n, vlevel) CVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define LOG_N_TIMES(n, LEVEL) CLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_N_TIMES(n, vlevel) CVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Generic PLOG() +#undef CPLOG +#undef CPLOG_IF +#undef PLOG +#undef PLOG_IF +#undef DCPLOG +#undef DCPLOG_IF +#undef DPLOG +#undef DPLOG_IF +#define CPLOG(LEVEL, ...)\ + C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CPLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::PErrorWriter, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define DCPLOG(LEVEL, ...)\ + if (ELPP_DEBUG_LOG) C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define DCPLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::PErrorWriter, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define PLOG(LEVEL) CPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define PLOG_IF(condition, LEVEL) CPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DPLOG(LEVEL) DCPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DPLOG_IF(condition, LEVEL) DCPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) + // Generic SYSLOG() +#undef CSYSLOG +#undef CSYSLOG_IF +#undef CSYSLOG_EVERY_N +#undef CSYSLOG_AFTER_N +#undef CSYSLOG_N_TIMES +#undef SYSLOG +#undef SYSLOG_IF +#undef SYSLOG_EVERY_N +#undef SYSLOG_AFTER_N +#undef SYSLOG_N_TIMES +#undef DCSYSLOG +#undef DCSYSLOG_IF +#undef DCSYSLOG_EVERY_N +#undef DCSYSLOG_AFTER_N +#undef DCSYSLOG_N_TIMES +#undef DSYSLOG +#undef DSYSLOG_IF +#undef DSYSLOG_EVERY_N +#undef DSYSLOG_AFTER_N +#undef DSYSLOG_N_TIMES +#if defined(ELPP_SYSLOG) +# define CSYSLOG(LEVEL, ...)\ + C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_EVERY_N(n, LEVEL, ...) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_AFTER_N(n, LEVEL, ...) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_N_TIMES(n, LEVEL, ...) C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define SYSLOG(LEVEL) CSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_IF(condition, LEVEL) CSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_EVERY_N(n, LEVEL) CSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_AFTER_N(n, LEVEL) CSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_N_TIMES(n, LEVEL) CSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define DCSYSLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::Writer, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_EVERY_N(n, LEVEL, ...)\ + if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_AFTER_N(n, LEVEL, ...)\ + if (ELPP_DEBUG_LOG) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_N_TIMES(n, LEVEL, ...)\ + if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DSYSLOG(LEVEL) DCSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_IF(condition, LEVEL) DCSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_EVERY_N(n, LEVEL) DCSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_AFTER_N(n, LEVEL) DCSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_N_TIMES(n, LEVEL) DCSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) +#else +# define CSYSLOG(LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() +# define SYSLOG(LEVEL) el::base::NullWriter() +# define SYSLOG_IF(condition, LEVEL) el::base::NullWriter() +# define SYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() +# define SYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() +# define SYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() +# define DCSYSLOG(LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() +# define DSYSLOG(LEVEL) el::base::NullWriter() +# define DSYSLOG_IF(condition, LEVEL) el::base::NullWriter() +# define DSYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() +# define DSYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() +# define DSYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() +#endif // defined(ELPP_SYSLOG) + // + // Custom Debug Only Loggers - Requires (level, loggerId/s) + // + // undef existing +#undef DCLOG +#undef DCVLOG +#undef DCLOG_IF +#undef DCVLOG_IF +#undef DCLOG_EVERY_N +#undef DCVLOG_EVERY_N +#undef DCLOG_AFTER_N +#undef DCVLOG_AFTER_N +#undef DCLOG_N_TIMES +#undef DCVLOG_N_TIMES + // Normal logs +#define DCLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG(LEVEL, __VA_ARGS__) +#define DCLOG_VERBOSE(vlevel, ...) if (ELPP_DEBUG_LOG) CLOG_VERBOSE(vlevel, __VA_ARGS__) +#define DCVLOG(vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG(vlevel, __VA_ARGS__) + // Conditional logs +#define DCLOG_IF(condition, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_IF(condition, LEVEL, __VA_ARGS__) +#define DCVLOG_IF(condition, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_IF(condition, vlevel, __VA_ARGS__) + // Hit counts based logs +#define DCLOG_EVERY_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_EVERY_N(n, LEVEL, __VA_ARGS__) +#define DCVLOG_EVERY_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_EVERY_N(n, vlevel, __VA_ARGS__) +#define DCLOG_AFTER_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_AFTER_N(n, LEVEL, __VA_ARGS__) +#define DCVLOG_AFTER_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_AFTER_N(n, vlevel, __VA_ARGS__) +#define DCLOG_N_TIMES(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_N_TIMES(n, LEVEL, __VA_ARGS__) +#define DCVLOG_N_TIMES(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_N_TIMES(n, vlevel, __VA_ARGS__) + // + // Default Debug Only Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros + // + // undef existing +#undef DLOG +#undef DVLOG +#undef DLOG_IF +#undef DVLOG_IF +#undef DLOG_EVERY_N +#undef DVLOG_EVERY_N +#undef DLOG_AFTER_N +#undef DVLOG_AFTER_N +#undef DLOG_N_TIMES +#undef DVLOG_N_TIMES + // Normal logs +#define DLOG(LEVEL) DCLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG(vlevel) DCVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Conditional logs +#define DLOG_IF(condition, LEVEL) DCLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_IF(condition, vlevel) DCVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Hit counts based logs +#define DLOG_EVERY_N(n, LEVEL) DCLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_EVERY_N(n, vlevel) DCVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define DLOG_AFTER_N(n, LEVEL) DCLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_AFTER_N(n, vlevel) DCVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define DLOG_N_TIMES(n, LEVEL) DCLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_N_TIMES(n, vlevel) DCVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Check macros +#undef CCHECK +#undef CPCHECK +#undef CCHECK_EQ +#undef CCHECK_NE +#undef CCHECK_LT +#undef CCHECK_GT +#undef CCHECK_LE +#undef CCHECK_GE +#undef CCHECK_BOUNDS +#undef CCHECK_NOTNULL +#undef CCHECK_STRCASEEQ +#undef CCHECK_STRCASENE +#undef CHECK +#undef PCHECK +#undef CHECK_EQ +#undef CHECK_NE +#undef CHECK_LT +#undef CHECK_GT +#undef CHECK_LE +#undef CHECK_GE +#undef CHECK_BOUNDS +#undef CHECK_NOTNULL +#undef CHECK_STRCASEEQ +#undef CHECK_STRCASENE +#define CCHECK(condition, ...) CLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " +#define CPCHECK(condition, ...) CPLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " +#define CHECK(condition) CCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#define PCHECK(condition) CPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#define CCHECK_EQ(a, b, ...) CCHECK(a == b, __VA_ARGS__) +#define CCHECK_NE(a, b, ...) CCHECK(a != b, __VA_ARGS__) +#define CCHECK_LT(a, b, ...) CCHECK(a < b, __VA_ARGS__) +#define CCHECK_GT(a, b, ...) CCHECK(a > b, __VA_ARGS__) +#define CCHECK_LE(a, b, ...) CCHECK(a <= b, __VA_ARGS__) +#define CCHECK_GE(a, b, ...) CCHECK(a >= b, __VA_ARGS__) +#define CCHECK_BOUNDS(val, min, max, ...) CCHECK(val >= min && val <= max, __VA_ARGS__) +#define CHECK_EQ(a, b) CCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_NE(a, b) CCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_LT(a, b) CCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_GT(a, b) CCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_LE(a, b) CCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_GE(a, b) CCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_BOUNDS(val, min, max) CCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) +namespace el { + namespace base { + namespace utils { + template + static T* checkNotNull(T* ptr, const char* name, const char* loggers, ...) { + CLOG_IF(ptr == nullptr, FATAL, loggers) << "Check failed: [" << name << " != nullptr]"; + return ptr; + } + } // namespace utils + } // namespace base +} // namespace el +#define CCHECK_NOTNULL(ptr, ...) el::base::utils::checkNotNull(ptr, #ptr, __VA_ARGS__) +#define CCHECK_STREQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ + << "Check failed: [" << #str1 << " == " << #str2 << "] " +#define CCHECK_STRNE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ + << "Check failed: [" << #str1 << " != " << #str2 << "] " +#define CCHECK_STRCASEEQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ + << "Check failed: [" << #str1 << " == " << #str2 << "] " +#define CCHECK_STRCASENE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ + << "Check failed: [" << #str1 << " != " << #str2 << "] " +#define CHECK_NOTNULL(ptr) CCHECK_NOTNULL(ptr, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STREQ(str1, str2) CCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STRNE(str1, str2) CCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STRCASEEQ(str1, str2) CCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STRCASENE(str1, str2) CCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#undef DCCHECK +#undef DCCHECK_EQ +#undef DCCHECK_NE +#undef DCCHECK_LT +#undef DCCHECK_GT +#undef DCCHECK_LE +#undef DCCHECK_GE +#undef DCCHECK_BOUNDS +#undef DCCHECK_NOTNULL +#undef DCCHECK_STRCASEEQ +#undef DCCHECK_STRCASENE +#undef DCPCHECK +#undef DCHECK +#undef DCHECK_EQ +#undef DCHECK_NE +#undef DCHECK_LT +#undef DCHECK_GT +#undef DCHECK_LE +#undef DCHECK_GE +#undef DCHECK_BOUNDS_ +#undef DCHECK_NOTNULL +#undef DCHECK_STRCASEEQ +#undef DCHECK_STRCASENE +#undef DPCHECK +#define DCCHECK(condition, ...) if (ELPP_DEBUG_LOG) CCHECK(condition, __VA_ARGS__) +#define DCCHECK_EQ(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_EQ(a, b, __VA_ARGS__) +#define DCCHECK_NE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_NE(a, b, __VA_ARGS__) +#define DCCHECK_LT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LT(a, b, __VA_ARGS__) +#define DCCHECK_GT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GT(a, b, __VA_ARGS__) +#define DCCHECK_LE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LE(a, b, __VA_ARGS__) +#define DCCHECK_GE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GE(a, b, __VA_ARGS__) +#define DCCHECK_BOUNDS(val, min, max, ...) if (ELPP_DEBUG_LOG) CCHECK_BOUNDS(val, min, max, __VA_ARGS__) +#define DCCHECK_NOTNULL(ptr, ...) if (ELPP_DEBUG_LOG) CCHECK_NOTNULL(ptr, __VA_ARGS__) +#define DCCHECK_STREQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STREQ(str1, str2, __VA_ARGS__) +#define DCCHECK_STRNE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRNE(str1, str2, __VA_ARGS__) +#define DCCHECK_STRCASEEQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASEEQ(str1, str2, __VA_ARGS__) +#define DCCHECK_STRCASENE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASENE(str1, str2, __VA_ARGS__) +#define DCPCHECK(condition, ...) if (ELPP_DEBUG_LOG) CPCHECK(condition, __VA_ARGS__) +#define DCHECK(condition) DCCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_EQ(a, b) DCCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_NE(a, b) DCCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_LT(a, b) DCCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_GT(a, b) DCCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_LE(a, b) DCCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_GE(a, b) DCCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_BOUNDS(val, min, max) DCCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_NOTNULL(ptr) DCCHECK_NOTNULL(ptr, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STREQ(str1, str2) DCCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STRNE(str1, str2) DCCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STRCASEEQ(str1, str2) DCCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STRCASENE(str1, str2) DCCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DPCHECK(condition) DCPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#if defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) +# define ELPP_USE_DEF_CRASH_HANDLER false +#else +# define ELPP_USE_DEF_CRASH_HANDLER true +#endif // defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) +#define ELPP_CRASH_HANDLER_INIT +#define ELPP_INIT_EASYLOGGINGPP(val)\ + ELPP_INITI_BASIC_DECLR\ + namespace el {\ + namespace base {\ + el::base::type::StoragePointer elStorage(val);\ + }\ + el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ + } + +#if ELPP_ASYNC_LOGGING +# define INITIALIZE_EASYLOGGINGPP\ + ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()),\ + new el::base::AsyncDispatchWorker()))\ + +#else +# define INITIALIZE_EASYLOGGINGPP\ + ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()))) +#endif // ELPP_ASYNC_LOGGING +#define INITIALIZE_NULL_EASYLOGGINGPP\ + ELPP_INITI_BASIC_DECLR\ + namespace el {\ + namespace base {\ + el::base::type::StoragePointer elStorage;\ + }\ + el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ + } + // NOTE: no ELPP_INITI_BASIC_DECLR when sharing - causes double free corruption on external symbols +#define SHARE_EASYLOGGINGPP(initializedStorage)\ + namespace el {\ + namespace base {\ + el::base::type::StoragePointer elStorage(initializedStorage);\ + }\ + el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ + } + +#if defined(ELPP_UNICODE) +# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv); std::locale::global(std::locale("")) +#else +# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv) +#endif // defined(ELPP_UNICODE) +#endif // EASYLOGGINGPP_H \ No newline at end of file diff --git a/extensions/common/glm/CMakeLists.txt b/extensions/common/glm/CMakeLists.txt new file mode 100644 index 0000000000..fe28b5d975 --- /dev/null +++ b/extensions/common/glm/CMakeLists.txt @@ -0,0 +1,43 @@ +set(NAME glm_dummy) + +file(GLOB ROOT_SOURCE *.cpp) +file(GLOB ROOT_INLINE *.inl) +file(GLOB ROOT_HEADER *.hpp) +file(GLOB ROOT_TEXT ../*.txt) +file(GLOB ROOT_NAT ../util/glm.natvis) + +file(GLOB_RECURSE CORE_SOURCE ./detail/*.cpp) +file(GLOB_RECURSE CORE_INLINE ./detail/*.inl) +file(GLOB_RECURSE CORE_HEADER ./detail/*.hpp) + +file(GLOB_RECURSE GTC_SOURCE ./gtc/*.cpp) +file(GLOB_RECURSE GTC_INLINE ./gtc/*.inl) +file(GLOB_RECURSE GTC_HEADER ./gtc/*.hpp) + +file(GLOB_RECURSE GTX_SOURCE ./gtx/*.cpp) +file(GLOB_RECURSE GTX_INLINE ./gtx/*.inl) +file(GLOB_RECURSE GTX_HEADER ./gtx/*.hpp) + +source_group("Text Files" FILES ${ROOT_TEXT}) +source_group("Core Files" FILES ${CORE_SOURCE}) +source_group("Core Files" FILES ${CORE_INLINE}) +source_group("Core Files" FILES ${CORE_HEADER}) +source_group("GTC Files" FILES ${GTC_SOURCE}) +source_group("GTC Files" FILES ${GTC_INLINE}) +source_group("GTC Files" FILES ${GTC_HEADER}) +source_group("GTX Files" FILES ${GTX_SOURCE}) +source_group("GTX Files" FILES ${GTX_INLINE}) +source_group("GTX Files" FILES ${GTX_HEADER}) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) + +if(GLM_TEST_ENABLE) + add_executable(${NAME} ${ROOT_TEXT} ${ROOT_NAT} + ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} + ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} + ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} + ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER}) +endif(GLM_TEST_ENABLE) + +#add_library(glm STATIC glm.cpp) +#add_library(glm_shared SHARED glm.cpp) diff --git a/extensions/common/glm/common.hpp b/extensions/common/glm/common.hpp new file mode 100644 index 0000000000..57beb106a9 --- /dev/null +++ b/extensions/common/glm/common.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/common.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/func_common.hpp" diff --git a/extensions/common/glm/detail/_features.hpp b/extensions/common/glm/detail/_features.hpp new file mode 100644 index 0000000000..ce2a35d9c1 --- /dev/null +++ b/extensions/common/glm/detail/_features.hpp @@ -0,0 +1,428 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_features.hpp +/// @date 2013-02-20 / 2013-02-20 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// #define GLM_CXX98_EXCEPTIONS +// #define GLM_CXX98_RTTI + +// #define GLM_CXX11_RVALUE_REFERENCES +// Rvalue references - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html + +// GLM_CXX11_TRAILING_RETURN +// Rvalue references for *this - GCC not supported +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm + +// GLM_CXX11_NONSTATIC_MEMBER_INIT +// Initialization of class objects by rvalues - GCC any +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1610.html + +// GLM_CXX11_NONSTATIC_MEMBER_INIT +// Non-static data member initializers - GCC 4.7 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2756.htm + +// #define GLM_CXX11_VARIADIC_TEMPLATE +// Variadic templates - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf + +// +// Extending variadic template template parameters - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf + +// #define GLM_CXX11_GENERALIZED_INITIALIZERS +// Initializer lists - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm + +// #define GLM_CXX11_STATIC_ASSERT +// Static assertions - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html + +// #define GLM_CXX11_AUTO_TYPE +// auto-typed variables - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf + +// #define GLM_CXX11_AUTO_TYPE +// Multi-declarator auto - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1737.pdf + +// #define GLM_CXX11_AUTO_TYPE +// Removal of auto as a storage-class specifier - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2546.htm + +// #define GLM_CXX11_AUTO_TYPE +// New function declarator syntax - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm + +// #define GLM_CXX11_LAMBDAS +// New wording for C++0x lambdas - GCC 4.5 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2927.pdf + +// #define GLM_CXX11_DECLTYPE +// Declared type of an expression - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf + +// +// Right angle brackets - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html + +// +// Default template arguments for function templates DR226 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226 + +// +// Solving the SFINAE problem for expressions DR339 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html + +// #define GLM_CXX11_ALIAS_TEMPLATE +// Template aliases N2258 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf + +// +// Extern templates N1987 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm + +// #define GLM_CXX11_NULLPTR +// Null pointer constant N2431 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf + +// #define GLM_CXX11_STRONG_ENUMS +// Strongly-typed enums N2347 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf + +// +// Forward declarations for enums N2764 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf + +// +// Generalized attributes N2761 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf + +// +// Generalized constant expressions N2235 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf + +// +// Alignment support N2341 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf + +// #define GLM_CXX11_DELEGATING_CONSTRUCTORS +// Delegating constructors N1986 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf + +// +// Inheriting constructors N2540 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm + +// #define GLM_CXX11_EXPLICIT_CONVERSIONS +// Explicit conversion operators N2437 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf + +// +// New character types N2249 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html + +// +// Unicode string literals N2442 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm + +// +// Raw string literals N2442 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm + +// +// Universal character name literals N2170 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html + +// #define GLM_CXX11_USER_LITERALS +// User-defined literals N2765 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf + +// +// Standard Layout Types N2342 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm + +// #define GLM_CXX11_DEFAULTED_FUNCTIONS +// #define GLM_CXX11_DELETED_FUNCTIONS +// Defaulted and deleted functions N2346 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm + +// +// Extended friend declarations N1791 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf + +// +// Extending sizeof N2253 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html + +// #define GLM_CXX11_INLINE_NAMESPACES +// Inline namespaces N2535 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm + +// #define GLM_CXX11_UNRESTRICTED_UNIONS +// Unrestricted unions N2544 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf + +// #define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS +// Local and unnamed types as template arguments N2657 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm + +// #define GLM_CXX11_RANGE_FOR +// Range-based for N2930 GCC 4.6 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html + +// #define GLM_CXX11_OVERRIDE_CONTROL +// Explicit virtual overrides N2928 N3206 N3272 GCC 4.7 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm + +// +// Minimal support for garbage collection and reachability-based leak detection N2670 No +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2670.htm + +// #define GLM_CXX11_NOEXCEPT +// Allowing move constructors to throw [noexcept] N3050 GCC 4.6 (core language only) +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html + +// +// Defining move special member functions N3053 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html + +// +// Sequence points N2239 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html + +// +// Atomic operations N2427 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html + +// +// Strong Compare and Exchange N2748 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html + +// +// Bidirectional Fences N2752 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2752.htm + +// +// Memory model N2429 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2429.htm + +// +// Data-dependency ordering: atomics and memory model N2664 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm + +// +// Propagating exceptions N2179 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html + +// +// Abandoning a process and at_quick_exit N2440 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2440.htm + +// +// Allow atomics use in signal handlers N2547 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2547.htm + +// +// Thread-local storage N2659 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm + +// +// Dynamic initialization and destruction with concurrency N2660 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm + +// +// __func__ predefined identifier N2340 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2340.htm + +// +// C99 preprocessor N1653 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm + +// +// long long N1811 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1811.pdf + +// +// Extended integral types N1988 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf + +#if(GLM_COMPILER & GLM_COMPILER_GCC) + +# if(GLM_COMPILER >= GLM_COMPILER_GCC43) +# define GLM_CXX11_STATIC_ASSERT +# endif + +#elif(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) +# if(__has_feature(cxx_exceptions)) +# define GLM_CXX98_EXCEPTIONS +# endif + +# if(__has_feature(cxx_rtti)) +# define GLM_CXX98_RTTI +# endif + +# if(__has_feature(cxx_access_control_sfinae)) +# define GLM_CXX11_ACCESS_CONTROL_SFINAE +# endif + +# if(__has_feature(cxx_alias_templates)) +# define GLM_CXX11_ALIAS_TEMPLATE +# endif + +# if(__has_feature(cxx_alignas)) +# define GLM_CXX11_ALIGNAS +# endif + +# if(__has_feature(cxx_attributes)) +# define GLM_CXX11_ATTRIBUTES +# endif + +# if(__has_feature(cxx_constexpr)) +# define GLM_CXX11_CONSTEXPR +# endif + +# if(__has_feature(cxx_decltype)) +# define GLM_CXX11_DECLTYPE +# endif + +# if(__has_feature(cxx_default_function_template_args)) +# define GLM_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS +# endif + +# if(__has_feature(cxx_defaulted_functions)) +# define GLM_CXX11_DEFAULTED_FUNCTIONS +# endif + +# if(__has_feature(cxx_delegating_constructors)) +# define GLM_CXX11_DELEGATING_CONSTRUCTORS +# endif + +# if(__has_feature(cxx_deleted_functions)) +# define GLM_CXX11_DELETED_FUNCTIONS +# endif + +# if(__has_feature(cxx_explicit_conversions)) +# define GLM_CXX11_EXPLICIT_CONVERSIONS +# endif + +# if(__has_feature(cxx_generalized_initializers)) +# define GLM_CXX11_GENERALIZED_INITIALIZERS +# endif + +# if(__has_feature(cxx_implicit_moves)) +# define GLM_CXX11_IMPLICIT_MOVES +# endif + +# if(__has_feature(cxx_inheriting_constructors)) +# define GLM_CXX11_INHERITING_CONSTRUCTORS +# endif + +# if(__has_feature(cxx_inline_namespaces)) +# define GLM_CXX11_INLINE_NAMESPACES +# endif + +# if(__has_feature(cxx_lambdas)) +# define GLM_CXX11_LAMBDAS +# endif + +# if(__has_feature(cxx_local_type_template_args)) +# define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS +# endif + +# if(__has_feature(cxx_noexcept)) +# define GLM_CXX11_NOEXCEPT +# endif + +# if(__has_feature(cxx_nonstatic_member_init)) +# define GLM_CXX11_NONSTATIC_MEMBER_INIT +# endif + +# if(__has_feature(cxx_nullptr)) +# define GLM_CXX11_NULLPTR +# endif + +# if(__has_feature(cxx_override_control)) +# define GLM_CXX11_OVERRIDE_CONTROL +# endif + +# if(__has_feature(cxx_reference_qualified_functions)) +# define GLM_CXX11_REFERENCE_QUALIFIED_FUNCTIONS +# endif + +# if(__has_feature(cxx_range_for)) +# define GLM_CXX11_RANGE_FOR +# endif + +# if(__has_feature(cxx_raw_string_literals)) +# define GLM_CXX11_RAW_STRING_LITERALS +# endif + +# if(__has_feature(cxx_rvalue_references)) +# define GLM_CXX11_RVALUE_REFERENCES +# endif + +# if(__has_feature(cxx_static_assert)) +# define GLM_CXX11_STATIC_ASSERT +# endif + +# if(__has_feature(cxx_auto_type)) +# define GLM_CXX11_AUTO_TYPE +# endif + +# if(__has_feature(cxx_strong_enums)) +# define GLM_CXX11_STRONG_ENUMS +# endif + +# if(__has_feature(cxx_trailing_return)) +# define GLM_CXX11_TRAILING_RETURN +# endif + +# if(__has_feature(cxx_unicode_literals)) +# define GLM_CXX11_UNICODE_LITERALS +# endif + +# if(__has_feature(cxx_unrestricted_unions)) +# define GLM_CXX11_UNRESTRICTED_UNIONS +# endif + +# if(__has_feature(cxx_user_literals)) +# define GLM_CXX11_USER_LITERALS +# endif + +# if(__has_feature(cxx_variadic_templates)) +# define GLM_CXX11_VARIADIC_TEMPLATES +# endif + +#endif//(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) diff --git a/extensions/common/glm/detail/_fixes.hpp b/extensions/common/glm/detail/_fixes.hpp new file mode 100644 index 0000000000..9728cafb73 --- /dev/null +++ b/extensions/common/glm/detail/_fixes.hpp @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_fixes.hpp +/// @date 2011-02-21 / 2011-11-22 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include + +//! Workaround for compatibility with other libraries +#ifdef max +#undef max +#endif + +//! Workaround for compatibility with other libraries +#ifdef min +#undef min +#endif + +//! Workaround for Android +#ifdef isnan +#undef isnan +#endif + +//! Workaround for Android +#ifdef isinf +#undef isinf +#endif + +//! Workaround for Chrone Native Client +#ifdef log2 +#undef log2 +#endif + diff --git a/extensions/common/glm/detail/_noise.hpp b/extensions/common/glm/detail/_noise.hpp new file mode 100644 index 0000000000..296709d4b9 --- /dev/null +++ b/extensions/common/glm/detail/_noise.hpp @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_noise.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../common.hpp" + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_QUALIFIER T mod289(T const & x) + { + return x - floor(x * static_cast(1.0) / static_cast(289.0)) * static_cast(289.0); + } + + template + GLM_FUNC_QUALIFIER T permute(T const & x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER tvec2 permute(tvec2 const & x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER tvec3 permute(tvec3 const & x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER tvec4 permute(tvec4 const & x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } +/* + template class vecType> + GLM_FUNC_QUALIFIER vecType permute(vecType const & x) + { + return mod289(((x * T(34)) + T(1)) * x); + } +*/ + template + GLM_FUNC_QUALIFIER T taylorInvSqrt(T const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER tvec2 taylorInvSqrt(tvec2 const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER tvec3 taylorInvSqrt(tvec3 const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER tvec4 taylorInvSqrt(tvec4 const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } +/* + template class vecType> + GLM_FUNC_QUALIFIER vecType taylorInvSqrt(vecType const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } +*/ + + template + GLM_FUNC_QUALIFIER tvec2 fade(tvec2 const & t) + { + return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); + } + + template + GLM_FUNC_QUALIFIER tvec3 fade(tvec3 const & t) + { + return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); + } + + template + GLM_FUNC_QUALIFIER tvec4 fade(tvec4 const & t) + { + return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); + } +/* + template class vecType> + GLM_FUNC_QUALIFIER vecType fade(vecType const & t) + { + return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); + } +*/ +}//namespace detail +}//namespace glm + diff --git a/extensions/common/glm/detail/_swizzle.hpp b/extensions/common/glm/detail/_swizzle.hpp new file mode 100644 index 0000000000..04ea55bcf2 --- /dev/null +++ b/extensions/common/glm/detail/_swizzle.hpp @@ -0,0 +1,833 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_swizzle.hpp +/// @date 2006-04-20 / 2011-02-16 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +namespace glm{ +namespace detail +{ + // Internal class for implementing swizzle operators + template + struct _swizzle_base0 + { + typedef T value_type; + + protected: + GLM_FUNC_QUALIFIER value_type& elem (size_t i) { return (reinterpret_cast(_buffer))[i]; } + GLM_FUNC_QUALIFIER const value_type& elem (size_t i) const { return (reinterpret_cast(_buffer))[i]; } + + // Use an opaque buffer to *ensure* the compiler doesn't call a constructor. + // The size 1 buffer is assumed to aligned to the actual members so that the + // elem() + char _buffer[1]; + }; + + template + struct _swizzle_base1 : public _swizzle_base0 + { + }; + + template + struct _swizzle_base1 : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1)); } + }; + + template + struct _swizzle_base1 : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1), this->elem(E2)); } + }; + + template + struct _swizzle_base1 : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1), this->elem(E2), this->elem(E3)); } + }; + + // Internal class for implementing swizzle operators + /* + Template parameters: + + ValueType = type of scalar values (e.g. float, double) + VecType = class the swizzle is applies to (e.g. tvec3) + N = number of components in the vector (e.g. 3) + E0...3 = what index the n-th element of this swizzle refers to in the unswizzled vec + + DUPLICATE_ELEMENTS = 1 if there is a repeated element, 0 otherwise (used to specialize swizzles + containing duplicate elements so that they cannot be used as r-values). + */ + template + struct _swizzle_base2 : public _swizzle_base1 + { + typedef VecType vec_type; + typedef ValueType value_type; + + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const ValueType& t) + { + for (int i = 0; i < N; ++i) + (*this)[i] = t; + return *this; + } + + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e = t; } + }; + _apply_op(that, op()); + return *this; + } + + GLM_FUNC_QUALIFIER void operator -= (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e -= t; } + }; + _apply_op(that, op()); + } + + GLM_FUNC_QUALIFIER void operator += (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e += t; } + }; + _apply_op(that, op()); + } + + GLM_FUNC_QUALIFIER void operator *= (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e *= t; } + }; + _apply_op(that, op()); + } + + GLM_FUNC_QUALIFIER void operator /= (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e /= t; } + }; + _apply_op(that, op()); + } + + GLM_FUNC_QUALIFIER value_type& operator[] (size_t i) + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + + protected: + template + GLM_FUNC_QUALIFIER void _apply_op(const VecType& that, T op) + { + // Make a copy of the data in this == &that. + // The copier should optimize out the copy in cases where the function is + // properly inlined and the copy is not necessary. + ValueType t[N]; + for (int i = 0; i < N; ++i) + t[i] = that[i]; + for (int i = 0; i < N; ++i) + op( (*this)[i], t[i] ); + } + }; + + // Specialization for swizzles containing duplicate elements. These cannot be modified. + template + struct _swizzle_base2 : public _swizzle_base1 + { + typedef VecType vec_type; + typedef ValueType value_type; + + struct Stub {}; + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (Stub const &) { return *this; } + + GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + }; + + template + struct _swizzle : public _swizzle_base2 + { + typedef _swizzle_base2 base_type; + + using base_type::operator=; + + GLM_FUNC_QUALIFIER operator VecType () const { return (*this)(); } + }; + +// +// To prevent the C++ syntax from getting entirely overwhelming, define some alias macros +// +#define _GLM_SWIZZLE_TEMPLATE1 template +#define _GLM_SWIZZLE_TEMPLATE2 template +#define _GLM_SWIZZLE_TYPE1 _swizzle +#define _GLM_SWIZZLE_TYPE2 _swizzle + +// +// Wrapper for a binary operator (e.g. u.yy + v.zy) +// +#define _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ + _GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \ + { \ + return a() OPERAND b(); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const V& b) \ + { \ + return a() OPERAND b; \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const V& a, const _GLM_SWIZZLE_TYPE1& b) \ + { \ + return a OPERAND b(); \ + } + +// +// Wrapper for a operand between a swizzle and a binary (e.g. 1.0f - u.xyz) +// +#define _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const T& b) \ + { \ + return a() OPERAND b; \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const T& a, const _GLM_SWIZZLE_TYPE1& b) \ + { \ + return a OPERAND b(); \ + } + +// +// Macro for wrapping a function taking one argument (e.g. abs()) +// +#define _GLM_SWIZZLE_FUNCTION_1_ARGS(RETURN_TYPE,FUNCTION) \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a) \ + { \ + return FUNCTION(a()); \ + } + +// +// Macro for wrapping a function taking two vector arguments (e.g. dot()). +// +#define _GLM_SWIZZLE_FUNCTION_2_ARGS(RETURN_TYPE,FUNCTION) \ + _GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \ + { \ + return FUNCTION(a(), b()); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE1& b) \ + { \ + return FUNCTION(a(), b()); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const typename V& b) \ + { \ + return FUNCTION(a(), b); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const V& a, const _GLM_SWIZZLE_TYPE1& b) \ + { \ + return FUNCTION(a, b()); \ + } + +// +// Macro for wrapping a function take 2 vec arguments followed by a scalar (e.g. mix()). +// +#define _GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(RETURN_TYPE,FUNCTION) \ + _GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b, const T& c) \ + { \ + return FUNCTION(a(), b(), c); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE1& b, const T& c) \ + { \ + return FUNCTION(a(), b(), c); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const typename S0::vec_type& b, const T& c)\ + { \ + return FUNCTION(a(), b, c); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const typename V& a, const _GLM_SWIZZLE_TYPE1& b, const T& c) \ + { \ + return FUNCTION(a, b(), c); \ + } + +}//namespace detail +}//namespace glm + +namespace glm +{ + namespace detail + { + _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(-) + _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(*) + _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(+) + _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(-) + _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(*) + _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(/) + } + + // + // Swizzles are distinct types from the unswizzled type. The below macros will + // provide template specializations for the swizzle types for the given functions + // so that the compiler does not have any ambiguity to choosing how to handle + // the function. + // + // The alternative is to use the operator()() when calling the function in order + // to explicitly convert the swizzled type to the unswizzled type. + // + + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, abs); + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acos); + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acosh); + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, all); + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, any); + + //_GLM_SWIZZLE_FUNCTION_2_ARGS(value_type, dot); + //_GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, cross); + //_GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, step); + //_GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(vec_type, mix); +} + +#define _GLM_SWIZZLE2_2_MEMBERS(T, P, V, E0,E1) \ + struct { detail::_swizzle<2, T, P, V, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2, T, P, V, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2, T, P, V, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2, T, P, V, 1,1,-1,-2> E1 ## E1; }; + +#define _GLM_SWIZZLE2_3_MEMBERS(T, P, V, E0,E1) \ + struct { detail::_swizzle<3,T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 1,1,1,-1> E1 ## E1 ## E1; }; + +#define _GLM_SWIZZLE2_4_MEMBERS(T, P, V, E0,E1) \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; + +#define _GLM_SWIZZLE3_2_MEMBERS(T, P, V, E0,E1,E2) \ + struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; + +#define _GLM_SWIZZLE3_3_MEMBERS(T, P, V ,E0,E1,E2) \ + struct { detail::_swizzle<3,T,P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,2,-1> E2 ## E2 ## E2; }; + +#define _GLM_SWIZZLE3_4_MEMBERS(T, P, V, E0,E1,E2) \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; + +#define _GLM_SWIZZLE4_2_MEMBERS(T, P, V, E0,E1,E2,E3) \ + struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 0,3,-1,-2> E0 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 1,3,-1,-2> E1 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 2,3,-1,-2> E2 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V, 3,0,-1,-2> E3 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 3,1,-1,-2> E3 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 3,2,-1,-2> E3 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 3,3,-1,-2> E3 ## E3; }; + +#define _GLM_SWIZZLE4_3_MEMBERS(T,P, V, E0,E1,E2,E3) \ + struct { detail::_swizzle<3,T,P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,3,-1> E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,3,-1> E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,3,-1> E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 0,3,0,-1> E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,3,1,-1> E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,3,2,-1> E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,3,3,-1> E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,3,-1> E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,3,-1> E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,3,-1> E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 1,3,0,-1> E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,3,1,-1> E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,3,2,-1> E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,3,3,-1> E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,3,-1> E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,3,-1> E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,2,-1> E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,3,-1> E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 2,3,0,-1> E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,3,1,-1> E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,3,2,-1> E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,3,3,-1> E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 3,0,0,-1> E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 3,0,1,-1> E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 3,0,2,-1> E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 3,0,3,-1> E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 3,1,0,-1> E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 3,1,1,-1> E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 3,1,2,-1> E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 3,1,3,-1> E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 3,2,0,-1> E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 3,2,1,-1> E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 3,2,2,-1> E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 3,2,3,-1> E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 3,3,0,-1> E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 3,3,1,-1> E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 3,3,2,-1> E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 3,3,3,-1> E3 ## E3 ## E3; }; + +#define _GLM_SWIZZLE4_4_MEMBERS(T, P, V, E0,E1,E2,E3) \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,3> E0 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,3> E0 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,3> E0 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,0> E0 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,1> E0 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,2> E0 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,3> E0 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,3> E0 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,3> E0 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,3> E0 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,0> E0 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,1> E0 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,2> E0 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,3> E0 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,3> E0 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,3> E0 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,3> E0 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,0> E0 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,1> E0 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,2> E0 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,3> E0 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,0> E0 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,1> E0 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,2> E0 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,3> E0 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,0> E0 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,1> E0 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,2> E0 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,3> E0 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,0> E0 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,1> E0 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,2> E0 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,3> E0 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,0> E0 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,1> E0 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,2> E0 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,3> E0 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,3> E1 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,3> E1 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,3> E1 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,0> E1 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,1> E1 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,2> E1 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,3> E1 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,3> E1 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,3> E1 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,3> E1 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,0> E1 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,1> E1 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,2> E1 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,3> E1 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,3> E1 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,3> E1 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,3> E1 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,0> E1 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,1> E1 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,2> E1 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,3> E1 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,0> E1 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,1> E1 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,2> E1 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,3> E1 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,0> E1 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,1> E1 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,2> E1 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,3> E1 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,0> E1 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,1> E1 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,2> E1 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,3> E1 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,0> E1 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,1> E1 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,2> E1 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,3> E1 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,3> E2 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,3> E2 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,3> E2 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,0> E2 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,1> E2 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,2> E2 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,3> E2 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,3> E2 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,3> E2 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,3> E2 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,0> E2 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,1> E2 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,2> E2 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,3> E2 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,3> E2 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,3> E2 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,3> E2 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,0> E2 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,1> E2 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,2> E2 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,3> E2 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,0> E2 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,1> E2 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,2> E2 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,3> E2 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,0> E2 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,1> E2 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,2> E2 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,3> E2 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,0> E2 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,1> E2 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,2> E2 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,3> E2 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,0> E2 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,1> E2 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,2> E2 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,3> E2 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,0> E3 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,1> E3 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,2> E3 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,3> E3 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,0> E3 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,1> E3 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,2> E3 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,3> E3 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,0> E3 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,1> E3 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,2> E3 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,3> E3 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,0> E3 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,1> E3 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,2> E3 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,3> E3 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,0> E3 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,1> E3 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,2> E3 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,3> E3 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,0> E3 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,1> E3 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,2> E3 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,3> E3 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,0> E3 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,1> E3 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,2> E3 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,3> E3 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,0> E3 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,1> E3 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,2> E3 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,3> E3 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,0> E3 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,1> E3 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,2> E3 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,3> E3 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,0> E3 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,1> E3 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,2> E3 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,3> E3 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,0> E3 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,1> E3 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,2> E3 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,3> E3 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,0> E3 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,1> E3 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,2> E3 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,3> E3 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,0> E3 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,1> E3 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,2> E3 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,3> E3 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,0> E3 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,1> E3 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,2> E3 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,3> E3 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,0> E3 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,1> E3 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,2> E3 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,3> E3 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,0> E3 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,1> E3 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,2> E3 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,3> E3 ## E3 ## E3 ## E3; }; diff --git a/extensions/common/glm/detail/_swizzle_func.hpp b/extensions/common/glm/detail/_swizzle_func.hpp new file mode 100644 index 0000000000..4dbb783c5b --- /dev/null +++ b/extensions/common/glm/detail/_swizzle_func.hpp @@ -0,0 +1,725 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_swizzle_func.hpp +/// @date 2011-10-16 / 2011-10-16 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#define GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \ + SWIZZLED_TYPE A ## B() CONST \ + { \ + return SWIZZLED_TYPE(this->A, this->B); \ + } + +#define GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C) \ + SWIZZLED_TYPE A ## B ## C() CONST \ + { \ + return SWIZZLED_TYPE(this->A, this->B, this->C); \ + } + +#define GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C, D) \ + SWIZZLED_TYPE A ## B ## C ## D() CONST \ + { \ + return SWIZZLED_TYPE(this->A, this->B, this->C, this->D); \ + } + +#define GLM_SWIZZLE_GEN_VEC2_ENTRY_DEF(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \ + template \ + SWIZZLED_TYPE CLASS_TYPE::A ## B() CONST \ + { \ + return SWIZZLED_TYPE(this->A, this->B); \ + } + +#define GLM_SWIZZLE_GEN_VEC3_ENTRY_DEF(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C) \ + template \ + SWIZZLED_TYPE CLASS_TYPE::A ## B ## C() CONST \ + { \ + return SWIZZLED_TYPE(this->A, this->B, this->C); \ + } + +#define GLM_SWIZZLE_GEN_VEC4_ENTRY_DEF(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C, D) \ + template \ + SWIZZLED_TYPE CLASS_TYPE::A ## B ## C ## D() CONST \ + { \ + return SWIZZLED_TYPE(this->A, this->B, this->C, this->D); \ + } + +#define GLM_MUTABLE + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC2(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, x, y) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, r, g) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, s, t) + +//GLM_SWIZZLE_GEN_REF_FROM_VEC2(valType, detail::vec2, detail::ref2) + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B) + +#define GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC3(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, x, y, z) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, r, g, b) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, s, t, p) + +//GLM_SWIZZLE_GEN_REF_FROM_VEC3(valType, detail::vec3, detail::ref2, detail::ref3) + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, C) + +#define GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, B) + +#define GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, C, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC4(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z, w) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b, a) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p, q) + +//GLM_SWIZZLE_GEN_REF_FROM_VEC4(valType, detail::vec4, detail::ref2, detail::ref3, detail::ref4) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t) + +//GLM_SWIZZLE_GEN_VEC_FROM_VEC2(valType, detail::vec2, detail::vec2, detail::vec3, detail::vec4) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, C) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p) + +//GLM_SWIZZLE_GEN_VEC_FROM_VEC3(valType, detail::vec3, detail::vec2, detail::vec3, detail::vec4) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, D) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z, w) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b, a) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p, q) + +//GLM_SWIZZLE_GEN_VEC_FROM_VEC4(valType, detail::vec4, detail::vec2, detail::vec3, detail::vec4) diff --git a/extensions/common/glm/detail/_vectorize.hpp b/extensions/common/glm/detail/_vectorize.hpp new file mode 100644 index 0000000000..1deff1e080 --- /dev/null +++ b/extensions/common/glm/detail/_vectorize.hpp @@ -0,0 +1,160 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_vectorize.hpp +/// @date 2011-10-14 / 2011-10-14 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "type_vec1.hpp" +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "type_vec4.hpp" + +namespace glm{ +namespace detail +{ + template class vecType> + struct functor1{}; + + template + struct functor1 + { + GLM_FUNC_QUALIFIER static tvec1 call(R (*Func) (T x), tvec1 const & v) + { + return tvec1(Func(v.x)); + } + }; + + template + struct functor1 + { + GLM_FUNC_QUALIFIER static tvec2 call(R (*Func) (T x), tvec2 const & v) + { + return tvec2(Func(v.x), Func(v.y)); + } + }; + + template + struct functor1 + { + GLM_FUNC_QUALIFIER static tvec3 call(R (*Func) (T x), tvec3 const & v) + { + return tvec3(Func(v.x), Func(v.y), Func(v.z)); + } + }; + + template + struct functor1 + { + GLM_FUNC_QUALIFIER static tvec4 call(R (*Func) (T x), tvec4 const & v) + { + return tvec4(Func(v.x), Func(v.y), Func(v.z), Func(v.w)); + } + }; + + template class vecType> + struct functor2{}; + + template + struct functor2 + { + GLM_FUNC_QUALIFIER static tvec1 call(T (*Func) (T x, T y), tvec1 const & a, tvec1 const & b) + { + return tvec1(Func(a.x, b.x)); + } + }; + + template + struct functor2 + { + GLM_FUNC_QUALIFIER static tvec2 call(T (*Func) (T x, T y), tvec2 const & a, tvec2 const & b) + { + return tvec2(Func(a.x, b.x), Func(a.y, b.y)); + } + }; + + template + struct functor2 + { + GLM_FUNC_QUALIFIER static tvec3 call(T (*Func) (T x, T y), tvec3 const & a, tvec3 const & b) + { + return tvec3(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z)); + } + }; + + template + struct functor2 + { + GLM_FUNC_QUALIFIER static tvec4 call(T (*Func) (T x, T y), tvec4 const & a, tvec4 const & b) + { + return tvec4(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z), Func(a.w, b.w)); + } + }; + + template class vecType> + struct functor2_vec_sca{}; + + template + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static tvec1 call(T (*Func) (T x, T y), tvec1 const & a, T b) + { + return tvec1(Func(a.x, b)); + } + }; + + template + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static tvec2 call(T (*Func) (T x, T y), tvec2 const & a, T b) + { + return tvec2(Func(a.x, b), Func(a.y, b)); + } + }; + + template + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static tvec3 call(T (*Func) (T x, T y), tvec3 const & a, T b) + { + return tvec3(Func(a.x, b), Func(a.y, b), Func(a.z, b)); + } + }; + + template + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static tvec4 call(T (*Func) (T x, T y), tvec4 const & a, T b) + { + return tvec4(Func(a.x, b), Func(a.y, b), Func(a.z, b), Func(a.w, b)); + } + }; +}//namespace detail +}//namespace glm diff --git a/extensions/common/glm/detail/dummy.cpp b/extensions/common/glm/detail/dummy.cpp new file mode 100644 index 0000000000..88d8f3b807 --- /dev/null +++ b/extensions/common/glm/detail/dummy.cpp @@ -0,0 +1,232 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/core/dummy.cpp +/// @date 2011-01-19 / 2011-06-15 +/// @author Christophe Riccio +/// +/// GLM is a header only library. There is nothing to compile. +/// dummy.cpp exist only a wordaround for CMake file. +/////////////////////////////////////////////////////////////////////////////////// + +#define GLM_MESSAGES +#include +#include +#include + +struct material +{ + glm::vec4 emission; // Ecm + glm::vec4 ambient; // Acm + glm::vec4 diffuse; // Dcm + glm::vec4 specular; // Scm + float shininess; // Srm +}; + +struct light +{ + glm::vec4 ambient; // Acli + glm::vec4 diffuse; // Dcli + glm::vec4 specular; // Scli + glm::vec4 position; // Ppli + glm::vec4 halfVector; // Derived: Hi + glm::vec3 spotDirection; // Sdli + float spotExponent; // Srli + float spotCutoff; // Crli + // (range: [0.0,90.0], 180.0) + float spotCosCutoff; // Derived: cos(Crli) + // (range: [1.0,0.0],-1.0) + float constantAttenuation; // K0 + float linearAttenuation; // K1 + float quadraticAttenuation;// K2 +}; + + +// Sample 1 +#include // glm::vec3 +#include // glm::cross, glm::normalize + +glm::vec3 computeNormal +( + glm::vec3 const & a, + glm::vec3 const & b, + glm::vec3 const & c +) +{ + return glm::normalize(glm::cross(c - a, b - a)); +} + +typedef unsigned int GLuint; +#define GL_FALSE 0 +void glUniformMatrix4fv(GLuint, int, int, float*){} + +// Sample 2 +#include // glm::vec3 +#include // glm::vec4, glm::ivec4 +#include // glm::mat4 +#include // glm::translate, glm::rotate, glm::scale, glm::perspective +#include // glm::value_ptr +void func(GLuint LocationMVP, float Translate, glm::vec2 const & Rotate) +{ + glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.f); + glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Translate)); + glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f)); + glm::mat4 View = glm::rotate(ViewRotateX, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f)); + glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f)); + glm::mat4 MVP = Projection * View * Model; + glUniformMatrix4fv(LocationMVP, 1, GL_FALSE, glm::value_ptr(MVP)); +} + +// Sample 3 +#include // glm::vec2 +#include // glm::packUnorm2x16 +#include // glm::uint +#include // glm::i8vec2, glm::i32vec2 +std::size_t const VertexCount = 4; +// Float quad geometry +std::size_t const PositionSizeF32 = VertexCount * sizeof(glm::vec2); +glm::vec2 const PositionDataF32[VertexCount] = +{ + glm::vec2(-1.0f,-1.0f), + glm::vec2( 1.0f,-1.0f), + glm::vec2( 1.0f, 1.0f), + glm::vec2(-1.0f, 1.0f) + }; +// Half-float quad geometry +std::size_t const PositionSizeF16 = VertexCount * sizeof(glm::uint); +glm::uint const PositionDataF16[VertexCount] = +{ + glm::uint(glm::packUnorm2x16(glm::vec2(-1.0f, -1.0f))), + glm::uint(glm::packUnorm2x16(glm::vec2( 1.0f, -1.0f))), + glm::uint(glm::packUnorm2x16(glm::vec2( 1.0f, 1.0f))), + glm::uint(glm::packUnorm2x16(glm::vec2(-1.0f, 1.0f))) +}; +// 8 bits signed integer quad geometry +std::size_t const PositionSizeI8 = VertexCount * sizeof(glm::i8vec2); +glm::i8vec2 const PositionDataI8[VertexCount] = +{ + glm::i8vec2(-1,-1), + glm::i8vec2( 1,-1), + glm::i8vec2( 1, 1), + glm::i8vec2(-1, 1) +}; +// 32 bits signed integer quad geometry +std::size_t const PositionSizeI32 = VertexCount * sizeof(glm::i32vec2); +glm::i32vec2 const PositionDataI32[VertexCount] = +{ + glm::i32vec2 (-1,-1), + glm::i32vec2 ( 1,-1), + glm::i32vec2 ( 1, 1), + glm::i32vec2 (-1, 1) +}; + +struct intersection +{ + glm::vec4 position; + glm::vec3 normal; +}; + +/* +// Sample 4 +#include // glm::vec3 +#include // glm::normalize, glm::dot, glm::reflect +#include // glm::pow +#include // glm::vecRand3 +glm::vec3 lighting +( + intersection const & Intersection, + material const & Material, + light const & Light, + glm::vec3 const & View +) +{ + glm::vec3 Color(0.0f); + glm::vec3 LightVertor(glm::normalize( + Light.position - Intersection.position + + glm::vecRand3(0.0f, Light.inaccuracy)); + + if(!shadow(Intersection.position, Light.position, LightVertor)) + { + float Diffuse = glm::dot(Intersection.normal, LightVector); + if(Diffuse <= 0.0f) + return Color; + if(Material.isDiffuse()) + Color += Light.color() * Material.diffuse * Diffuse; + if(Material.isSpecular()) + { + glm::vec3 Reflect(glm::reflect( + glm::normalize(-LightVector), + glm::normalize(Intersection.normal))); + float Dot = glm::dot(Reflect, View); + float Base = Dot > 0.0f ? Dot : 0.0f; + float Specular = glm::pow(Base, Material.exponent); + Color += Material.specular * Specular; + } + } + return Color; +} +*/ + + +template class vecType> +T normalizeDotA(vecType const & x, vecType const & y) +{ + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); +} + +#define GLM_TEMPLATE_GENTYPE typename T, glm::precision P, template class + +template +T normalizeDotB(vecType const & x, vecType const & y) +{ + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); +} + +template +typename vecType::value_type normalizeDotC(vecType const & a, vecType const & b) +{ + return glm::dot(a, b) * glm::inversesqrt(glm::dot(a, a) * glm::dot(b, b)); +} + +int main() +{ + glm::vec1 o(1); + glm::vec2 a(1); + glm::vec3 b(1); + glm::vec4 c(1); + + glm::quat q; + glm::dualquat p; + + glm::mat4 m(1); + + float a0 = normalizeDotA(a, a); + float b0 = normalizeDotB(b, b); + float c0 = normalizeDotC(c, c); + + return 0; +} diff --git a/extensions/common/glm/detail/func_common.hpp b/extensions/common/glm/detail/func_common.hpp new file mode 100644 index 0000000000..da28007b05 --- /dev/null +++ b/extensions/common/glm/detail/func_common.hpp @@ -0,0 +1,456 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_common.hpp +/// @date 2008-03-08 / 2010-01-26 +/// @author Christophe Riccio +/// +/// @see GLSL 4.20.8 specification, section 8.3 Common Functions +/// +/// @defgroup core_func_common Common functions +/// @ingroup core +/// +/// These all operate component-wise. The description is per component. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" +#include "precision.hpp" +#include "type_int.hpp" +#include "_fixes.hpp" + +namespace glm +{ + /// @addtogroup core_func_common + /// @{ + + /// Returns x if x >= 0; otherwise, it returns -x. + /// + /// @tparam genType floating-point or signed integer; scalar or vector types. + /// + /// @see GLSL abs man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType abs(genType x); + + template class vecType> + GLM_FUNC_DECL vecType abs(vecType const & x); + + /// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0. + /// + /// @tparam genType Floating-point or signed integer; scalar or vector types. + /// + /// @see GLSL sign man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template class vecType> + GLM_FUNC_DECL vecType sign(vecType const & x); + + /// Returns a value equal to the nearest integer that is less then or equal to x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL floor man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template class vecType> + GLM_FUNC_DECL vecType floor(vecType const & x); + + /// Returns a value equal to the nearest integer to x + /// whose absolute value is not larger than the absolute value of x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL trunc man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template class vecType> + GLM_FUNC_DECL vecType trunc(vecType const & x); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// This includes the possibility that round(x) returns the + /// same value as roundEven(x) for all values of x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL round man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template class vecType> + GLM_FUNC_DECL vecType round(vecType const & x); + + /// Returns a value equal to the nearest integer to x. + /// A fractional part of 0.5 will round toward the nearest even + /// integer. (Both 3.5 and 4.5 for x will return 4.0.) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL roundEven man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + /// @see New round to even technique + template class vecType> + GLM_FUNC_DECL vecType roundEven(vecType const & x); + + /// Returns a value equal to the nearest integer + /// that is greater than or equal to x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL ceil man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template class vecType> + GLM_FUNC_DECL vecType ceil(vecType const & x); + + /// Return x - floor(x). + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL fract man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType fract(genType x); + + template class vecType> + GLM_FUNC_DECL vecType fract(vecType const & x); + + /// Modulus. Returns x - y * floor(x / y) + /// for each component in x using the floating point value y. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL mod man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType mod(genType x, genType y); + + template class vecType> + GLM_FUNC_DECL vecType mod(vecType const & x, T y); + + template class vecType> + GLM_FUNC_DECL vecType mod(vecType const & x, vecType const & y); + + /// Returns the fractional part of x and sets i to the integer + /// part (as a whole number floating point value). Both the + /// return value and the output parameter will have the same + /// sign as x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL modf man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType modf(genType x, genType & i); + + /// Returns y if y < x; otherwise, it returns x. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see GLSL min man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType min(genType x, genType y); + + template class vecType> + GLM_FUNC_DECL vecType min(vecType const & x, T y); + + template class vecType> + GLM_FUNC_DECL vecType min(vecType const & x, vecType const & y); + + /// Returns y if x < y; otherwise, it returns x. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see GLSL max man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType max(genType x, genType y); + + template class vecType> + GLM_FUNC_DECL vecType max(vecType const & x, T y); + + template class vecType> + GLM_FUNC_DECL vecType max(vecType const & x, vecType const & y); + + /// Returns min(max(x, minVal), maxVal) for each component in x + /// using the floating-point values minVal and maxVal. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see GLSL clamp man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType clamp(genType x, genType minVal, genType maxVal); + + template class vecType> + GLM_FUNC_DECL vecType clamp(vecType const & x, T minVal, T maxVal); + + template class vecType> + GLM_FUNC_DECL vecType clamp(vecType const & x, vecType const & minVal, vecType const & maxVal); + + /// If genTypeU is a floating scalar or vector: + /// Returns x * (1.0 - a) + y * a, i.e., the linear blend of + /// x and y using the floating-point value a. + /// The value for a is not restricted to the range [0, 1]. + /// + /// If genTypeU is a boolean scalar or vector: + /// Selects which vector each returned component comes + /// from. For a component of that is false, the + /// corresponding component of x is returned. For a + /// component of a that is true, the corresponding + /// component of y is returned. Components of x and y that + /// are not selected are allowed to be invalid floating point + /// values and will have no effect on the results. Thus, this + /// provides different functionality than + /// genType mix(genType x, genType y, genType(a)) + /// where a is a Boolean vector. + /// + /// @see GLSL mix man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + /// + /// @param[in] x Value to interpolate. + /// @param[in] y Value to interpolate. + /// @param[in] a Interpolant. + /// + /// @tparam genTypeT Floating point scalar or vector. + /// @tparam genTypeU Floating point or boolean scalar or vector. It can't be a vector if it is the length of genTypeT. + /// + /// @code + /// #include + /// ... + /// float a; + /// bool b; + /// glm::dvec3 e; + /// glm::dvec3 f; + /// glm::vec4 g; + /// glm::vec4 h; + /// ... + /// glm::vec4 r = glm::mix(g, h, a); // Interpolate with a floating-point scalar two vectors. + /// glm::vec4 s = glm::mix(g, h, b); // Teturns g or h; + /// glm::dvec3 t = glm::mix(e, f, a); // Types of the third parameter is not required to match with the first and the second. + /// glm::vec4 u = glm::mix(g, h, r); // Interpolations can be perform per component with a vector for the last parameter. + /// @endcode + template class vecType> + GLM_FUNC_DECL vecType mix(vecType const & x, vecType const & y, vecType const & a); + + template class vecType> + GLM_FUNC_DECL vecType mix(vecType const & x, vecType const & y, U a); + + template + GLM_FUNC_DECL genTypeT mix(genTypeT x, genTypeT y, genTypeU a); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0 for each component of a genType. + /// + /// @see GLSL step man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType step(genType edge, genType x); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0. + /// + /// @see GLSL step man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template