From 740e3ebc51e93d95940513f59b97abb6a4d46843 Mon Sep 17 00:00:00 2001 From: Warmist Date: Wed, 26 Jun 2013 01:18:26 +0300 Subject: [PATCH] Implemented building support. --- plugins/rendermax/renderer_light.cpp | 124 +++++++++++++++++++++++---- plugins/rendermax/renderer_light.hpp | 17 +++- plugins/rendermax/rendermax.lua | 61 ++++++++++++- 3 files changed, 181 insertions(+), 21 deletions(-) diff --git a/plugins/rendermax/renderer_light.cpp b/plugins/rendermax/renderer_light.cpp index f9b3f07e6..311d2c4ef 100644 --- a/plugins/rendermax/renderer_light.cpp +++ b/plugins/rendermax/renderer_light.cpp @@ -434,6 +434,14 @@ matLightDef* lightingEngineViewscreen::getMaterial(int matType,int matIndex) else return NULL; } +buildingLightDef* lightingEngineViewscreen::getBuilding(df::building* bld) +{ + auto it=buildingDefs.find(std::make_tuple((int)bld->getType(),(int)bld->getSubtype(),(int)bld->getCustomType())); + if(it!=buildingDefs.end()) + return &it->second; + else + return NULL; +} void lightingEngineViewscreen::applyMaterial(int tileId,const matLightDef& mat,float size, float thickness) { if(mat.isTransparent) @@ -636,6 +644,11 @@ void lightingEngineViewscreen::doOcupancyAndLights() df::tiletype type = b->tiletypeAt(gpos); df::tile_designation d = b->DesignationAt(gpos); + if(d.bits.hidden) + { + curCell=lightCell(0,0,0); + continue; // do not process hidden stuff + } //df::tile_occupancy o = b->OccupancyAt(gpos); df::tiletype_shape shape = ENUM_ATTR(tiletype,shape,type); df::tiletype_shape_basic basic_shape = ENUM_ATTR(tiletype_shape, basic_shape, shape); @@ -646,7 +659,7 @@ void lightingEngineViewscreen::doOcupancyAndLights() matLightDef* lightDef=getMaterial(mat.mat_type,mat.mat_index); if(!lightDef || !lightDef->isTransparent) lightDef=&matWall; - if(shape==df::tiletype_shape::BROOK_BED || d.bits.hidden ) + if(shape==df::tiletype_shape::BROOK_BED ) { curCell=lightCell(0,0,0); } @@ -778,34 +791,58 @@ void lightingEngineViewscreen::doOcupancyAndLights() for(size_t i = 0; i < df::global::world->buildings.all.size(); i++) { df::building *bld = df::global::world->buildings.all[i]; + if(window_z!=bld->z) continue; + if(bld->getBuildStage()getMaxBuildStage()) //only work if fully built + continue; + df::coord2d p1(bld->x1,bld->y1); df::coord2d p2(bld->x2,bld->y2); p1=worldToViewportCoord(p1,vp,window2d); p2=worldToViewportCoord(p1,vp,window2d); if(isInViewport(p1,vp)||isInViewport(p2,vp)) { + int tile=getIndex(p1.x,p1.y); //TODO multitile buildings. How they would work? df::building_type type = bld->getType(); - - if (type == df::enums::building_type::WindowGlass || type==df::enums::building_type::WindowGem) - { - applyMaterial(tile,bld->mat_type,bld->mat_index); - } - if (type == df::enums::building_type::Table) + buildingLightDef* def=getBuilding(bld); + if(!def) + continue; + if(def->poweredOnly && bld->isUnpowered()) + continue; + if(type==df::enums::building_type::Door) { - addLight(tile,candle); + df::building_doorst* door=static_cast(bld); + if(!door->door_flags.bits.closed) + continue; } - if (type==df::enums::building_type::Statue) + + + if(def->useMaterial) { - addLight(tile,torch); + matLightDef* mat=getMaterial(bld->mat_type,bld->mat_index); + if(!mat)mat=&matWall; + if(def->light.isEmiting) + { + addLight(tile,def->light.makeSource()); + } + else if(mat->isEmiting) + { + addLight(tile,mat->makeSource()); + } + if(def->light.isTransparent) + { + ocupancy[tile]*=def->light.transparency; + } + else + { + ocupancy[tile]*=mat->transparency; + } } - if(type==df::enums::building_type::Door) + else { - df::building_doorst* door=static_cast(bld); - if(door->door_flags.bits.closed) - applyMaterial(tile,bld->mat_type,bld->mat_index,1,&matWall); + applyMaterial(tile,def->light); } } } @@ -833,6 +870,10 @@ lightCell lua_parseLightCell(lua_State* L) //Lua::GetOutput(L)->print("got cell(%f,%f,%f)\n",ret.r,ret.g,ret.b); return ret; } +#define GETLUAFLAG(field,name) lua_getfield(L,-1,"flags");\ + if(lua_isnil(L,-1)){field=false;}\ + else{lua_getfield(L,-1,#name);field=lua_isnil(L,-1);lua_pop(L,1);}\ + lua_pop(L,1) matLightDef lua_parseMatDef(lua_State* L) { @@ -861,7 +902,10 @@ matLightDef lua_parseMatDef(lua_State* L) } else lua_pop(L,1); - //todo flags + GETLUAFLAG(ret.flicker,"flicker"); + GETLUAFLAG(ret.useThickness,"useThickness"); + GETLUAFLAG(ret.sizeModifiesPower,"sizeModifiesPower"); + GETLUAFLAG(ret.sizeModifiesRange,"sizeModifiesRange"); return ret; } int lightingEngineViewscreen::parseMaterials(lua_State* L) @@ -918,6 +962,48 @@ int lightingEngineViewscreen::parseSpecial(lua_State* L) return 0; } #undef LOAD_SPECIAL +int lightingEngineViewscreen::parseBuildings(lua_State* L) +{ + auto engine= (lightingEngineViewscreen*)lua_touserdata(L, 1); + engine->buildingDefs.clear(); + Lua::StackUnwinder unwinder(L); + lua_getfield(L,2,"buildings"); + if(!lua_istable(L,-1)) + { + luaL_error(L,"Buildings table not found."); + return 0; + } + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + int type=lua_tonumber(L,-2); + if(!lua_istable(L,-1)) + { + luaL_error(L,"Broken building definitions."); + } + //os->print("Processing type:%d\n",type); + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + int subtype=lua_tonumber(L,-2); + //os->print("\tProcessing subtype:%d\n",index); + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + int custom=lua_tonumber(L,-2); + //os->print("\tProcessing custom:%d\n",index); + buildingLightDef current; + current.light=lua_parseMatDef(L); + engine->buildingDefs[std::make_tuple(type,subtype,custom)]=current; + GETLUAFLAG(current.poweredOnly,"poweredOnly"); + GETLUAFLAG(current.useMaterial,"useMaterial"); + lua_pop(L, 1); + } + + lua_pop(L, 1); + } + lua_pop(L, 1); + } + lua_pop(L,1); + return 0; +} void lightingEngineViewscreen::defaultSettings() { matAmbience=matLightDef(lightCell(0.85f,0.85f,0.85f)); @@ -967,7 +1053,12 @@ void lightingEngineViewscreen::loadSettings() lua_pushlightuserdata(s, this); lua_pushvalue(s,env); Lua::SafeCall(out,s,2,0); - + + lua_pushcfunction(s, parseBuildings); + lua_pushlightuserdata(s, this); + lua_pushvalue(s,env); + Lua::SafeCall(out,s,2,0); + out.print("%d buildings loaded\n",buildingDefs.size()); } } @@ -978,3 +1069,4 @@ void lightingEngineViewscreen::loadSettings() } lua_pop(s,1); } +#undef GETLUAFLAG diff --git a/plugins/rendermax/renderer_light.hpp b/plugins/rendermax/renderer_light.hpp index 290863aee..556d53a68 100644 --- a/plugins/rendermax/renderer_light.hpp +++ b/plugins/rendermax/renderer_light.hpp @@ -3,6 +3,7 @@ #include "renderer_opengl.hpp" #include "Types.h" #include +#include #include "modules/MapCache.h" struct renderer_light : public renderer_wrap { @@ -99,11 +100,10 @@ struct lightSource }; struct matLightDef { - int mat_index; - int mat_type; bool isTransparent; lightCell transparency; bool isEmiting; + bool useThickness; bool sizeModifiesPower; bool sizeModifiesRange; bool flicker; @@ -120,6 +120,12 @@ struct matLightDef return lightSource(emitColor,radius); } }; +struct buildingLightDef +{ + matLightDef light; + bool poweredOnly; + bool useMaterial; +}; class lightingEngineViewscreen:public lightingEngine { public: @@ -147,10 +153,13 @@ private: bool addLight(int tileId,const lightSource& light); matLightDef* getMaterial(int matType,int matIndex); + buildingLightDef* getBuilding(df::building* bld); + //apply material to cell void applyMaterial(int tileId,const matLightDef& mat,float size=1, float thickness = 1); //try to find and apply material, if failed return false, and if def!=null then apply def. bool applyMaterial(int tileId,int matType,int matIndex,float size=1,const matLightDef* def=NULL); + size_t inline getIndex(int x,int y) { return x*h+y; @@ -181,6 +190,7 @@ private: static int parseMaterials(lua_State* L); static int parseSpecial(lua_State* L); + static int parseBuildings(lua_State* L); //special stuff matLightDef matLava; matLightDef matIce; @@ -192,7 +202,8 @@ private: float levelDim; //materials std::map,matLightDef> matDefs; - + //buildings + std::map,buildingLightDef> buildingDefs; int w,h; DFHack::rect2d mapPort; }; diff --git a/plugins/rendermax/rendermax.lua b/plugins/rendermax/rendermax.lua index 4e335ec86..785cb8b1d 100644 --- a/plugins/rendermax/rendermax.lua +++ b/plugins/rendermax/rendermax.lua @@ -8,8 +8,9 @@ for k,v in pairs(ret) do _ENV[k]=v end -- add material by id (index,mat pair or token string or a type number), flags is a table of strings --- supported flags: +-- supported flags (but not implemented): -- flicker +-- useThickness -- use thickness of stuff in transparency calculation -- sizeModifiesPower -- sizeModifiesRange function addMaterial(id,transparency,emitance,radius,flags) @@ -27,8 +28,58 @@ function addMaterial(id,transparency,emitance,radius,flags) materials[matinfo.type]=materials[matinfo.type] or {} materials[matinfo.type][matinfo.index]=makeMaterialDef(transparency,emitance,radius,flags) end +function buildingLookUp(id) + local tokens={} + local lookup={ Workshop=df.workshop_type,Furnace=df.furnace_type,Trap=df.trap_type, + SiegeEngine=siegeengine_type} + for i in string.gmatch(id, "[^:]+") do + table.insert(tokens,i) + end + local ret={} + ret.type=df.building_type[tokens[1]] + if tokens[2] then + local type_array=lookup[tokens[1]] + if type_array then + ret.subtype=type_array[tokens[2]] + end + if tokens[2]=="Custom" and tokens[3] then --TODO cache for faster lookup + if ret.type==df.building_type.Workshop then + for k,v in pairs(df.global.world.raws.buildings.workshops) do + if v.code==tokens[3] then + ret.custom=v.id + break + end + end + elseif ret.type==df.building_type.Furnace then + for k,v in pairs(df.global.world.raws.buildings.furnaces) do + if v.code==tokens[3] then + ret.custom=v.id + break + end + end + end + end + end + return ret +end +-- add building by id (string e.g. "Statue" or "Workshop:Masons", flags is a table of strings +-- supported flags: +-- useMaterial --uses material, but the defined things overwrite +-- poweredOnly --glow only when powered function addBuilding(id,transparency,emitance,radius,flags) - --stuff + local bld=buildingLookUp(id) + local mat=makeMaterialDef(transparency,emitance,radius,flags) + buildings[bld.type]=buildings[bld.type] or {} + if bld.subtype then + if bld.custom then + buildings[bld.type][bld.subtype]=buildings[bld.type][bld.subtype] or {} + buildings[bld.type][bld.subtype][bld.custom]=mat + else + buildings[bld.type][bld.subtype]={[-1]=mat} + end + else + buildings[bld.type][-1]={[-1]=mat} + end end function makeMaterialDef(transparency,emitance,radius,flags) local flg @@ -43,6 +94,7 @@ end ------------------------------------------------------------------------ ---------------- Configuration Starts Here ------------------------- ------------------------------------------------------------------------ +is_computer_quantum=false -- will enable more costly parts in the future --special things special.LAVA=makeMaterialDef({0.8,0.2,0.2},{0.8,0.2,0.2},5) special.WATER=makeMaterialDef({0.5,0.5,0.8}) @@ -71,3 +123,8 @@ addMaterial("INORGANIC:ADAMANTINE",{0.1,0.3,0.3},{0.1,0.3,0.3},4) addMaterial("CREATURE:DRAGON:BLOOD",nil,{0.6,0.1,0.1},4) -- TODO gems --buildings +addBuilding("Statue",{1,1,1},{0.9,0.75,0.3},8) +addBuilding("Bed",{1,1,1},{0.3,0.2,0.0},2) +addBuilding("WindowGlass",nil,nil,0,{"useMaterial"}) +addBuilding("WindowGem",nil,nil,0,{"useMaterial"}) +addBuilding("Door",nil,nil,0,{"useMaterial"}) -- special case, only closed door obstruct/emit light \ No newline at end of file