1 /** 2 Component facilities module. 3 4 Copyright: © 2015-2016 Claude Merle 5 Authors: Claude Merle 6 License: This file is part of EntitySysD. 7 8 EntitySysD is free software: you can redistribute it and/or modify it 9 under the terms of the Lesser GNU General Public License as published 10 by the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 EntitySysD is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 Lesser GNU General Public License for more details. 17 18 You should have received a copy of the Lesser GNU General Public License 19 along with EntitySysD. If not, see $(LINK http://www.gnu.org/licenses/). 20 */ 21 22 module entitysysd.component; 23 24 // UDA for component types 25 enum component; 26 27 /** 28 * To be a valid component, $(D C) must: 29 * - be a $(D struct) or $(D union) 30 * - have the UDA $(D component) 31 * - must contain only mutable or const fields (no $(D immutable), $(D inout) or 32 * $(D shared) qualifiers) 33 */ 34 template isComponent(C) 35 { 36 import std.meta : allSatisfy; 37 import std.traits : RepresentationTypeTuple, isMutable, hasUDA; 38 39 enum bool isMutableOrConst(F) = isMutable!F || is(F == const); 40 static if (__traits(compiles, hasUDA!(C, component))) 41 enum bool isComponent = (is(C == struct) || is(C == union)) && 42 hasUDA!(C, component) && 43 allSatisfy!(isMutableOrConst, 44 RepresentationTypeTuple!C); 45 else 46 enum bool isComponent = false; 47 } 48 49 template areComponents(CList...) 50 { 51 import std.meta : allSatisfy; 52 enum bool areComponents = allSatisfy!(isComponent, CList); 53 } 54 55 56 struct BaseComponentCounter 57 { 58 static size_t counter = 0; 59 } 60 61 struct ComponentCounter(Derived) 62 { 63 public: 64 static size_t getId() 65 { 66 static size_t counter = -1; 67 if (counter == -1) 68 { 69 counter = mBaseComponentCounter.counter; 70 mBaseComponentCounter.counter++; 71 } 72 73 return counter; 74 } 75 76 private: 77 BaseComponentCounter mBaseComponentCounter; 78 } 79 80 81 //****************************************************************************** 82 //***** UNIT-TESTS 83 //****************************************************************************** 84 85 /// 86 unittest 87 { 88 @component struct TestComponent0 89 { 90 int a, b; 91 } 92 93 @component class TestComponent1 // component cannot be a class 94 { 95 string str; 96 } 97 98 @component union TestComponent2 99 { 100 float f; 101 uint u; 102 } 103 104 static assert(!isComponent!int); 105 static assert(isComponent!TestComponent0); 106 static assert(!isComponent!TestComponent1); 107 static assert(isComponent!TestComponent2); 108 }