mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-07-24 11:55:28 -04:00
64e6860718
Updated copyrights.
306 lines
10 KiB
C++
306 lines
10 KiB
C++
/**
|
|
|
|
GDevelop - Light Extension
|
|
Copyright (c) 2008-2015 Florian Rival (Florian.Rival@gmail.com)
|
|
This project is released under the MIT License.
|
|
*/
|
|
|
|
#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 "GDCpp/Object.h"
|
|
#include "GDCpp/RuntimeScene.h"
|
|
#include "GDCpp/ImageManager.h"
|
|
#include "GDCpp/Serialization/SerializerElement.h"
|
|
#include "GDCpp/FontManager.h"
|
|
#include "GDCpp/Position.h"
|
|
#include "GDCpp/Polygon2d.h"
|
|
#include "GDCpp/CommonTools.h"
|
|
#include "LightObject.h"
|
|
#include "LightManager.h"
|
|
|
|
#if defined(GD_IDE_ONLY)
|
|
#include "GDCpp/CommonTools.h"
|
|
#include "GDCore/IDE/ArbitraryResourceWorker.h"
|
|
#include "GDCore/IDE/Dialogs/MainFrameWrapper.h"
|
|
#include "LightObjectEditor.h"
|
|
#endif
|
|
|
|
using namespace std;
|
|
|
|
std::map<const gd::Layout*, boost::weak_ptr<Light_Manager> > RuntimeLightObject::lightManagersList;
|
|
#if defined(GD_IDE_ONLY)
|
|
sf::Texture LightObject::edittimeIconImage;
|
|
sf::Sprite LightObject::edittimeIcon;
|
|
#endif
|
|
|
|
LightObject::LightObject(std::string name_) :
|
|
Object(name_),
|
|
light(sf::Vector2f(0,0)/*(Useless)*/, 150, 128, 16, sf::Color(255,255,255)),
|
|
globalLight(false),
|
|
globalLightColor(128,128,128,150)
|
|
{
|
|
}
|
|
|
|
void LightObject::DoUnserializeFrom(gd::Project & project, const gd::SerializerElement & element)
|
|
{
|
|
SetIntensity(element.GetIntAttribute("intensity", 255));
|
|
SetRadius(element.GetIntAttribute("radius", 180));
|
|
SetQuality(element.GetIntAttribute("quality", 16));
|
|
|
|
{
|
|
int r = element.GetIntAttribute("colorR", 255);
|
|
int g = element.GetIntAttribute("colorG", 255);
|
|
int b = element.GetIntAttribute("colorB", 255);
|
|
SetColor(sf::Color(r,g,b));
|
|
}
|
|
|
|
globalLight = element.GetBoolAttribute("globalLight", false);
|
|
|
|
{
|
|
int r = element.GetIntAttribute("globalColorR", 255);
|
|
int g = element.GetIntAttribute("globalColorG", 255);
|
|
int b = element.GetIntAttribute("globalColorB", 255);
|
|
int a = element.GetIntAttribute("globalColorA", 255);
|
|
globalLightColor = sf::Color(r,g,b,a);
|
|
}
|
|
|
|
}
|
|
|
|
#if defined(GD_IDE_ONLY)
|
|
void LightObject::DoSerializeTo(gd::SerializerElement & element) const
|
|
{
|
|
element.SetAttribute("intensity", GetIntensity());
|
|
element.SetAttribute("radius", GetRadius());
|
|
element.SetAttribute("quality", GetQuality());
|
|
|
|
element.SetAttribute("colorR", GetColor().r);
|
|
element.SetAttribute("colorG", GetColor().g);
|
|
element.SetAttribute("colorB", GetColor().b);
|
|
|
|
element.SetAttribute("globalLight", globalLight);
|
|
element.SetAttribute("globalColorR", globalLightColor.r);
|
|
element.SetAttribute("globalColorG", globalLightColor.g);
|
|
element.SetAttribute("globalColorB", globalLightColor.b);
|
|
element.SetAttribute("globalColorA", globalLightColor.a);
|
|
}
|
|
#endif
|
|
|
|
RuntimeLightObject::RuntimeLightObject(RuntimeScene & scene, const gd::Object & object) :
|
|
RuntimeObject(scene, object),
|
|
angle(0)
|
|
{
|
|
const LightObject & lightObject = static_cast<const LightObject&>(object);
|
|
|
|
globalLight = lightObject.IsGlobalLight();
|
|
globalLightColor = lightObject.GetGlobalColor();
|
|
light = Light(sf::Vector2f(GetX(),GetY()), lightObject.GetIntensity(), lightObject.GetRadius(), lightObject.GetQuality(), lightObject.GetColor());
|
|
|
|
//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 for each scene ) the common blur effect, shared by all lights.
|
|
if ( !manager->commonBlurEffectLoaded )
|
|
{
|
|
manager->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",
|
|
sf::Shader::Fragment);
|
|
manager->commonBlurEffect.setParameter("texture", sf::Shader::CurrentTexture);
|
|
|
|
manager->commonBlurEffectLoaded = true;
|
|
}
|
|
|
|
UpdateGlobalLightMembers();
|
|
}
|
|
|
|
void RuntimeLightObject::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();
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Render object at runtime
|
|
*/
|
|
bool RuntimeLightObject::Draw( sf::RenderTarget& window )
|
|
{
|
|
//Don't draw anything if hidden
|
|
if ( hidden ) return true;
|
|
|
|
if ( !manager ) return false;
|
|
|
|
if ( updateClock.getElapsedTime().asMilliseconds() > 25 )
|
|
{
|
|
light.Generate(manager->walls);
|
|
updateClock.restart(); //Update each 25 milliseconds
|
|
}
|
|
|
|
if ( globalLight )
|
|
{
|
|
//Create render image
|
|
if ( globalLightImage->getSize().x != window.getSize().x || globalLightImage->getSize().y != window.getSize().y )
|
|
globalLightImage->create(window.getSize().x, window.getSize().y);
|
|
|
|
//Render light on an intermediate image
|
|
globalLightImage->clear(globalLightColor);
|
|
globalLightImage->setView(window.getView());
|
|
light.Draw(globalLightImage.get());
|
|
globalLightImage->display();
|
|
|
|
//Display the intermediate image
|
|
sf::Sprite sprite;
|
|
sprite.setTexture(globalLightImage->getTexture());
|
|
manager->commonBlurEffect.setParameter("offset",0.005 * 1);
|
|
|
|
window.setView(sf::View(sf::FloatRect(0,0,window.getSize().x, window.getSize().y)));
|
|
sf::RenderStates renderStates;
|
|
renderStates.blendMode = sf::BlendMultiply;
|
|
renderStates.shader = &manager->commonBlurEffect;
|
|
window.draw(sprite, renderStates);
|
|
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)
|
|
void LightObject::DrawInitialInstance(gd::InitialInstance & instance, sf::RenderTarget & renderTarget, gd::Project & project, gd::Layout & layout)
|
|
{
|
|
edittimeIcon.setPosition(instance.GetX(), instance.GetY());
|
|
renderTarget.draw(edittimeIcon);
|
|
}
|
|
|
|
sf::Vector2f LightObject::GetInitialInstanceDefaultSize(gd::InitialInstance & instance, gd::Project & project, gd::Layout & layout) const
|
|
{
|
|
return sf::Vector2f(32,32);
|
|
}
|
|
|
|
void LightObject::LoadEdittimeIcon()
|
|
{
|
|
edittimeIconImage.loadFromFile("CppPlatform/Extensions/lightIcon32.png");
|
|
edittimeIconImage.setSmooth(false);
|
|
edittimeIcon.setTexture(edittimeIconImage);
|
|
}
|
|
|
|
bool LightObject::GenerateThumbnail(const gd::Project & project, wxBitmap & thumbnail) const
|
|
{
|
|
thumbnail = wxBitmap("CppPlatform/Extensions/lightIcon24.png", wxBITMAP_TYPE_ANY);
|
|
|
|
return true;
|
|
}
|
|
|
|
void LightObject::EditObject( wxWindow* parent, gd::Project & game, gd::MainFrameWrapper & mainFrameWrapper )
|
|
{
|
|
LightObjectEditor dialog(parent, game, *this);
|
|
dialog.ShowModal();
|
|
}
|
|
|
|
void RuntimeLightObject::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 RuntimeLightObject::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 RuntimeLightObject::GetNumberOfProperties() const
|
|
{
|
|
return 2;
|
|
}
|
|
#endif
|
|
|
|
void RuntimeLightObject::OnPositionChanged()
|
|
{
|
|
light.SetPosition(sf::Vector2f(GetX(),GetY()));
|
|
}
|
|
|
|
void RuntimeLightObject::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 RuntimeLightObject::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]) ));
|
|
}
|
|
|
|
RuntimeObject * CreateRuntimeLightObject(RuntimeScene & scene, const gd::Object & object)
|
|
{
|
|
return new RuntimeLightObject(scene, object);
|
|
}
|
|
|
|
gd::Object * CreateLightObject(std::string name)
|
|
{
|
|
return new LightObject(name);
|
|
}
|
|
|
|
|