31 static const char *DrawFn_Transparent_Name =
"Transparent";
32 static const char *DrawFn_Sky_Name =
"Sky";
33 static const char *DrawFn_Background_Name =
"Background";
34 static const char *DrawFn_Liquid_Name =
"Liquid";
35 static const char *DrawFn_Solid_Name =
"Solid";
39 if (
SEqual(mattex, DrawFn_Transparent_Name)) { col = 0;
return true; }
43 if (col == 0)
return false;
53 if (!mattex || !mattex->
GetCStr())
return false;
58 const char *cmattex = mattex->
GetCStr();
60 if (*cmattex ==
'^') { ift=
false; ++cmattex; }
75 const char *cmattex = mattex->
GetCStr();
76 std::string fg_mattex(cmattex, cmattex + sep_pos);
77 std::string bg_mattex(cmattex + sep_pos + 1);
79 uint8_t fg_col, bg_col;
80 if (!
TexColSingle(fg_mattex.c_str(), fg_col))
return false;
81 if (!
TexColSingle(bg_mattex.c_str(), bg_col))
return false;
83 fg = fg_col; bg = bg_col;
88 void C4MapScriptMatTexMask::UnmaskSpec(
C4String *spec)
104 if (!spec || !spec->
GetCStr())
return;
105 const char *cspec = spec->
GetCStr();
106 bool invert=
false, bgsky=
false, bgtunnel=
false, prefix_done=
false;
111 case '~': invert=!invert;
break;
112 case '^': bgsky=
true;
break;
113 case '&': bgtunnel=
true;
break;
114 default: prefix_done=
true;
break;
116 if (prefix_done)
break;
120 if (
SEqual(cspec, DrawFn_Transparent_Name))
125 else if (
SEqual(cspec, DrawFn_Sky_Name))
130 else if (
SEqual(cspec, DrawFn_Background_Name))
137 else if (
SEqual(cspec, DrawFn_Liquid_Name))
142 else if (
SEqual(cspec, DrawFn_Solid_Name))
147 else if (
SEqual(cspec,
"*"))
161 if (col) mat_mask[col] =
true;
169 const char *tex_name;
173 mat_mask[col] =
true;
181 if ((mat_mask[i] && (bgsky || !bgtunnel)) != invert)
183 if ((mat_mask[i] && (!bgsky || bgtunnel)) != invert)
184 tunnel_mask[i] =
true;
195 for (int32_t i=0; i<arr->
GetSize(); ++i)
210 if (spec)
throw C4AulExecError(
"MatTexMask expected string or array of strings.");
212 sky_mask = std::vector<bool>(256,
true);
213 tunnel_mask = std::vector<bool>(256,
true);
215 tunnel_mask[0] =
false;
227 if (!rect)
return true;
228 if (rect->
GetSize() != 4)
return false;
238 if (!layer || !
FnParTexCol(mattex, fg, bg))
return false;
240 if (!
FnParRect(layer, rect, &rcBounds))
return false;
241 std::unique_ptr<C4MapScriptAlgo> algo(
FnParAlgo(mask_algo));
242 return layer->
Fill(fg, bg, rcBounds, algo.get());
249 if (!layer)
return false;
251 if (!
FnParRect(layer, rect, &rcBounds))
return false;
252 std::unique_ptr<C4MapScriptAlgo> algo(
FnParAlgo(mask_algo));
253 if (!algo.get())
return false;
254 return layer->
Blit(rcBounds, algo.get());
261 uint8_t fg = 0, bg = 0;
262 if (mattex_fill && mattex_fill->
GetCStr())
267 if (!layer)
return nullptr;
268 if (!width && !height)
273 if (width<=0 || height<=0)
throw C4AulExecError(
FormatString(
"CreateLayer: Invalid size (%d*%d).", (
int)width, (
int)height).getData());
275 if (!map)
return nullptr;
277 if (fg != 0 || bg != 0) layer->
Fill(fg, bg, layer->
GetBounds(),
nullptr);
285 if (!layer)
return nullptr;
287 if (!map)
return nullptr;
290 if (!
FnParRect(layer, rect, &src_rect))
return nullptr;
291 if (!src_rect.
Wdt || !src_rect.
Hgt)
return nullptr;
293 new_layer->
Blit(layer, src_rect, mat_mask, 0,0);
299 if (!mattex)
return -1;
308 static int32_t FnLayerGetDefaultBackgroundIndex(
C4PropList * _this,
const C4Value &value)
313 if ((str = value.
getStr()))
328 static int32_t FnLayerGetPixel(
C4PropList * _this, int32_t x, int32_t y)
332 if (!layer)
return 0;
333 return layer->
GetPix(x,y,0);
336 static int32_t FnLayerGetBackPixel(
C4PropList * _this, int32_t x, int32_t y)
340 if (!layer)
return 0;
344 static bool FnLayerSetPixel(
C4PropList * _this, int32_t x, int32_t y,
const C4Value& fg_value_c4v,
const C4Value& bg_value_c4v)
348 if (!layer)
return false;
353 fg = layer->
GetPix(x,y,0);
357 const C4Value& val = fg_value_c4v;
362 throw C4AulExecError(
"MapLayer::SetPixel: Trying to set invalid pixel value.");
367 throw C4AulExecError(
"MapLayer::SetPixel: Trying to set invalid pixel value.");
378 const C4Value& val = bg_value_c4v;
383 throw C4AulExecError(
"MapLayer::SetPixel: Trying to set invalid pixel value.");
388 throw C4AulExecError(
"MapLayer::SetPixel: Trying to set invalid pixel value.");
393 return layer->
SetPix(x,y,fg,bg);
400 if (!layer)
return -1;
403 if (!
FnParRect(layer, rect, &check_rect))
return -1;
407 static bool FnLayerResize(
C4PropList * _this, int32_t new_wdt, int32_t new_hgt)
412 if (!layer || new_wdt<=0 || new_hgt<=0)
return false;
422 if (!layer)
return false;
425 if (!
FnParRect(layer, rect, &search_rect))
return false;
426 int32_t x,y;
bool result;
427 if (!max_tries) max_tries = 500;
428 if ((result = layer->
FindPos(search_rect, mat_mask, &x, &y, max_tries)))
430 if (out_pos && !out_pos->
IsFrozen())
463 if (wdt<=0 || hgt<=0)
return false;
464 fg_surface = std::make_unique<CSurface8>();
465 bg_surface = std::make_unique<CSurface8>();
466 if (!fg_surface->Create(wdt, hgt) || !bg_surface->Create(wdt, hgt))
477 fg_surface.reset(); bg_surface.reset();
496 for (int32_t y=0; y<fg_surface->Hgt; ++y)
498 for (int32_t x=0; x<fg_surface->Wdt; ++x)
501 fg_surface->_SetPix(x,y, 0);
504 bg_surface->_SetPix(x,y, 0);
512 return fg_surface ?
C4Rect(0,0,fg_surface->Wdt,fg_surface->Hgt) :
C4Rect();
518 uint8_t temp_fg, temp_bg;
520 assert(rcBounds.
x>=0 && rcBounds.
y>=0 && rcBounds.
x+rcBounds.
Wdt<=fg_surface->Wdt && rcBounds.
y+rcBounds.
Hgt<=fg_surface->Hgt);
522 for (int32_t y=rcBounds.
y; y<rcBounds.
y+rcBounds.
Hgt; ++y)
523 for (int32_t x=rcBounds.
x; x<rcBounds.
x+rcBounds.
Wdt; ++x)
524 if (!algo || (*algo)(x,y,temp_fg,temp_bg))
526 fg_surface->_SetPix(x,y,fg);
527 bg_surface->_SetPix(x,y,bg);
537 assert(rcBounds.
x>=0 && rcBounds.
y>=0 && rcBounds.
x+rcBounds.
Wdt<=fg_surface->Wdt && rcBounds.
y+rcBounds.
Hgt<=fg_surface->Hgt);
541 for (int32_t y=rcBounds.
y; y<rcBounds.
y+rcBounds.
Hgt; ++y)
542 for (int32_t x=rcBounds.
x; x<rcBounds.
x+rcBounds.
Wdt; ++x)
543 if (((*algo)(x,y,fg,bg)))
545 if (fg) fg_surface->_SetPix(x,y,fg);
546 if (bg) bg_surface->_SetPix(x,y,bg);
561 for (int32_t y=src_rect.
y; y<src_rect.
y+src_rect.
Hgt; ++y)
562 for (int32_t x=src_rect.
x; x<src_rect.
x+src_rect.
Wdt; ++x)
564 fg = src->fg_surface->_GetPix(x, y);
565 bg = src->bg_surface->_GetPix(x, y);
567 if (col_mask(fg, bg))
569 fg_surface->_SetPix(x-src_rect.
x+tx,y-src_rect.
y+ty,fg);
570 bg_surface->_SetPix(x-src_rect.
x+tx,y-src_rect.
y+ty,bg);
580 assert(rcBounds.
x>=0 && rcBounds.
y>=0 && rcBounds.
x+rcBounds.
Wdt<=fg_surface->Wdt && rcBounds.
y+rcBounds.
Hgt<=fg_surface->Hgt);
583 for (int32_t y=rcBounds.
y; y<rcBounds.
y+rcBounds.
Hgt; ++y)
584 for (int32_t x=rcBounds.
x; x<rcBounds.
x+rcBounds.
Wdt; ++x)
585 count += col_mask(fg_surface->_GetPix(x,y), bg_surface->_GetPix(x, y));
592 if (!
HasSurface() || search_rect.
Wdt<=0 || search_rect.
Hgt<=0)
return false;
594 for (int32_t i=0; i<max_tries; ++i)
596 int32_t x=search_rect.
x +
Random(search_rect.
Wdt);
597 int32_t y=search_rect.
y +
Random(search_rect.
Hgt);
598 if (col_mask(fg_surface->_GetPix(x,y), bg_surface->_GetPix(x,y))) { *out_x=x; *out_y=y;
return true; }
602 int32_t sx=search_rect.
x +
Random(search_rect.
Wdt);
603 int32_t sy=search_rect.
y +
Random(search_rect.
Hgt);
604 for (int32_t x = sx; x < search_rect.
x + search_rect.
Wdt; ++x)
605 if (col_mask(fg_surface->_GetPix(x,sy), bg_surface->_GetPix(x,sy))) { *out_x=x; *out_y=sy;
return true; }
606 for (int32_t y = sy + 1; y<search_rect.
y + search_rect.
Hgt; ++y)
607 for (int32_t x = search_rect.
x; x < search_rect.
x + search_rect.
Wdt; ++x)
608 if (col_mask(fg_surface->_GetPix(x,y), bg_surface->_GetPix(x,y))) { *out_x=x; *out_y=y;
return true; }
609 for (int32_t y = search_rect.
y; y<sy; ++y)
610 for (int32_t x = search_rect.
x; x < search_rect.
x + search_rect.
Wdt; ++x)
611 if (col_mask(fg_surface->_GetPix(x,y), bg_surface->_GetPix(x,y))) { *out_x=x; *out_y=y;
return true; }
612 for (int32_t x = search_rect.
x; x<sx; ++x)
613 if (col_mask(fg_surface->_GetPix(x,sy), bg_surface->_GetPix(x,sy))) { *out_x=x; *out_y=sy;
return true; }
621 for (
auto & layer : layers)
delete layer;
629 layers.push_back(new_layer);
632 layers.remove(new_layer);
650 LayerPrototype->
SetName(
"MapLayer");
681 ::AddFunc(p,
"CreateLayer", FnCreateLayer);
682 ::AddFunc(p,
"Duplicate", FnLayerDuplicate);
683 ::AddFunc(p,
"GetMaterialTextureIndex", FnLayerGetMaterialTextureIndex);
684 ::AddFunc(p,
"GetDefaultBackgroundIndex", FnLayerGetDefaultBackgroundIndex);
685 ::AddFunc(p,
"GetPixel", FnLayerGetPixel);
686 ::AddFunc(p,
"GetBackPixel", FnLayerGetBackPixel);
687 ::AddFunc(p,
"SetPixel", FnLayerSetPixel);
688 ::AddFunc(p,
"GetPixelCount", FnLayerGetPixelCount);
690 ::AddFunc(p,
"FindPosition", FnLayerFindPosition);
691 ::AddFunc(p,
"CreateMatTexMask", FnLayerCreateMatTexMask);
696 assert(LayerPrototype && MapPrototype);
702 assert(LayerPrototype && MapPrototype);
709 delete LayerPrototype;
delete MapPrototype;
710 LayerPrototype = MapPrototype =
nullptr;
716 return LayerPrototype;
727 assert(pmap_fg_surface);
728 assert(pmap_bg_surface);
739 std::unique_ptr<C4MapScriptMap> map(CreateMap());
742 if (*pmap_fg_surface && *pmap_bg_surface)
745 map->SetSurfaces(std::move(*pmap_fg_surface), std::move(*pmap_bg_surface));
749 assert(!*pmap_fg_surface && !*pmap_bg_surface);
751 int32_t map_wdt,map_hgt;
752 pLandscape->
GetMapSize(map_wdt, map_hgt, iPlayerCount);
753 if (!map->CreateSurface(map_wdt, map_hgt))
return false;
761 map->ConvertSkyToTransparent();
763 std::tie(*pmap_fg_surface, *pmap_bg_surface) = map->ReleaseSurfaces();
void AddFunc(C4PropListStatic *Parent, const char *Name, RType(*pFunc)(ThisType *, ParTypes...), bool Public=true)
const int C4M_MaxTexIndex
#define PSF_InitializeMap
C4AulScriptEngine ScriptEngine
bool DensitySolid(int32_t dens)
bool DensitySemiSolid(int32_t dens)
bool DensityLiquid(int32_t dens)
bool FnParRect(C4MapScriptLayer *layer, C4ValueArray *rect, C4Rect *rc_bounds)
C4MapScriptAlgo * FnParAlgo(C4PropList *algo_par)
C4MapScriptHost MapScript
bool TexColSingle(const char *mattex, uint8_t &col)
bool FnParTexCol(C4String *mattex, uint8_t &fg, uint8_t &bg)
C4GameScriptHost GameScript
C4Value C4VInt(int32_t i)
C4Value C4VPropList(C4PropList *p)
unsigned int SCharCount(char cTarget, const char *szInStr, const char *cpUntil)
int SCharPos(char cTarget, const char *szInStr, int iIndex)
bool SEqual(const char *szStr1, const char *szStr2)
bool Inside(T ival, U lbound, V rbound)
StdStrBuf FormatString(const char *szFmt,...)
C4PropListStatic * GetPropList()
void RegisterGlobalConstant(const char *szName, const C4Value &rValue)
C4Value Call(const char *szFunction, C4AulParSet *pPars=nullptr, bool fPassError=false)
int32_t GetPixDensity(BYTE byPix) const
C4PropListStatic * GetLayerPrototype()
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
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 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
bool SetPix(int32_t x, int32_t y, uint8_t fg, uint8_t bg) const
C4MapScriptLayer(C4PropList *prototype, C4MapScriptMap *map)
int32_t GetPixCount(const C4Rect &rcBounds, const C4MapScriptMatTexMask &mask)
class C4MapScriptMap * GetMap()
bool Blit(const C4Rect &rcBounds, const C4MapScriptAlgo *algo)
bool CreateSurface(int32_t wdt, int32_t hgt)
void ConvertSkyToTransparent()
bool FindPos(const C4Rect &search_rect, const C4MapScriptMatTexMask &mask, int32_t *out_x, int32_t *out_y, int32_t max_tries)
uint8_t GetBackPix(int32_t x, int32_t y, uint8_t outside_col) const
C4MapScriptLayer * CreateLayer(int32_t wdt, int32_t hgt)
void Init(const C4Value &spec)
int32_t Get(const char *szMaterial)
virtual void SetName(const char *NewName=nullptr)
C4AulFunc * GetFunc(C4PropertyName k) const
virtual class C4MapScriptLayer * GetMapScriptLayer()
void SetProperty(C4PropertyName k, const C4Value &to)
void Intersect(const C4Rect &r2)
void GetMapSize(int32_t &rWdt, int32_t &rHgt, int32_t iPlayerNum)
virtual bool Load(C4Group &hGroup, const char *szFilename, const char *szLanguage, C4LangStringTable *pLocalTable)
void Reg2List(C4AulScriptEngine *pEngine)
virtual bool LoadData(const char *szFilename, const char *szData, class C4LangStringTable *pLocalTable)
const char * GetCStr() const
C4String * RegString(StdStrBuf String)
int32_t GetIndex(const char *szMaterial, const char *szTexture, bool fAddIfNotExist=true, const char *szErrorIfFailed=nullptr)
int32_t GetIndexMatTex(const char *szMaterialTexture, const char *szDefaultTexture=nullptr, bool fAddIfNotExist=true, const char *szErrorIfFailed=nullptr)
BYTE DefaultBkgMatTex(BYTE fg) const
const char * GetTexture(int32_t iIndex)
const C4Value & GetItem(int32_t iElem) const
void SetItem(int32_t iElemNr, const C4Value &Value)
C4ValueArray * getArray() const
C4PropList * _getPropList() const
C4String * getStr() const