Implement lights, thanks @Tarjei400

Now otclient have lights! This code was originally made
by @Tarjei400, I have improved it and merged into otclient
master. Many thanks for tarjei for the contribution.

Warning, this still experimental, fixes may come in the next days.
This commit is contained in:
Eduardo Bart 2012-11-28 23:47:26 -02:00
parent eb979ef7cd
commit 81068f820d
26 changed files with 283 additions and 38 deletions

View File

@ -11,12 +11,11 @@ Module
//- client_particles //- client_particles
- client_topmenu - client_topmenu
- client_background - client_background
//- client_about
- client_options - client_options
- client_terminal - client_terminal
- client_modulemanager - client_modulemanager
- client_entergame - client_entergame
- client_stats //- client_stats
@onLoad: | @onLoad: |
dofile 'client' dofile 'client'

View File

@ -4,6 +4,7 @@ function UIGameMap.create()
local gameMap = UIGameMap.internalCreate() local gameMap = UIGameMap.internalCreate()
gameMap:setKeepAspectRatio(true) gameMap:setKeepAspectRatio(true)
gameMap:setVisibleDimension({width = 15, height = 11}) gameMap:setVisibleDimension({width = 15, height = 11})
gameMap:setDrawLights(true)
return gameMap return gameMap
end end

View File

@ -210,6 +210,9 @@ void Painter::updateGlCompositionMode()
case CompositionMode_DestBlending: case CompositionMode_DestBlending:
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
break; break;
case CompositionMode_Light:
glBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
break;
} }
} }

View File

@ -36,7 +36,8 @@ public:
CompositionMode_Multiply, CompositionMode_Multiply,
CompositionMode_Add, CompositionMode_Add,
CompositionMode_Replace, CompositionMode_Replace,
CompositionMode_DestBlending CompositionMode_DestBlending,
CompositionMode_Light
}; };
enum DrawMode { enum DrawMode {
Triangles = GL_TRIANGLES, Triangles = GL_TRIANGLES,

View File

@ -44,6 +44,8 @@ set(otclient_SOURCES ${otclient_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/mapio.cpp ${CMAKE_CURRENT_LIST_DIR}/mapio.cpp
${CMAKE_CURRENT_LIST_DIR}/mapview.cpp ${CMAKE_CURRENT_LIST_DIR}/mapview.cpp
${CMAKE_CURRENT_LIST_DIR}/mapview.h ${CMAKE_CURRENT_LIST_DIR}/mapview.h
${CMAKE_CURRENT_LIST_DIR}/lightview.cpp
${CMAKE_CURRENT_LIST_DIR}/lightview.h
${CMAKE_CURRENT_LIST_DIR}/missile.cpp ${CMAKE_CURRENT_LIST_DIR}/missile.cpp
${CMAKE_CURRENT_LIST_DIR}/missile.h ${CMAKE_CURRENT_LIST_DIR}/missile.h
${CMAKE_CURRENT_LIST_DIR}/outfit.cpp ${CMAKE_CURRENT_LIST_DIR}/outfit.cpp

View File

@ -29,6 +29,7 @@
#include "game.h" #include "game.h"
#include "effect.h" #include "effect.h"
#include "luavaluecasts.h" #include "luavaluecasts.h"
#include "lightview.h"
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
@ -58,7 +59,7 @@ Creature::Creature() : Thing()
m_footStep = 0; m_footStep = 0;
} }
void Creature::draw(const Point& dest, float scaleFactor, bool animate) void Creature::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
{ {
if(!canBeSeen()) if(!canBeSeen())
return; return;
@ -79,9 +80,12 @@ void Creature::draw(const Point& dest, float scaleFactor, bool animate)
internalDrawOutfit(dest + animationOffset * scaleFactor, scaleFactor, animate, animate, m_direction); internalDrawOutfit(dest + animationOffset * scaleFactor, scaleFactor, animate, animate, m_direction);
m_footStepDrawn = true; m_footStepDrawn = true;
if(lightView && m_light.intensity > 0)
lightView->addLightSource(dest + (animationOffset + Point(16,16)) * scaleFactor, scaleFactor, m_light);
} }
void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction) void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView)
{ {
// outfit is a real creature // outfit is a real creature
if(m_outfit.getCategory() == ThingCategoryCreature) { if(m_outfit.getCategory() == ThingCategoryCreature) {
@ -105,7 +109,7 @@ void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWal
if(m_outfit.getMount() != 0) { if(m_outfit.getMount() != 0) {
auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature); auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature);
dest -= datType->getDisplacement() * scaleFactor; dest -= datType->getDisplacement() * scaleFactor;
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase); datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
dest += getDisplacement() * scaleFactor; dest += getDisplacement() * scaleFactor;
zPattern = 1; zPattern = 1;
} }
@ -118,7 +122,7 @@ void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWal
continue; continue;
auto datType = rawGetThingType(); auto datType = rawGetThingType();
datType->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase); datType->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase, yPattern == 0 ? lightView : nullptr);
if(getLayers() > 1) { if(getLayers() > 1) {
Color oldColor = g_painter->getColor(); Color oldColor = g_painter->getColor();
@ -161,7 +165,7 @@ void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWal
if(m_outfit.getCategory() == ThingCategoryEffect) if(m_outfit.getCategory() == ThingCategoryEffect)
animationPhase = std::min(animationPhase+1, animationPhases); animationPhase = std::min(animationPhase+1, animationPhases);
type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase); type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView);
} }
} }

View File

@ -26,6 +26,7 @@
#include "thing.h" #include "thing.h"
#include "outfit.h" #include "outfit.h"
#include "tile.h" #include "tile.h"
#include "mapview.h"
#include <framework/core/scheduledevent.h> #include <framework/core/scheduledevent.h>
#include <framework/core/declarations.h> #include <framework/core/declarations.h>
#include <framework/core/timer.h> #include <framework/core/timer.h>
@ -44,9 +45,9 @@ public:
Creature(); Creature();
virtual void draw(const Point& dest, float scaleFactor, bool animate); virtual void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr);
void internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction); void internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView = nullptr);
void drawOutfit(const Rect& destRect, bool resize); void drawOutfit(const Rect& destRect, bool resize);
void drawInformation(const Point& point, bool useGray, const Rect& parentRect); void drawInformation(const Point& point, bool useGray, const Rect& parentRect);

View File

@ -31,6 +31,7 @@
class Map; class Map;
class Game; class Game;
class MapView; class MapView;
class LightView;
class Tile; class Tile;
class Thing; class Thing;
class Item; class Item;
@ -52,6 +53,7 @@ class CreatureType;
class Spawn; class Spawn;
typedef stdext::shared_object_ptr<MapView> MapViewPtr; typedef stdext::shared_object_ptr<MapView> MapViewPtr;
typedef stdext::shared_object_ptr<LightView> LightViewPtr;
typedef stdext::shared_object_ptr<Tile> TilePtr; typedef stdext::shared_object_ptr<Tile> TilePtr;
typedef stdext::shared_object_ptr<Thing> ThingPtr; typedef stdext::shared_object_ptr<Thing> ThingPtr;
typedef stdext::shared_object_ptr<Item> ItemPtr; typedef stdext::shared_object_ptr<Item> ItemPtr;

View File

@ -24,7 +24,7 @@
#include "map.h" #include "map.h"
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
void Effect::draw(const Point& dest, float scaleFactor, bool animate) void Effect::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
{ {
if(m_id == 0) if(m_id == 0)
return; return;
@ -32,7 +32,7 @@ void Effect::draw(const Point& dest, float scaleFactor, bool animate)
int animationPhase = 0; int animationPhase = 0;
if(animate) if(animate)
animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / m_phaseDuration), getAnimationPhases() - 1); animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / m_phaseDuration), getAnimationPhases() - 1);
rawGetThingType()->draw(dest, scaleFactor, 0, 0, 0, 0, animationPhase); rawGetThingType()->draw(dest, scaleFactor, 0, 0, 0, 0, animationPhase, lightView);
} }
void Effect::onAppear() void Effect::onAppear()

View File

@ -35,7 +35,7 @@ class Effect : public Thing
}; };
public: public:
void draw(const Point& dest, float scaleFactor, bool animate); void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr);
void setId(uint32 id); void setId(uint32 id);
uint32 getId() { return m_id; } uint32 getId() { return m_id; }

View File

@ -58,7 +58,7 @@ ItemPtr Item::createFromOtb(int id)
return item; return item;
} }
void Item::draw(const Point& dest, float scaleFactor, bool animate) void Item::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
{ {
if(m_clientId == 0) if(m_clientId == 0)
return; return;
@ -76,7 +76,7 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate)
int xPattern = 0, yPattern = 0, zPattern = 0; int xPattern = 0, yPattern = 0, zPattern = 0;
calculatePatterns(xPattern, yPattern, zPattern); calculatePatterns(xPattern, yPattern, zPattern);
rawGetThingType()->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase); rawGetThingType()->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase, lightView);
} }
void Item::setId(uint32 id) void Item::setId(uint32 id)

View File

@ -81,7 +81,7 @@ public:
static ItemPtr create(int id); static ItemPtr create(int id);
static ItemPtr createFromOtb(int id); static ItemPtr createFromOtb(int id);
void draw(const Point& dest, float scaleFactor, bool animate); void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr);
void setId(uint32 id); void setId(uint32 id);
void setOtbId(uint16 id); void setOtbId(uint16 id);

122
src/otclient/lightview.cpp Normal file
View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "lightview.h"
#include "mapview.h"
#include <framework/graphics/framebuffer.h>
#include <framework/graphics/framebuffermanager.h>
#include <framework/graphics/painter.h>
#include <framework/graphics/image.h>
LightView::LightView()
{
m_lightbuffer = g_framebuffers.getTemporaryFrameBuffer();
generateLightBuble();
reset();
}
void LightView::generateLightBuble()
{
const int size = 256;
uint8_t dest[size*size*4];
for(int x = 0; x < size; x++){
for(int y = 0; y < size; y++){
int norm = std::sqrt((size/2 - x)*(size/2 - x) + (size/2 - y)*(size/2 - y));
float p = 128*norm/(size/2);
float color = (p <= 128 ? 255 * (128-p)*(128-p)/(128*128) : 0);
if(color < 0)
color = 0;
int line = y;
dest[4*x + 4*size*line] = (uint8_t)color;
dest[4*x + 4*size*line + 1] = (uint8_t)color;
dest[4*x + 4*size*line + 2] = (uint8_t)color;
dest[4*x + 4*size*line + 3] = 255;
}
}
ImagePtr light = ImagePtr(new Image(Size(size,size), 4, dest));
m_lightTexture = TexturePtr(new Texture(light, false));
m_lightTexture->setSmooth(true);
}
void LightView::reset()
{
m_numLights = 0;
}
void LightView::setGlobalLight(const Light& light)
{
m_globalLight = light;
}
void LightView::addLightSource(const Point& center, float scaleFactor, const Light& light)
{
if(m_numLights > MAX_LIGHTS)
return;
int radius = light.intensity * 64 * scaleFactor;
m_lightMap[m_numLights].center = center;
m_lightMap[m_numLights].color = Color::from8bit(light.color);
m_lightMap[m_numLights].radius = radius;
m_numLights++;
}
void LightView::drawGlobalLight(const Light& light)
{
Color color = Color::from8bit(light.color);
float factor = 0;//std::max<int>(256 - light.intensity, 0) / 256.0f;
color.setRed(color.rF() * factor);
color.setGreen(color.gF() * factor);
color.setBlue(color.bF() * factor);
color.setAlpha(1.0f);
g_painter->clear(color);
}
void LightView::drawLightSource(const Point& center, const Color& color, int radius)
{
Rect dest = Rect(center - Point(radius, radius), Size(radius*2,radius*2));
g_painter->setColor(color);
g_painter->drawTexturedRect(dest, m_lightTexture);
// debug draw
//g_painter->drawBoundingRect(dest);
}
void LightView::draw(Size size)
{
m_lightbuffer->resize(size);
m_lightbuffer->bind();
drawGlobalLight(m_globalLight);
g_painter->setCompositionMode(Painter::CompositionMode_Add);
for(int i=0;i<m_numLights;++i)
drawLightSource(m_lightMap[i].center, m_lightMap[i].color, m_lightMap[i].radius);
m_lightbuffer->release();
g_painter->setCompositionMode(Painter::CompositionMode_Light);
m_lightbuffer->draw();
g_painter->setCompositionMode(Painter::CompositionMode_Normal);
}

63
src/otclient/lightview.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef LIGHTVIEW_H
#define LIGHTVIEW_H
#include "declarations.h"
#include <framework/graphics/declarations.h>
#include "thingtype.h"
struct LightSource {
Color color;
Point center;
int radius;
};
class LightView : public LuaObject
{
enum {
MAX_LIGHTS = 1024
};
public:
LightView();
void reset();
void setGlobalLight(const Light& light);
void addLightSource(const Point& center, float scaleFactor, const Light& light);
void draw(Size size);
private:
void drawGlobalLight(const Light& light);
void drawLightSource(const Point& center, const Color& color, int radius);
void generateLightBuble();
TexturePtr m_lightTexture;
FrameBufferPtr m_lightbuffer;
MapView* m_mapView;
int m_numLights;
Light m_globalLight;
std::array<LightSource, MAX_LIGHTS> m_lightMap;
};
#endif // LIGHTVIEW_H

View File

@ -517,6 +517,7 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassMemberFunction<UIMap>("setDrawFlags", &UIMap::setDrawFlags); g_lua.bindClassMemberFunction<UIMap>("setDrawFlags", &UIMap::setDrawFlags);
g_lua.bindClassMemberFunction<UIMap>("setDrawTexts", &UIMap::setDrawTexts); g_lua.bindClassMemberFunction<UIMap>("setDrawTexts", &UIMap::setDrawTexts);
g_lua.bindClassMemberFunction<UIMap>("setDrawMinimapColors", &UIMap::setDrawMinimapColors); g_lua.bindClassMemberFunction<UIMap>("setDrawMinimapColors", &UIMap::setDrawMinimapColors);
g_lua.bindClassMemberFunction<UIMap>("setDrawLights", &UIMap::setDrawLights);
g_lua.bindClassMemberFunction<UIMap>("setAnimated", &UIMap::setAnimated); g_lua.bindClassMemberFunction<UIMap>("setAnimated", &UIMap::setAnimated);
g_lua.bindClassMemberFunction<UIMap>("setKeepAspectRatio", &UIMap::setKeepAspectRatio); g_lua.bindClassMemberFunction<UIMap>("setKeepAspectRatio", &UIMap::setKeepAspectRatio);
g_lua.bindClassMemberFunction<UIMap>("setMapShader", &UIMap::setMapShader); g_lua.bindClassMemberFunction<UIMap>("setMapShader", &UIMap::setMapShader);
@ -524,6 +525,7 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassMemberFunction<UIMap>("isAutoViewModeEnabled", &UIMap::isAutoViewModeEnabled); g_lua.bindClassMemberFunction<UIMap>("isAutoViewModeEnabled", &UIMap::isAutoViewModeEnabled);
g_lua.bindClassMemberFunction<UIMap>("isDrawingTexts", &UIMap::isDrawingTexts); g_lua.bindClassMemberFunction<UIMap>("isDrawingTexts", &UIMap::isDrawingTexts);
g_lua.bindClassMemberFunction<UIMap>("isDrawingMinimapColors", &UIMap::isDrawingMinimapColors); g_lua.bindClassMemberFunction<UIMap>("isDrawingMinimapColors", &UIMap::isDrawingMinimapColors);
g_lua.bindClassMemberFunction<UIMap>("isDrawingLights", &UIMap::isDrawingLights);
g_lua.bindClassMemberFunction<UIMap>("isAnimating", &UIMap::isAnimating); g_lua.bindClassMemberFunction<UIMap>("isAnimating", &UIMap::isAnimating);
g_lua.bindClassMemberFunction<UIMap>("isKeepAspectRatioEnabled", &UIMap::isKeepAspectRatioEnabled); g_lua.bindClassMemberFunction<UIMap>("isKeepAspectRatioEnabled", &UIMap::isKeepAspectRatioEnabled);
g_lua.bindClassMemberFunction<UIMap>("getVisibleDimension", &UIMap::getVisibleDimension); g_lua.bindClassMemberFunction<UIMap>("getVisibleDimension", &UIMap::getVisibleDimension);

View File

@ -29,11 +29,14 @@
#include "animatedtext.h" #include "animatedtext.h"
#include "missile.h" #include "missile.h"
#include "shadermanager.h" #include "shadermanager.h"
#include "lightview.h"
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/graphics/image.h>
#include <framework/graphics/framebuffermanager.h> #include <framework/graphics/framebuffermanager.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/core/application.h> #include <framework/core/application.h>
#include <framework/core/resourcemanager.h>
enum { enum {
@ -86,6 +89,15 @@ void MapView::draw(const Rect& rect)
drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls | Otc::DrawItems; drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls | Otc::DrawItems;
Size tileSize = Size(1,1) * m_tileSize; Size tileSize = Size(1,1) * m_tileSize;
if(m_drawLights) {
m_lightView->reset();
Light globalLight = g_map.getLight();
if(cameraPosition.z <= 7)
globalLight.intensity = std::min<uint8>(200, globalLight.intensity);
m_lightView->setGlobalLight(globalLight);
}
if(m_mustDrawVisibleTilesCache || (drawFlags & Otc::DrawAnimations)) { if(m_mustDrawVisibleTilesCache || (drawFlags & Otc::DrawAnimations)) {
m_framebuffer->bind(); m_framebuffer->bind();
@ -99,6 +111,7 @@ void MapView::draw(const Rect& rect)
auto it = m_cachedVisibleTiles.begin(); auto it = m_cachedVisibleTiles.begin();
auto end = m_cachedVisibleTiles.end(); auto end = m_cachedVisibleTiles.end();
for(int z=m_cachedLastVisibleFloor;z>=m_cachedFirstVisibleFloor;--z) { for(int z=m_cachedLastVisibleFloor;z>=m_cachedFirstVisibleFloor;--z) {
while(it != end) { while(it != end) {
const TilePtr& tile = *it; const TilePtr& tile = *it;
Position tilePos = tile->getPosition(); Position tilePos = tile->getPosition();
@ -108,7 +121,7 @@ void MapView::draw(const Rect& rect)
++it; ++it;
if(!m_drawMinimapColors) if(!m_drawMinimapColors)
tile->draw(transformPositionTo2D(tilePos, cameraPosition), scaleFactor, drawFlags); tile->draw(transformPositionTo2D(tilePos, cameraPosition), scaleFactor, drawFlags, m_lightView.get());
else { else {
uint8 c = tile->getMinimapColorByte(); uint8 c = tile->getMinimapColorByte();
if(c == 0) if(c == 0)
@ -121,7 +134,7 @@ void MapView::draw(const Rect& rect)
if(drawFlags & Otc::DrawMissiles && !m_drawMinimapColors) { if(drawFlags & Otc::DrawMissiles && !m_drawMinimapColors) {
for(const MissilePtr& missile : g_map.getFloorMissiles(z)) { for(const MissilePtr& missile : g_map.getFloorMissiles(z)) {
missile->draw(transformPositionTo2D(missile->getPosition(), cameraPosition), scaleFactor, drawFlags & Otc::DrawAnimations); missile->draw(transformPositionTo2D(missile->getPosition(), cameraPosition), scaleFactor, drawFlags & Otc::DrawAnimations, m_lightView.get());
} }
} }
} }
@ -134,6 +147,11 @@ void MapView::draw(const Rect& rect)
m_mustDrawVisibleTilesCache = false; m_mustDrawVisibleTilesCache = false;
} }
if(m_drawLights) {
m_framebuffer->bind();
m_lightView->draw(m_framebuffer->getSize());
m_framebuffer->release();
}
Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize; Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize;
if(isFollowingCreature()) if(isFollowingCreature())
@ -450,7 +468,6 @@ void MapView::updateGeometry(const Size& visibleDimension, const Size& optimized
m_visibleCenterOffset = visibleCenterOffset; m_visibleCenterOffset = visibleCenterOffset;
m_optimizedSize = optimizedSize; m_optimizedSize = optimizedSize;
m_framebuffer->resize(bufferSize); m_framebuffer->resize(bufferSize);
requestVisibleTilesCacheUpdate(); requestVisibleTilesCacheUpdate();
} }
@ -631,3 +648,11 @@ void MapView::setDrawMinimapColors(bool enable)
m_framebuffer->setSmooth(m_smooth); m_framebuffer->setSmooth(m_smooth);
} }
void MapView::setDrawLights(bool enable)
{
if(enable)
m_lightView = LightViewPtr(new LightView);
else
m_lightView = nullptr;
m_drawLights = enable;
}

View File

@ -101,6 +101,9 @@ public:
void setAnimated(bool animated) { m_animated = animated; requestVisibleTilesCacheUpdate(); } void setAnimated(bool animated) { m_animated = animated; requestVisibleTilesCacheUpdate(); }
bool isAnimating() { return m_animated; } bool isAnimating() { return m_animated; }
void setDrawLights(bool enable);
bool isDrawingLights() { return m_drawLights; }
void setShader(const PainterShaderProgramPtr& shader) { m_shader = shader; } void setShader(const PainterShaderProgramPtr& shader) { m_shader = shader; }
PainterShaderProgramPtr getShader() { return m_shader; } PainterShaderProgramPtr getShader() { return m_shader; }
@ -135,6 +138,7 @@ private:
stdext::boolean<true> m_drawTexts; stdext::boolean<true> m_drawTexts;
stdext::boolean<true> m_smooth; stdext::boolean<true> m_smooth;
stdext::boolean<false> m_drawMinimapColors; stdext::boolean<false> m_drawMinimapColors;
stdext::boolean<false> m_drawLights;
stdext::boolean<true> m_follow; stdext::boolean<true> m_follow;
std::vector<TilePtr> m_cachedVisibleTiles; std::vector<TilePtr> m_cachedVisibleTiles;
std::vector<CreaturePtr> m_cachedFloorVisibleCreatures; std::vector<CreaturePtr> m_cachedFloorVisibleCreatures;
@ -144,6 +148,7 @@ private:
ViewMode m_viewMode; ViewMode m_viewMode;
Otc::DrawFlags m_drawFlags; Otc::DrawFlags m_drawFlags;
std::vector<Point> m_spiral; std::vector<Point> m_spiral;
LightViewPtr m_lightView;
}; };
#endif #endif

View File

@ -27,7 +27,7 @@
#include <framework/core/clock.h> #include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
void Missile::draw(const Point& dest, float scaleFactor, bool animate) void Missile::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
{ {
if(m_id == 0 || !animate) if(m_id == 0 || !animate)
return; return;
@ -63,7 +63,7 @@ void Missile::draw(const Point& dest, float scaleFactor, bool animate)
} }
float fraction = m_animationTimer.ticksElapsed() / m_duration; float fraction = m_animationTimer.ticksElapsed() / m_duration;
rawGetThingType()->draw(dest + m_delta * fraction * scaleFactor, scaleFactor, 0, xPattern, yPattern, 0, 0); rawGetThingType()->draw(dest + m_delta * fraction * scaleFactor, scaleFactor, 0, xPattern, yPattern, 0, 0, lightView);
} }
void Missile::setPath(const Position& fromPosition, const Position& toPosition) void Missile::setPath(const Position& fromPosition, const Position& toPosition)

View File

@ -35,7 +35,7 @@ class Missile : public Thing
}; };
public: public:
void draw(const Point& dest, float scaleFactor, bool animate); void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr);
void setId(uint32 id); void setId(uint32 id);
void setPath(const Position& fromPosition, const Position& toPosition); void setPath(const Position& fromPosition, const Position& toPosition);

View File

@ -36,7 +36,7 @@ public:
Thing(); Thing();
virtual ~Thing() { } virtual ~Thing() { }
virtual void draw(const Point& dest, float scaleFactor, bool animate) { } virtual void draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView = nullptr) { }
virtual void setId(uint32 id) { } virtual void setId(uint32 id) { }
void setPosition(const Position& position); void setPosition(const Position& position);

View File

@ -23,6 +23,7 @@
#include "thingtype.h" #include "thingtype.h"
#include "spritemanager.h" #include "spritemanager.h"
#include "game.h" #include "game.h"
#include "lightview.h"
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/graphics/texture.h> #include <framework/graphics/texture.h>
@ -138,7 +139,7 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
m_texturesFramesOffsets.resize(m_animationPhases); m_texturesFramesOffsets.resize(m_animationPhases);
} }
void ThingType::draw(const Point& dest, float scaleFactor, int layer, int xPattern, int yPattern, int zPattern, int animationPhase) void ThingType::draw(const Point& dest, float scaleFactor, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, LightView *lightView)
{ {
if(m_null) if(m_null)
return; return;
@ -160,6 +161,12 @@ void ThingType::draw(const Point& dest, float scaleFactor, int layer, int xPatte
textureRect.size() * scaleFactor); textureRect.size() * scaleFactor);
g_painter->drawTexturedRect(screenRect, texture, textureRect); g_painter->drawTexturedRect(screenRect, texture, textureRect);
if(lightView && hasLight()) {
Light light = getLight();
if(light.intensity > 0)
lightView->addLightSource(screenRect.center(), scaleFactor, light);
}
} }
const TexturePtr& ThingType::getTexture(int animationPhase) const TexturePtr& ThingType::getTexture(int animationPhase)

View File

@ -107,7 +107,7 @@ public:
void unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin); void unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin);
void draw(const Point& dest, float scaleFactor, int layer, int xPattern, int yPattern, int zPattern, int animationPhase); void draw(const Point& dest, float scaleFactor, int layer, int xPattern, int yPattern, int zPattern, int animationPhase, LightView *lightView = nullptr);
uint16 getId() { return m_id; } uint16 getId() { return m_id; }
ThingCategory getCategory() { return m_category; } ThingCategory getCategory() { return m_category; }

View File

@ -37,7 +37,7 @@ Tile::Tile(const Position& position) :
{ {
} }
void Tile::draw(const Point& dest, float scaleFactor, int drawFlags) void Tile::draw(const Point& dest, float scaleFactor, int drawFlags, LightView *lightView)
{ {
bool animate = drawFlags & Otc::DrawAnimations; bool animate = drawFlags & Otc::DrawAnimations;
@ -50,8 +50,9 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
if((thing->isGround() && drawFlags & Otc::DrawGround) || if((thing->isGround() && drawFlags & Otc::DrawGround) ||
(thing->isGroundBorder() && drawFlags & Otc::DrawGroundBorders) || (thing->isGroundBorder() && drawFlags & Otc::DrawGroundBorders) ||
(thing->isOnBottom() && drawFlags & Otc::DrawOnBottom)) (thing->isOnBottom() && drawFlags & Otc::DrawOnBottom)) {
thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate); thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
}
m_drawElevation += thing->getElevation(); m_drawElevation += thing->getElevation();
if(m_drawElevation > Otc::MAX_ELEVATION) if(m_drawElevation > Otc::MAX_ELEVATION)
@ -68,7 +69,7 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
const ThingPtr& thing = *it; const ThingPtr& thing = *it;
if(thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->isCreature()) if(thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->isCreature())
break; break;
thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate); thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
if(thing->isLyingCorpse()) { if(thing->isLyingCorpse()) {
redrawPreviousTopW = std::max(thing->getWidth(), redrawPreviousTopW); redrawPreviousTopW = std::max(thing->getWidth(), redrawPreviousTopW);
@ -91,7 +92,7 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
continue; continue;
const TilePtr& tile = g_map.getTile(m_position.translated(x,y)); const TilePtr& tile = g_map.getTile(m_position.translated(x,y));
if(tile) if(tile)
tile->draw(dest + Point(x*Otc::TILE_PIXELS, y*Otc::TILE_PIXELS)*scaleFactor, scaleFactor, topRedrawFlags); tile->draw(dest + Point(x*Otc::TILE_PIXELS, y*Otc::TILE_PIXELS)*scaleFactor, scaleFactor, topRedrawFlags, lightView);
} }
} }
} }
@ -102,8 +103,7 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
if(animate) { if(animate) {
for(const CreaturePtr& creature : m_walkingCreatures) { for(const CreaturePtr& creature : m_walkingCreatures) {
creature->draw(Point(dest.x + ((creature->getPosition().x - m_position.x)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor, creature->draw(Point(dest.x + ((creature->getPosition().x - m_position.x)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor,
dest.y + ((creature->getPosition().y - m_position.y)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor), scaleFactor, animate); dest.y + ((creature->getPosition().y - m_position.y)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor), scaleFactor, animate, lightView);
} }
} }
@ -113,21 +113,24 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
continue; continue;
CreaturePtr creature = thing->static_self_cast<Creature>(); CreaturePtr creature = thing->static_self_cast<Creature>();
if(creature && (!creature->isWalking() || !animate)) if(creature && (!creature->isWalking() || !animate))
creature->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate); creature->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
} }
} }
// effects // effects
if(drawFlags & Otc::DrawEffects) { if(drawFlags & Otc::DrawEffects) {
for(const EffectPtr& effect : m_effects) for(const EffectPtr& effect : m_effects){
effect->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate); effect->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
}
} }
// top items // top items
if(drawFlags & Otc::DrawOnTop) { if(drawFlags & Otc::DrawOnTop) {
for(const ThingPtr& thing : m_things) { for(const ThingPtr& thing : m_things) {
if(thing->isOnTop()) if(thing->isOnTop()){
thing->draw(dest, scaleFactor, animate); thing->draw(dest, scaleFactor, animate, lightView);
}
} }
} }
} }

View File

@ -24,6 +24,7 @@
#define TILE_H #define TILE_H
#include "declarations.h" #include "declarations.h"
#include "mapview.h"
#include "effect.h" #include "effect.h"
#include "creature.h" #include "creature.h"
#include "item.h" #include "item.h"
@ -59,7 +60,7 @@ public:
Tile(const Position& position); Tile(const Position& position);
void draw(const Point& dest, float scaleFactor, int drawFlags); void draw(const Point& dest, float scaleFactor, int drawFlags, LightView *lightView = nullptr);
public: public:
void clean(); void clean();

View File

@ -181,6 +181,8 @@ void UIMap::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleN
setDrawTexts(node->value<bool>()); setDrawTexts(node->value<bool>());
else if(node->tag() == "draw-minimap-colors") else if(node->tag() == "draw-minimap-colors")
setDrawMinimapColors(node->value<bool>()); setDrawMinimapColors(node->value<bool>());
else if(node->tag() == "draw-lights")
setDrawLights(node->value<bool>());
else if(node->tag() == "animated") else if(node->tag() == "animated")
setAnimated(node->value<bool>()); setAnimated(node->value<bool>());
} }

View File

@ -52,6 +52,7 @@ public:
void setDrawFlags(Otc::DrawFlags drawFlags) { m_mapView->setDrawFlags(drawFlags); } void setDrawFlags(Otc::DrawFlags drawFlags) { m_mapView->setDrawFlags(drawFlags); }
void setDrawTexts(bool enable) { m_mapView->setDrawTexts(enable); } void setDrawTexts(bool enable) { m_mapView->setDrawTexts(enable); }
void setDrawMinimapColors(bool enable) { m_mapView->setDrawMinimapColors(enable); } void setDrawMinimapColors(bool enable) { m_mapView->setDrawMinimapColors(enable); }
void setDrawLights(bool enable) { m_mapView->setDrawLights(enable); }
void setAnimated(bool enable) { m_mapView->setAnimated(enable); } void setAnimated(bool enable) { m_mapView->setAnimated(enable); }
void setKeepAspectRatio(bool enable); void setKeepAspectRatio(bool enable);
void setMapShader(const PainterShaderProgramPtr& shader) { m_mapView->setShader(shader); } void setMapShader(const PainterShaderProgramPtr& shader) { m_mapView->setShader(shader); }
@ -60,6 +61,7 @@ public:
bool isAutoViewModeEnabled() { return m_mapView->isAutoViewModeEnabled(); } bool isAutoViewModeEnabled() { return m_mapView->isAutoViewModeEnabled(); }
bool isDrawingTexts() { return m_mapView->isDrawingTexts(); } bool isDrawingTexts() { return m_mapView->isDrawingTexts(); }
bool isDrawingMinimapColors() { return m_mapView->isDrawingMinimapColors(); } bool isDrawingMinimapColors() { return m_mapView->isDrawingMinimapColors(); }
bool isDrawingLights() { return m_mapView->isDrawingLights(); }
bool isAnimating() { return m_mapView->isAnimating(); } bool isAnimating() { return m_mapView->isAnimating(); }
bool isKeepAspectRatioEnabled() { return m_aspectRatio != 0.0f; } bool isKeepAspectRatioEnabled() { return m_aspectRatio != 0.0f; }