1 /* 2 * OpenClonk, http://www.openclonk.org 3 * 4 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ 5 * Copyright (c) 2009-2016, The OpenClonk Team and contributors 6 * 7 * Distributed under the terms of the ISC license; see accompanying file 8 * "COPYING" for details. 9 * 10 * "Clonk" is a registered trademark of Matthes Bender, used with permission. 11 * See accompanying file "TRADEMARK" for details. 12 * 13 * To redistribute this file separately, substitute the full license texts 14 * for the above references. 15 */ 16 // complex dynamic landscape creator 17 18 #ifndef INC_C4MapCreatorS2 19 #define INC_C4MapCreatorS2 20 21 #define C4MC_SizeRes 100 // positions in percent 22 #define C4MC_ZoomRes 100 // zoom resolution (-100 to +99) 23 24 // string consts 25 #define C4MC_Overlay "overlay" // overlay node 26 #define C4MC_Point "point" // polygon point 27 #define C4MC_Map "map" // map node 28 29 #define C4MC_DefAlgo "solid" // default overlay algorithm 30 31 // error messages 32 #define C4MCErr_404 "file not found" 33 #define C4MCErr_NoGroup "internal error: no group" 34 35 #define C4MCErr_EOF "unexpected end of file" 36 #define C4MCErr_NoDirGlobal "can't use directives in local scope" 37 #define C4MCErr_UnknownDir "unknown directive: %s" 38 #define C4MCErr_MapNoGlobal "can't declare map in local scope" 39 #define C4MCErr_OpTypeErr "operator type mismatch" 40 #define C4MCErr_IdtfExp "identifier expected" 41 #define C4MCErr_UnnamedNoGlbl "unnamed objects not allowed in global scope" 42 #define C4MCErr_BlOpenExp "'{' expected" 43 #define C4MCErr_OpsNoGlobal "operators not allowed in global scope" 44 #define C4MCErr_SColonOrOpExp "';' or operator expected" 45 #define C4MCErr_Obj2Exp "second operand expected" 46 #define C4MCErr_ReinstNoGlobal "can't reinstanciate object '%s' in global scope" 47 #define C4MCErr_UnknownObj "unknown object: %s" 48 #define C4MCErr_ReinstUnknown "can't reinstanciate '%s'; object type is unknown" 49 #define C4MCErr_EqSColonBlOpenExp "'=', ';' or '{' expected" 50 #define C4MCErr_FieldConstExp "constant for field '%s' expected" 51 #define C4MCErr_SColonExp "';' expected" 52 #define C4MCErr_Field404 "field '%s' not found" 53 #define C4MCErr_FieldValInvalid "'%s' is not a valid value for this field" 54 #define C4MCErr_MatNotFound "material '%s' not found" 55 #define C4MCErr_TexNotFound "texture '%s' not found" 56 #define C4MCErr_AlgoNotFound "algorithm '%s' not found" 57 #define C4MCErr_SFuncNotFound "script func '%s' not found in scenario script" 58 #define C4MCErr_PointOnlyOvl "point only allowed in overlays" 59 #define C4MCErr_NoRecTemplate "cannot use template '%s' within itself" 60 61 // predef 62 class C4MCCallbackArray; 63 class C4MCCallbackArrayList; 64 class C4MCNode; 65 class C4MCOverlay; 66 class C4MCPoint; 67 class C4MCMap; 68 class C4MapCreatorS2; 69 class C4MCParserErr; 70 class C4MCParser; 71 72 struct C4MCAlgorithm 73 { 74 char Identifier[C4MaxName]; 75 bool (*Function) (C4MCOverlay*, int32_t, int32_t); 76 }; 77 78 extern C4MCAlgorithm C4MCAlgoMap[]; 79 80 // node type enum 81 enum C4MCNodeType { MCN_Node, MCN_Overlay, MCN_Point, MCN_Map }; 82 83 // one token type 84 enum C4MCTokenType 85 { 86 MCT_NONE, // nothing 87 MCT_DIR, // directive (stored in CurrTokenIdtf) 88 MCT_IDTF, // identifier (stored in CurrTokenIdtf) 89 MCT_INT, // integer constant (stored in CurrTokenVal) 90 MCT_EQ, // = 91 MCT_BLOPEN, // { 92 MCT_BLCLOSE,// } 93 MCT_SCOLON, // ; 94 MCT_AND, // & 95 MCT_OR, // | 96 MCT_XOR, // ^ 97 MCT_RANGE, // - 98 MCT_PERCENT,// integer constant (stored in CurrTokenVal) + % 99 MCT_PX, // integer constant (stored in CurrTokenVal) + px 100 MCT_EOF // end of file 101 }; 102 103 // a callback array 104 // contains a script func, and a map to call the func for 105 class C4MCCallbackArray 106 { 107 public: 108 C4MCCallbackArray(C4AulFunc *pSFunc, C4MapCreatorS2 *pMapCreator); // ctor 109 ~C4MCCallbackArray(); // dtor 110 111 protected: 112 C4MapCreatorS2 *pMapCreator; // map creator class to query current map of 113 BYTE *pMap; // bitmap whether or not to call the function for a map pixel 114 int32_t iWdt, iHgt; // size of the bitmap, when created 115 C4AulFunc *pSF; // script func to be called 116 117 C4MCCallbackArray *pNext; // next array in linked list 118 119 public: 120 void EnablePixel(int32_t iX, int32_t iY); // enable pixel in map; create map if necessary 121 void Execute(int32_t iMapZoom); // evaluate the array 122 123 friend class C4MCCallbackArrayList; 124 }; 125 126 // callback array list: contains all callbacks 127 class C4MCCallbackArrayList 128 { 129 public: C4MCCallbackArrayList()130 C4MCCallbackArrayList() { pFirst=nullptr; } // ctor ~C4MCCallbackArrayList()131 ~C4MCCallbackArrayList() { Clear(); } // ctor 132 133 protected: 134 C4MCCallbackArray *pFirst; // first array in list 135 136 public: 137 void Add(C4MCCallbackArray *pNewArray); // add given array to list 138 void Clear(); // clear the list 139 void Execute(int32_t iMapZoom);// execute all arrays 140 }; 141 142 // generic map creator tree node 143 // the code has been STL-free so far, so keep the line 144 class C4MCNode 145 { 146 public: 147 C4MCNode *Owner, *Child0, *ChildL, *Prev, *Next; // tree structure 148 C4MapCreatorS2 *MapCreator; // owning map creator 149 char Name[C4MaxName]; // name, if named 150 151 public: 152 C4MCNode(C4MCNode *pOwner=nullptr); // constructor 153 C4MCNode(C4MCParser* pParser, C4MCNode *pOwner, C4MCNode &rTemplate, bool fClone); // constructor using template 154 virtual ~C4MCNode(); // destructor 155 clone(C4MCParser * pParser,C4MCNode * pToNode)156 virtual C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) { return new C4MCNode(pParser, pToNode, *this, true); } 157 158 void Clear(); // clear all child nodes 159 void Reg2Owner(C4MCNode *pOwner); // register into list 160 161 protected: GlobalScope()162 virtual bool GlobalScope() { return false; } // whether node is a global scope SetOp(C4MCTokenType eOp)163 virtual bool SetOp(C4MCTokenType eOp) { return false; } // set following operator 164 C4MCNode *GetNodeByName(const char *szName); // search node by name 165 166 virtual bool SetField(C4MCParser *pParser, const char *szField, const char *szSVal, int32_t iVal, C4MCTokenType ValType); // set field 167 int32_t IntPar(C4MCParser *pParser, const char *szSVal, int32_t iVal, C4MCTokenType ValType); // ensure par is int32_t 168 const char *StrPar(C4MCParser *pParser, const char *szSVal, int32_t iVal, C4MCTokenType ValType); // ensure par is string 169 Evaluate()170 virtual void Evaluate() { } // called when all fields are initialized 171 void ReEvaluate(); // evaluate everything again 172 173 // For Percents and Pixels 174 class int_bool 175 { 176 public: Evaluate(int32_t relative_to)177 int32_t Evaluate(int32_t relative_to) 178 { if (percent) return value * relative_to / C4MC_SizeRes; else return value; } Set(int32_t value,bool percent)179 void Set(int32_t value, bool percent) 180 { this->value = value; this->percent = percent; } 181 private: 182 int32_t value; 183 bool percent; 184 }; 185 public: Type()186 virtual C4MCNodeType Type() { return MCN_Node; } // get node type Overlay()187 virtual C4MCOverlay *Overlay() { return nullptr; } // return overlay, if this is one 188 C4MCOverlay *OwnerOverlay(); // return an owner who is an overlay 189 190 friend class C4MCParser; 191 }; 192 193 // overlay node 194 class C4MCOverlay : public C4MCNode 195 { 196 public: 197 C4MCOverlay(C4MCNode *pOwner=nullptr); // constructor 198 C4MCOverlay(C4MCParser* pParser, C4MCNode *pOwner, C4MCOverlay &rTemplate, bool fClone); // construct of template 199 clone(C4MCParser * pParser,C4MCNode * pToNode)200 C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) override { return new C4MCOverlay(pParser, pToNode, *this, true); } 201 202 protected: 203 void Default(); // set default values for default presets 204 205 public: 206 int32_t Seed; // random seed 207 int32_t FixedSeed; // fixed random seed set in def 208 int32_t X,Y,Wdt,Hgt,OffX,OffY; // extends/offset 209 int_bool RX, RY, RWdt, RHgt, ROffX, ROffY; // extends/offset relatively to owner 210 int32_t Material; // material index 211 bool Sub; // tunnel bg? 212 char Texture[C4M_MaxName+1]; // texture name 213 BYTE MatClr; // resolved mat-tex color 214 BYTE MatClrBkg; // resolved mat-tex color 215 C4MCTokenType Op; // following operator 216 C4MCAlgorithm *Algorithm; // algorithm to calc whether filled or not 217 int32_t Turbulence, Lambda, Rotate; // turbulence factors; rotation angle 218 int_bool Alpha, Beta; // extra params 219 int32_t ZoomX, ZoomY; // zoom factor for algorithm 220 bool Invert, LooseBounds, Group, Mask; // extra algo behaviour 221 C4MCCallbackArray *pEvaluateFunc; // function called for nodes being evaluated and fulfilled 222 C4MCCallbackArray *pDrawFunc; // function called when this node is drawn - pass drawcolor as first param, return color to be actually used 223 SetOp(C4MCTokenType eOp)224 bool SetOp(C4MCTokenType eOp) override { Op=eOp; return true; } // set following operator 225 226 C4MCAlgorithm *GetAlgo(const char *szName); 227 228 bool SetField(C4MCParser *pParser, const char *szField, const char *szSVal, int32_t iVal, C4MCTokenType ValType) override; // set field 229 230 void Evaluate() override; // called when all fields are initialized 231 Overlay()232 C4MCOverlay *Overlay() override { return this; } // this is an overlay 233 C4MCOverlay *FirstOfChain(); // go backwards in op chain until first overlay of chain 234 235 bool CheckMask(int32_t iX, int32_t iY); // check whether algorithms succeeds at iX/iY 236 bool RenderPix(int32_t iX, int32_t iY, BYTE &rPix, BYTE &rPixBkg, C4MCTokenType eLastOp=MCT_NONE, bool fLastSet=false, bool fDraw=true, C4MCOverlay **ppPixelSetOverlay=nullptr); // render this pixel 237 bool PeekPix(int32_t iX, int32_t iY); // check mask; regard operator chain InBounds(int32_t iX,int32_t iY)238 bool InBounds(int32_t iX, int32_t iY) { return iX>=X && iY>=Y && iX<X+Wdt && iY<Y+Hgt; } // return whether point iX/iY is inside bounds 239 240 public: Type()241 C4MCNodeType Type() override { return MCN_Overlay; } // get node type 242 243 friend class C4MapCreatorS2; 244 friend class C4MCParser; 245 }; 246 247 // point of polygon node 248 class C4MCPoint : public C4MCNode 249 { 250 public: 251 C4MCPoint(C4MCNode *pOwner=nullptr); // constructor 252 C4MCPoint(C4MCParser* pParser, C4MCNode *pOwner, C4MCPoint &rTemplate, bool fClone); // construct of template 253 clone(C4MCParser * pParser,C4MCNode * pToNode)254 C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) override { return new C4MCPoint(pParser, pToNode, *this, true); } 255 256 protected: 257 void Default(); // set default values for default presets 258 259 public: 260 int32_t X,Y; 261 int_bool RX,RY; 262 263 void Evaluate() override; // called when all fields are initialized 264 bool SetField(C4MCParser *pParser, const char *szField, const char *szSVal, int32_t iVal, C4MCTokenType ValType) override; // set field 265 266 public: Type()267 C4MCNodeType Type() override { return MCN_Point; } // get node type 268 269 friend class C4MapCreatorS2; 270 friend class C4MCParser; 271 }; 272 273 // simply an overlay that can be rendered 274 class C4MCMap : public C4MCOverlay 275 { 276 public: 277 C4MCMap(C4MCNode *pOwner=nullptr); // constructor 278 C4MCMap(C4MCParser* pParser, C4MCNode *pOwner, C4MCMap &rTemplate, bool fClone); // construct of template 279 clone(C4MCParser * pParser,C4MCNode * pToNode)280 C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) override { return new C4MCMap(pParser, pToNode, *this, true); } 281 282 protected: 283 void Default(); // set default values for default presets 284 285 public: 286 bool RenderTo(BYTE *pToBuf, BYTE *pToBufBkg, int32_t iPitch); // render to buffer 287 void SetSize(int32_t iWdt, int32_t iHgt); 288 289 public: Type()290 C4MCNodeType Type() override { return MCN_Map; } // get node type 291 292 friend class C4MapCreatorS2; 293 friend class C4MCParser; 294 }; 295 296 // main map creator class 297 class C4MapCreatorS2 : public C4MCNode 298 { 299 public: 300 C4MapCreatorS2(C4SLandscape *pLandscape, C4TextureMap *pTexMap, C4MaterialMap *pMatMap, int iPlayerCount); // constructor 301 ~C4MapCreatorS2() override; // destructor 302 303 void Default(); // set default data 304 void Clear(); // clear any data 305 bool ReadFile(const char *szFilename, C4Group *pGrp); // read defs of file 306 bool ReadScript(const char *szScript); // reads def directly from mem 307 308 public: 309 C4MCMap *GetMap(const char *szMapName); // get map by name 310 311 public: 312 bool Render(const char *szMapName, CSurface8*& sfcMap, CSurface8*& sfcMapBkg); // create map surface 313 BYTE *RenderBuf(const char *szMapName, int32_t &sfcWdt, int32_t &sfcHgt); // create buffer and render it 314 SetC4SLandscape(C4SLandscape * pLandscape)315 void SetC4SLandscape(C4SLandscape *pLandscape) // update source for map size 316 { Landscape=pLandscape; } 317 318 protected: 319 C4SLandscape *Landscape; // landsape presets 320 C4TextureMap *TexMap; // texture map 321 C4MaterialMap *MatMap; // material map 322 C4MCMap DefaultMap; // default template: landscape 323 C4MCOverlay DefaultOverlay; // default template: overlay 324 C4MCPoint DefaultPoint; // default template: point 325 C4MCMap *pCurrentMap; // map currently rendered 326 C4MCCallbackArrayList CallbackArrays; // list of callback arrays 327 int PlayerCount; // player count for MapPlayerExtend 328 GlobalScope()329 bool GlobalScope() override { return true; } // it's the global node 330 331 public: ExecuteCallbacks(int32_t iMapZoom)332 void ExecuteCallbacks(int32_t iMapZoom) { CallbackArrays.Execute(iMapZoom); } 333 334 friend class C4MCOverlay; 335 friend class C4MCMap; 336 friend class C4MCParser; 337 friend class C4MCCallbackArray; 338 }; 339 340 341 // file parser for map creator 342 343 // parser error 344 class C4MCParserErr 345 { 346 public: 347 char Msg[C4MaxMessage]; // message string 348 349 C4MCParserErr(C4MCParser *pParser, const char *szMsg); // construct setting error msg 350 C4MCParserErr(C4MCParser *pParser, const char *szMsg, const char *szPar); // construct setting error msg 351 void show(); // log error 352 }; 353 354 // the parser 355 class C4MCParser 356 { 357 private: 358 C4MapCreatorS2 *MapCreator; // map creator parsing into 359 char *Code; // loaded code, can be nullptr if externally owned 360 const char *BPos; // Beginning of code 361 const char *CPos; // current parser pos in code 362 C4MCTokenType CurrToken; // last token read 363 char CurrTokenIdtf[C4MaxName]; // current token string 364 int32_t CurrTokenVal; // current token value 365 char Filename[C4MaxName]; // filename 366 367 bool AdvanceSpaces(); // advance to next token char; return whether EOF is reached 368 bool GetNextToken(); // get token, store in fields and advance to next; return whether not EOF 369 void ParseTo(C4MCNode *pToNode); // parse stuff into 370 void ParseValue(C4MCNode *pToNode, const char *szFieldName); // Set Field 371 372 public: 373 C4MCParser(C4MapCreatorS2 *pMapCreator); // constructor 374 ~C4MCParser(); // destructor 375 376 void Clear(); // clear stuff 377 378 void ParseFile(const char *szFilename, C4Group *pGrp); // load and parse file 379 void Parse(const char *szScript); // load and parse from mem 380 void ParseMemFile(const char *szScript, const char *szFilename); // parse file previosuly loaded into mem 381 382 friend class C4MCParserErr; 383 }; 384 385 #endif 386