OpenClonk
C4MapScript.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2013-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Handles scripted map creation */
19 
20 #ifndef INC_C4MapScript
21 #define INC_C4MapScript
22 
24 #include "graphics/CSurface8.h"
25 #include "landscape/C4Landscape.h"
26 #include "lib/C4Rect.h"
27 #include "script/C4Aul.h"
28 #include "script/C4ScriptHost.h"
29 
30 bool FnParTexCol(C4String *mattex, uint8_t& fg, uint8_t& bg);
31 
32 // mattex masks: Array of bools for each possible material-texture index
34 {
35  std::vector<bool> sky_mask; // vector of size C4M_MaxTexIndex + 1: true means pixel color is let through; false means it is blocked
36  std::vector<bool> tunnel_mask; // vector of size C4M_MaxTexIndex + 1: true means pixel color is let through; false means it is blocked
37 
38  // sky_mask stores the mask for pixels with sky or transparent background, and tunnel_mask
39  // stores the mask for pixels with non-sky background. We don't allow
40  // different masks for different background materials since this would
41  // need a C4M_MaxTexIndex + 1 x C4M_MaxTexIndex + 1 matrix to account
42  // for each possible combination of foreground and background pixel.
43 
44  void UnmaskSpec(C4String *spec);
45 public:
46  C4MapScriptMatTexMask() : sky_mask(C4M_MaxTexIndex + 1,false), tunnel_mask(C4M_MaxTexIndex + 1, false) { }
47  C4MapScriptMatTexMask(const C4Value &spec) : sky_mask(C4M_MaxTexIndex + 1, false), tunnel_mask(C4M_MaxTexIndex + 1, false) { Init(spec); }
48  void Init(const C4Value &spec);
49 
50  bool operator()(uint8_t fg, uint8_t bg) const { if (bg == C4M_MaxTexIndex) return sky_mask[fg]; else return tunnel_mask[fg]; }
51 };
52 
53 // algorithms may be either indicator functions (int,int)->bool that tell whether a map pixel should be
54 // set (to be used in C4MapScriptLayer::Fill) or functions (int,int)->int that tell which material should
55 // be set (to be used in Fill or C4MapScriptLayer::Blit).
57 {
58 protected:
59  bool GetXYProps(const C4PropList *props, C4PropertyName k, int32_t *out_xy, bool zero_defaults);
60 public:
61  virtual bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const = 0;
62  virtual ~C4MapScriptAlgo() = default;
63 };
64 
65 // List of possible algorithms. Also registered as script constants in void C4MapScriptHost::InitFunctionMap.
67 {
69 
71 
73 
75  MAPALGO_Ellipsis = 21, // This is "MAPALGO_Ellipse", but misspelled. Use will result in a warning.
79 
81  MAPALGO_Or = 31,
84 
89 
92 };
93 
94 // MAPALGO_Layer: Just query pixel in layer. Pixels outside the layer range are zero.
96 {
97  const class C4MapScriptLayer *layer;
98 public:
99  C4MapScriptAlgoLayer(const C4MapScriptLayer *layer) : layer(layer) {}
100  C4MapScriptAlgoLayer(const C4PropList *props);
101 
102  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
103 };
104 
105 // MAPALGO_RndChecker: checkerboard on which areas are randomly set or unset
107 {
108  int32_t seed, set_percentage, checker_wdt, checker_hgt;
109  bool is_fixed_offset;
110 public:
112 
113  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
114 };
115 
116 // MAPALGO_Rect: 1 for pixels contained in rect, 0 otherwise
118 {
119  C4Rect rect;
120 public:
121  C4MapScriptAlgoRect(const C4PropList *props);
122 
123  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
124 };
125 
126 // MAPALGO_Ellipse: 1 for pixels within ellipse, 0 otherwise
128 {
129  int32_t cx,cy;
130  int32_t wdt,hgt;
131 public:
132  C4MapScriptAlgoEllipse(const C4PropList *props);
133 
134  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
135 };
136 
137 // MAPALGO_Polygon: 1 for pixels within polygon or on border, 0 otherwise
139 {
140  struct Pt { int32_t x,y; };
141  std::vector<Pt> poly;
142  int32_t wdt;
143  bool empty; // don't fill inside of polygon
144  bool open; // don't draw closing segment. only valid if empty=true
145 public:
146  C4MapScriptAlgoPolygon(const C4PropList *props);
147 
148  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
149 };
150 
151 // MAPALGO_Lines: 1 for pixels on stripes in direction ("X","Y"). Stripe distance "Distance". Optional offset "OffX", "OffY"
153 {
154  int32_t lx,ly,distance,ox,oy;
155  int64_t ll,dl; // (line width)^2 and distance * line width
156 public:
157  C4MapScriptAlgoLines(const C4PropList *props);
158 
159  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
160 };
161 
162 // base class for algo that takes one or more operands
164 {
165 protected:
166  std::vector<C4MapScriptAlgo *> operands;
167 public:
168  C4MapScriptAlgoModifier(const C4PropList *props, int32_t min_ops=0, int32_t max_ops=0);
169  ~C4MapScriptAlgoModifier() override { Clear(); }
170  void Clear();
171 };
172 
173 // MAPALGO_And: 0 if any of the operands is 0. Otherwise, returns value of last operand.
175 {
176 public:
178 
179  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
180 };
181 
182 // MAPALGO_Or: First nonzero operand
184 {
185 public:
187 
188  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
189 };
190 
191 // MAPALGO_Not: 1 if operand is 0, 0 otherwise.
193 {
194 public:
196 
197  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
198 };
199 
200 // MAPALGO_Xor: If exactly one of the two operands is nonzero, return it. Otherwise, return zero.
202 {
203 public:
205 
206  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
207 };
208 
209 // MAPALGO_Offset: Base layer shifted by ox,oy
211 {
212  int32_t ox,oy;
213 public:
214  C4MapScriptAlgoOffset(const C4PropList *props);
215 
216  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
217 };
218 
219 // MAPALGO_Scale: Base layer scaled by sx,sy percent from fixed point cx,cy
221 {
222  int32_t sx,sy,cx,cy;
223 public:
224  C4MapScriptAlgoScale(const C4PropList *props);
225 
226  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
227 };
228 
229 // MAPALGO_Rotate: Base layer rotated by angle r around point ox,oy
231 {
232  int32_t sr,cr,ox,oy;
233  enum {Precision=1000};
234 public:
235  C4MapScriptAlgoRotate(const C4PropList *props);
236 
237  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
238 };
239 
240 // MAPALGO_Turbulence: move by a random offset iterations times
242 {
243  int32_t amp[2], scale[2], seed, iterations;
244 public:
246 
247  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
248 };
249 
250 // MAPALGO_Border: Border of operand layer
252 {
253  int32_t left[2], top[2], right[2], bottom[2];
254  void ResolveBorderProps(int32_t *p);
255 public:
256  C4MapScriptAlgoBorder(const C4PropList *props);
257 
258  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
259 };
260 
261 // MAPALGO_Filter: Original color of operand if it's marked to go through filter. 0 otherwise.
263 {
264  C4MapScriptMatTexMask filter;
265 public:
266  C4MapScriptAlgoFilter(const C4PropList *props);
267 
268  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
269 };
270 
272  C4MapScriptAlgo *inner;
273  uint8_t fg, bg;
274 public:
275  C4MapScriptAlgoSetMaterial(C4MapScriptAlgo *inner, int fg, int bg);
276  ~C4MapScriptAlgoSetMaterial() override;
277  bool operator () (int32_t x, int32_t y, uint8_t& fg, uint8_t& bg) const override;
278 };
279 
280 // layer of a script-controlled map
281 // C4M_MaxTexIndex can be used to mark Sky
283 {
284  std::unique_ptr<CSurface8> fg_surface;
285  std::unique_ptr<CSurface8> bg_surface;
286 protected:
288 
289 public:
291  ~C4MapScriptLayer() override { ClearSurface(); }
292  C4MapScriptLayer * GetMapScriptLayer() override { return this; }
293  class C4MapScriptMap *GetMap() { return map; }
294 
295  // Surface management
296  bool CreateSurface(int32_t wdt, int32_t hgt);
297  void ClearSurface();
298  void SetSurfaces(std::unique_ptr<CSurface8> fg, std::unique_ptr<CSurface8> bg)
299  {
300  fg_surface = std::move(fg);
301  bg_surface = std::move(bg);
303  }
304  std::pair<std::unique_ptr<CSurface8>, std::unique_ptr<CSurface8>> ReleaseSurfaces()
305  {
306  return std::make_pair(std::move(fg_surface), std::move(bg_surface));
307  }
308  bool HasSurface() const { return fg_surface && fg_surface->Bits && bg_surface && bg_surface->Bits; }
309 
310  // Size management
311  void UpdateSurfaceSize(); // updates width and height properties by current surface
312  C4Rect GetBounds () const;
313  int32_t GetWdt() const { return fg_surface ? fg_surface->Wdt : 0; }
314  int32_t GetHgt() const { return fg_surface ? fg_surface->Hgt : 0; }
315 
316  // Pixel functions
317  uint8_t GetPix(int32_t x, int32_t y, uint8_t outside_col) const { return (!HasSurface()||x<0||y<0||x>=fg_surface->Wdt||y>=fg_surface->Hgt) ? outside_col : fg_surface->_GetPix(x,y); }
318  uint8_t GetBackPix(int32_t x, int32_t y, uint8_t outside_col) const { return (!HasSurface()||x<0||y<0||x>=bg_surface->Wdt||y>=bg_surface->Hgt) ? outside_col : bg_surface->_GetPix(x,y); }
319  bool SetPix(int32_t x, int32_t y, uint8_t fg, uint8_t bg) const { if (!HasSurface()||x<0||y<0||x>=bg_surface->Wdt||y>=bg_surface->Hgt) return false; fg_surface->_SetPix(x,y,fg); bg_surface->_SetPix(x,y,bg); return true; }
320  bool IsPixMasked(int32_t x, int32_t y) const { return GetPix(x,y,0) != 0 || GetBackPix(x,y,0) != 0; } // masking: If pixel is inside surface and not transparent
321  void ConvertSkyToTransparent(); // change all pixels that are C4M_MaxTexIndex to 0
322  int32_t GetPixCount(const C4Rect &rcBounds, const C4MapScriptMatTexMask &mask); // return number of pixels that match mask
323 
324  // Drawing functions
325  bool Fill(uint8_t fg, uint8_t bg, const C4Rect &rcBounds, const C4MapScriptAlgo *algo);
326  bool Blit(const C4Rect &rcBounds, const C4MapScriptAlgo *algo);
327  bool Blit(const C4MapScriptLayer *src, const C4Rect &src_rect, const C4MapScriptMatTexMask &mask, int32_t tx, int32_t ty);
328 
329  // Search functions
330  bool FindPos(const C4Rect &search_rect, const C4MapScriptMatTexMask &mask, int32_t *out_x, int32_t *out_y, int32_t max_tries);
331 };
332 
334 {
335  std::list<C4MapScriptLayer *> layers;
336 public:
337  C4MapScriptMap(C4PropList *prototype) : C4MapScriptLayer(prototype, nullptr) { map=this; }
338  ~C4MapScriptMap() override { Clear(); }
339  void Clear();
340  C4MapScriptMap * GetMapScriptMap() override { return this; }
341 
342  C4MapScriptLayer *CreateLayer(int32_t wdt, int32_t hgt);
343 };
344 
345 // Script host for scenario Map.c, parsed in static MapLayer prop list context
346 // Also hosts engine functions MapLayer prop list.
348 {
349 private:
350  C4PropListStaticMember *LayerPrototype{nullptr}, *MapPrototype{nullptr};
351 
352  C4MapScriptMap *CreateMap();
353 public:
355  ~C4MapScriptHost() override;
356  void InitFunctionMap(C4AulScriptEngine *pEngine);
357  void AddEngineFunctions() override;
358  bool Load(C4Group &, const char *, const char *, C4LangStringTable *) override;
359  bool LoadData(const char *, const char *, C4LangStringTable *) override;
360  void Clear();
361  C4PropListStatic * GetPropList() override;
362  bool InitializeMap(C4SLandscape *pLandscape, C4TextureMap *pTexMap, C4MaterialMap *pMatMap, uint32_t iPlayerCount, std::unique_ptr<CSurface8> *pmap_fg_surface, std::unique_ptr<CSurface8>* pmap_bg_surface);
363  C4PropListStatic *GetLayerPrototype() { return LayerPrototype; }
364 
367 };
368 
370 
371 #endif
const int C4M_MaxTexIndex
Definition: C4Constants.h:51
C4MapScriptHost MapScript
bool FnParTexCol(C4String *mattex, uint8_t &fg, uint8_t &bg)
Definition: C4MapScript.cpp:48
C4MapScriptAlgoType
Definition: C4MapScript.h:67
@ MAPALGO_Layer
Definition: C4MapScript.h:70
@ MAPALGO_Border
Definition: C4MapScript.h:90
@ MAPALGO_Ellipsis
Definition: C4MapScript.h:75
@ MAPALGO_Rect
Definition: C4MapScript.h:74
@ MAPALGO_Rotate
Definition: C4MapScript.h:87
@ MAPALGO_None
Definition: C4MapScript.h:68
@ MAPALGO_Turbulence
Definition: C4MapScript.h:88
@ MAPALGO_Or
Definition: C4MapScript.h:81
@ MAPALGO_Filter
Definition: C4MapScript.h:91
@ MAPALGO_Lines
Definition: C4MapScript.h:77
@ MAPALGO_Not
Definition: C4MapScript.h:82
@ MAPALGO_RndChecker
Definition: C4MapScript.h:72
@ MAPALGO_And
Definition: C4MapScript.h:80
@ MAPALGO_Scale
Definition: C4MapScript.h:86
@ MAPALGO_Xor
Definition: C4MapScript.h:83
@ MAPALGO_Polygon
Definition: C4MapScript.h:76
@ MAPALGO_Ellipse
Definition: C4MapScript.h:78
@ MAPALGO_Offset
Definition: C4MapScript.h:85
C4PropertyName
C4MapScriptAlgoAnd(const C4PropList *props)
Definition: C4MapScript.h:177
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoBorder(const C4PropList *props)
C4MapScriptAlgoEllipse(const C4PropList *props)
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoFilter(const C4PropList *props)
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
virtual bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const =0
bool GetXYProps(const C4PropList *props, C4PropertyName k, int32_t *out_xy, bool zero_defaults)
virtual ~C4MapScriptAlgo()=default
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoLayer(const C4MapScriptLayer *layer)
Definition: C4MapScript.h:99
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoLines(const C4PropList *props)
~C4MapScriptAlgoModifier() override
Definition: C4MapScript.h:169
C4MapScriptAlgoModifier(const C4PropList *props, int32_t min_ops=0, int32_t max_ops=0)
std::vector< C4MapScriptAlgo * > operands
Definition: C4MapScript.h:166
C4MapScriptAlgoNot(const C4PropList *props)
Definition: C4MapScript.h:195
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoOffset(const C4PropList *props)
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoOr(const C4PropList *props)
Definition: C4MapScript.h:186
C4MapScriptAlgoPolygon(const C4PropList *props)
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoRect(const C4PropList *props)
C4MapScriptAlgoRndChecker(const C4PropList *props)
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoRotate(const C4PropList *props)
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoScale(const C4PropList *props)
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoSetMaterial(C4MapScriptAlgo *inner, int fg, int bg)
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4MapScriptAlgoTurbulence(const C4PropList *props)
C4MapScriptAlgoXor(const C4PropList *props)
Definition: C4MapScript.h:204
bool operator()(int32_t x, int32_t y, uint8_t &fg, uint8_t &bg) const override
C4PropListStatic * GetLayerPrototype()
Definition: C4MapScript.h:363
C4MaterialMap * pMatMap
Definition: C4MapScript.h:366
bool InitializeMap(C4SLandscape *pLandscape, C4TextureMap *pTexMap, C4MaterialMap *pMatMap, uint32_t iPlayerCount, std::unique_ptr< CSurface8 > *pmap_fg_surface, std::unique_ptr< CSurface8 > *pmap_bg_surface)
C4PropListStatic * GetPropList() override
C4TextureMap * pTexMap
Definition: C4MapScript.h:365
void AddEngineFunctions() override
bool Load(C4Group &, const char *, const char *, C4LangStringTable *) override
bool LoadData(const char *, const char *, C4LangStringTable *) override
void InitFunctionMap(C4AulScriptEngine *pEngine)
~C4MapScriptHost() override
bool HasSurface() const
Definition: C4MapScript.h:308
int32_t GetHgt() const
Definition: C4MapScript.h:314
bool Fill(uint8_t fg, uint8_t bg, const C4Rect &rcBounds, const C4MapScriptAlgo *algo)
uint8_t GetPix(int32_t x, int32_t y, uint8_t outside_col) const
Definition: C4MapScript.h:317
C4MapScriptLayer * GetMapScriptLayer() override
Definition: C4MapScript.h:292
int32_t GetWdt() const
Definition: C4MapScript.h:313
bool SetPix(int32_t x, int32_t y, uint8_t fg, uint8_t bg) const
Definition: C4MapScript.h:319
C4MapScriptLayer(C4PropList *prototype, C4MapScriptMap *map)
~C4MapScriptLayer() override
Definition: C4MapScript.h:291
int32_t GetPixCount(const C4Rect &rcBounds, const C4MapScriptMatTexMask &mask)
C4Rect GetBounds() const
class C4MapScriptMap * GetMap()
Definition: C4MapScript.h:293
bool Blit(const C4Rect &rcBounds, const C4MapScriptAlgo *algo)
void UpdateSurfaceSize()
bool CreateSurface(int32_t wdt, int32_t hgt)
bool IsPixMasked(int32_t x, int32_t y) const
Definition: C4MapScript.h:320
void ConvertSkyToTransparent()
bool FindPos(const C4Rect &search_rect, const C4MapScriptMatTexMask &mask, int32_t *out_x, int32_t *out_y, int32_t max_tries)
void SetSurfaces(std::unique_ptr< CSurface8 > fg, std::unique_ptr< CSurface8 > bg)
Definition: C4MapScript.h:298
std::pair< std::unique_ptr< CSurface8 >, std::unique_ptr< CSurface8 > > ReleaseSurfaces()
Definition: C4MapScript.h:304
class C4MapScriptMap * map
Definition: C4MapScript.h:287
uint8_t GetBackPix(int32_t x, int32_t y, uint8_t outside_col) const
Definition: C4MapScript.h:318
~C4MapScriptMap() override
Definition: C4MapScript.h:338
C4MapScriptMap * GetMapScriptMap() override
Definition: C4MapScript.h:340
C4MapScriptLayer * CreateLayer(int32_t wdt, int32_t hgt)
C4MapScriptMap(C4PropList *prototype)
Definition: C4MapScript.h:337
void Init(const C4Value &spec)
bool operator()(uint8_t fg, uint8_t bg) const
Definition: C4MapScript.h:50
C4MapScriptMatTexMask(const C4Value &spec)
Definition: C4MapScript.h:47
Definition: C4Rect.h:28