Files
GDevelop/Extensions/Light/LightObject.cpp
T
Florian 7d35fc59fa Exchanged all french messages with their English counterparts.
git-svn-id: svn://localhost@844 8062f311-0dae-4547-b526-b8ab9ac864a5
2012-09-20 19:55:40 +00:00

442 lines
13 KiB
C++

/**
Game Develop - Light Extension
Copyright (c) 2008-2012 Florian Rival (Florian.Rival@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#if defined(GD_IDE_ONLY)
#include <wx/wx.h> //Must be placed first, otherwise we get nice errors relative to "cannot convert 'const TCHAR*'..." in wx/msw/winundef.h
#endif
#include <SFML/Graphics.hpp>
#include "GDL/Object.h"
#include "GDL/RuntimeScene.h"
#include "GDL/ImageManager.h"
#include "GDL/tinyxml/tinyxml.h"
#include "GDL/FontManager.h"
#include "GDL/XmlMacros.h"
#include "GDL/Position.h"
#include "GDL/Polygon.h"
#include "GDL/CommonTools.h"
#include "LightObject.h"
#include "LightManager.h"
#if defined(GD_IDE_ONLY)
#include "GDL/CommonTools.h"
#include "GDCore/IDE/ArbitraryResourceWorker.h"
#include "GDCore/IDE/Dialogs/MainFrameWrapper.h"
#include "LightObjectEditor.h"
#endif
std::map<const Scene*, boost::weak_ptr<Light_Manager> > LightObject::lightManagersList;
sf::Shader LightObject::commonBlurEffect;
bool LightObject::commonBlurEffectLoaded = false;
#if defined(GD_IDE_ONLY)
sf::Texture LightObject::edittimeIconImage;
sf::Sprite LightObject::edittimeIcon;
#endif
LightObject::LightObject(std::string name_) :
Object(name_),
angle(0),
light(sf::Vector2f(GetX(),GetY()), 150, 128, 16, sf::Color(255,255,255)),
globalLight(false),
globalLightColor(128,128,128,150)
{
}
void LightObject::LoadFromXml(const TiXmlElement * elem)
{
{
float intensity = 255;
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("intensity", intensity);
SetIntensity(intensity);
}
{
float radius = 180;
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("radius", radius);
SetRadius(radius);
}
{
int quality = 16;
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("quality", quality);
SetQuality(quality);
}
{
int r = 255;
int g = 255;
int b = 255;
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("colorR", r);
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("colorG", g);
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("colorB", b);
SetColor(sf::Color(r,g,b));
}
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_BOOL("globalLight", globalLight);
{
int r = 255;
int g = 255;
int b = 255;
int a = 255;
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("globalColorR", r);
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("globalColorG", g);
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("globalColorB", b);
GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("globalColorA", a);
globalLightColor = sf::Color(r,g,b,a);
}
}
#if defined(GD_IDE_ONLY)
void LightObject::SaveToXml(TiXmlElement * elem)
{
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_DOUBLE("intensity", GetIntensity());
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_DOUBLE("radius", GetRadius());
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("quality", GetQuality());
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("colorR", GetColor().r);
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("colorG", GetColor().g);
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("colorB", GetColor().b);
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_BOOL("globalLight", globalLight);
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("globalColorR", globalLightColor.r);
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("globalColorG", globalLightColor.g);
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("globalColorB", globalLightColor.b);
GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("globalColorA", globalLightColor.a);
}
#endif
bool LightObject::LoadResources(const RuntimeScene & scene, const ImageManager & imageMgr)
{
return true;
}
bool LightObject::LoadRuntimeResources(const RuntimeScene & scene, const ImageManager & imageMgr )
{
//Get a manager for the scene
if ( lightManagersList[&scene].expired() )
{
manager = boost::shared_ptr<Light_Manager>(new Light_Manager);
lightManagersList[&scene] = manager;
}
else
manager = lightManagersList[&scene].lock();
//Load ( only once during program use ) the common blur effect, shared by all lights.
if ( !commonBlurEffectLoaded )
{
commonBlurEffect.LoadFromMemory("uniform sampler2D texture;\nuniform float offset;\n\nvoid main()\n{\n vec2 offx = vec2(offset, 0.0);\n vec2 offy = vec2(0.0, offset);\n\n vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * 1 +\n texture2D(texture, gl_TexCoord[0].xy - offx) * 2 +\n texture2D(texture, gl_TexCoord[0].xy + offx) * 2 +\n texture2D(texture, gl_TexCoord[0].xy - offy) * 2 +\n texture2D(texture, gl_TexCoord[0].xy + offy) * 2 +\n texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1 +\n texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1 +\n texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1 +\n texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1;\n\n gl_FragColor = gl_Color * (pixel / 13.0);\n}\n");
commonBlurEffect.SetCurrentTexture("texture");
commonBlurEffectLoaded = true;
}
UpdateGlobalLightMembers();
return true;
}
void LightObject::UpdateGlobalLightMembers()
{
if ( globalLight )
{
//Create supplementary members for the global light
if ( !globalLightImage ) globalLightImage = boost::shared_ptr<sf::RenderTexture>(new sf::RenderTexture);
}
else
{
//Not a global light, destroy all members related to
globalLightImage.reset();
}
}
/**
* Update animation and direction from the inital position
*/
bool LightObject::InitializeFromInitialPosition(const InitialPosition & position)
{
return true;
}
/**
* Render object at runtime
*/
bool LightObject::Draw( sf::RenderTarget& window )
{
//Don't draw anything if hidden
if ( hidden ) return true;
if ( !manager ) return false;
if ( updateClock.GetElapsedTime() > 25 ) //Update each 25 milliseconds
{
light.Generate(manager->walls);
updateClock.Reset();
}
if ( globalLight )
{
//Create render image
if ( globalLightImage->GetWidth() != window.GetWidth() || globalLightImage->GetHeight() != window.GetHeight() )
globalLightImage->Create(window.GetWidth(), window.GetHeight());
//Render light on an intermediate image
globalLightImage->Clear(globalLightColor);
globalLightImage->SetView(window.GetView());
//light.SetPosition(sf::Vector2f(light.GetPosition().x-(window.GetView().GetCenter().x-window.GetView().GetSize().x/2), light.GetPosition().y-(window.GetView().GetCenter().y-window.GetView().GetSize().y/2)));
light.Draw(globalLightImage.get());
globalLightImage->Display();
//Display the intermediate image
sf::Sprite sprite;
sprite.SetTexture(globalLightImage->GetTexture());
sprite.SetBlendMode(sf::Blend::Multiply);
commonBlurEffect.SetParameter("offset",0.005 * 1);
window.SetView(sf::View(sf::FloatRect(0,0,window.GetWidth(), window.GetHeight())));
window.Draw(sprite, commonBlurEffect);
window.SetView(globalLightImage->GetView());
}
else
{
light.Draw(&window);
}
//Debug draw
/*for (unsigned int i = 0;i<manager->walls.size();++i)
{
sf::Shape shape = sf::Shape::Line(manager->walls[i]->pt1, manager->walls[i]->pt2, 1, sf::Color(255,0,0));
window.Draw(shape);
}*/
return true;
}
#if defined(GD_IDE_ONLY)
/**
* Render object at edittime
*/
bool LightObject::DrawEdittime(sf::RenderTarget& renderWindow)
{
edittimeIcon.SetPosition(GetX(), GetY());
renderWindow.Draw(edittimeIcon);
return true;
}
void LightObject::LoadEdittimeIcon()
{
edittimeIconImage.LoadFromFile("Extensions/lightIcon32.png");
edittimeIconImage.SetSmooth(false);
edittimeIcon.SetTexture(edittimeIconImage);
}
void LightObject::ExposeResources(gd::ArbitraryResourceWorker & worker)
{
}
bool LightObject::GenerateThumbnail(const gd::Project & project, wxBitmap & thumbnail)
{
thumbnail = wxBitmap("Extensions/lightIcon24.png", wxBITMAP_TYPE_ANY);
return true;
}
void LightObject::EditObject( wxWindow* parent, Game & game, gd::MainFrameWrapper & mainFrameWrapper )
{
LightObjectEditor dialog(parent, game, *this);
dialog.ShowModal();
}
wxPanel * LightObject::CreateInitialPositionPanel( wxWindow* parent, const Game & game_, const Scene & scene_, const InitialPosition & position )
{
return NULL;
}
void LightObject::UpdateInitialPositionFromPanel(wxPanel * panel, InitialPosition & position)
{
}
void LightObject::GetPropertyForDebugger(unsigned int propertyNb, string & name, string & value) const
{
if ( propertyNb == 0 ) {name = _("Color"); value = ToString(GetColor().r)+";"+ToString(GetColor().g)+";"+ToString(GetColor().b);}
else if ( propertyNb == 1 ) {name = _("Intensity"); value = ToString(GetIntensity());}
else if ( propertyNb == 2 ) {name = _("Radius"); value = ToString(GetRadius());}
else if ( propertyNb == 2 ) {name = _("Quality"); value = ToString(GetQuality());}
}
bool LightObject::ChangeProperty(unsigned int propertyNb, string newValue)
{
if ( propertyNb == 0 )
{
string r, gb, g, b;
{
size_t separationPos = newValue.find(";");
if ( separationPos > newValue.length())
return false;
r = newValue.substr(0, separationPos);
gb = newValue.substr(separationPos+1, newValue.length());
}
{
size_t separationPos = gb.find(";");
if ( separationPos > gb.length())
return false;
g = gb.substr(0, separationPos);
b = gb.substr(separationPos+1, gb.length());
}
SetColor(sf::Color(ToInt(r), ToInt(g), ToInt(b)));
}
else if ( propertyNb == 1 ) { SetIntensity(ToFloat(newValue)); }
else if ( propertyNb == 2 ) { SetRadius(ToFloat(newValue)); }
else if ( propertyNb == 3 ) { SetQuality(ToInt(newValue)); }
return true;
}
unsigned int LightObject::GetNumberOfProperties() const
{
return 2;
}
#endif
void LightObject::OnPositionChanged()
{
light.SetPosition(sf::Vector2f(GetX(),GetY()));
}
void LightObject::SetColor(const std::string & colorStr)
{
vector < string > colors = SplitString<string>(colorStr, ';');
if ( colors.size() < 3 ) return; //La couleur est incorrecte
SetColor(sf::Color( ToInt(colors[0]), ToInt(colors[1]), ToInt(colors[2]) ));
}
void LightObject::SetGlobalColor(const std::string & colorStr)
{
vector < string > colors = SplitString<string>(colorStr, ';');
if ( colors.size() < 3 ) return; //La couleur est incorrecte
SetGlobalColor(sf::Color( ToInt(colors[0]),ToInt(colors[1]),ToInt(colors[2]) ));
}
/**
* LightObject provides a basic bounding box.
*/
std::vector<Polygon2d> LightObject::GetHitBoxes() const
{
std::vector<Polygon2d> mask;
Polygon2d rectangle = Polygon2d::CreateRectangle(GetWidth(), GetHeight());
rectangle.Rotate(GetAngle()/180*3.14159);
rectangle.Move(GetX()+GetCenterX(), GetY()+GetCenterY());
mask.push_back(rectangle);
return mask;
}
/**
* Get the real X position of the sprite
*/
float LightObject::GetDrawableX() const
{
return GetX();
}
/**
* Get the real Y position of the text
*/
float LightObject::GetDrawableY() const
{
return GetY();
}
/**
* Width is the width of the current sprite.
*/
float LightObject::GetWidth() const
{
return 32;
}
/**
* Height is the height of the current sprite.
*/
float LightObject::GetHeight() const
{
return 32;
}
/**
* X center is computed with text rectangle
*/
float LightObject::GetCenterX() const
{
return 16;
}
/**
* Y center is computed with text rectangle
*/
float LightObject::GetCenterY() const
{
return 16;
}
/**
* Nothing to do when updating time
*/
void LightObject::UpdateTime(float)
{
}
/**
* Function destroying an extension Object.
* Game Develop does not delete directly extension object
* to avoid overloaded new/delete conflicts.
*/
void DestroyLightObject(Object * object)
{
delete object;
}
/**
* Function creating an extension Object.
* Game Develop can not directly create an extension object
*/
Object * CreateLightObject(std::string name)
{
return new LightObject(name);
}