mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-07-22 01:55:25 -04:00
a8559bfbbc
* Update all CMakeLists of extensions to use clang-format * Run clang-format on all Extensions * Update GDCore CMakeLists.txt to add clang-format * Run clang-format on GDCore files * Update GDJS and GDCpp CMakeLists.txt to add clang-format * Run clang-format on GDCpp and GDJS files
301 lines
10 KiB
C++
301 lines
10 KiB
C++
/**
|
|
|
|
GDevelop - Tiled Sprite Extension
|
|
Copyright (c) 2012-2016 Victor Levasseur (victorlevasseur01@orange.fr)
|
|
Copyright (c) 2014-2016 Florian Rival (Florian.Rival@gmail.com)
|
|
This project is released under the MIT License.
|
|
*/
|
|
|
|
#if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI)
|
|
#include <wx/bitmap.h> //Must be placed first, otherwise we get errors relative to "cannot convert 'const TCHAR*'..." in wx/msw/winundef.h
|
|
#include <wx/panel.h>
|
|
#endif
|
|
#include <SFML/Graphics.hpp>
|
|
#include "GDCore/Tools/Localization.h"
|
|
#include "GDCpp/Runtime/CommonTools.h"
|
|
#include "GDCpp/Runtime/FontManager.h"
|
|
#include "GDCpp/Runtime/ImageManager.h"
|
|
#include "GDCpp/Runtime/Polygon2d.h"
|
|
#include "GDCpp/Runtime/Project/InitialInstance.h"
|
|
#include "GDCpp/Runtime/Project/Object.h"
|
|
#include "GDCpp/Runtime/Project/Project.h"
|
|
#include "GDCpp/Runtime/RuntimeGame.h"
|
|
#include "GDCpp/Runtime/RuntimeScene.h"
|
|
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
|
|
#include "TiledSpriteObject.h"
|
|
|
|
#if defined(GD_IDE_ONLY)
|
|
#include "GDCore/IDE/Dialogs/MainFrameWrapper.h"
|
|
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
|
#include "TiledSpriteObjectEditor.h"
|
|
#endif
|
|
|
|
using namespace std;
|
|
|
|
TiledSpriteObject::TiledSpriteObject(gd::String name_)
|
|
: Object(name_), textureName(""), width(32), height(32) {}
|
|
|
|
void TiledSpriteObject::DoUnserializeFrom(
|
|
gd::Project& project, const gd::SerializerElement& element) {
|
|
textureName = element.GetStringAttribute("texture");
|
|
width = element.GetDoubleAttribute("width", 128);
|
|
height = element.GetDoubleAttribute("height", 128);
|
|
}
|
|
|
|
#if defined(GD_IDE_ONLY)
|
|
void TiledSpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
|
|
element.SetAttribute("texture", textureName);
|
|
element.SetAttribute("width", width);
|
|
element.SetAttribute("height", height);
|
|
}
|
|
|
|
void TiledSpriteObject::LoadResources(gd::Project& project,
|
|
gd::Layout& layout) {
|
|
texture = project.GetImageManager()->GetSFMLTexture(textureName);
|
|
}
|
|
#endif
|
|
|
|
namespace {
|
|
sf::Vector2f RotatePoint(sf::Vector2f point, float angle) {
|
|
float t, cosa = cos(-angle),
|
|
sina = sin(-angle); // We want a clockwise rotation
|
|
|
|
t = point.x;
|
|
point.x = t * cosa + point.y * sina;
|
|
point.y = -t * sina + point.y * cosa;
|
|
|
|
return point;
|
|
}
|
|
} // namespace
|
|
|
|
RuntimeTiledSpriteObject::RuntimeTiledSpriteObject(
|
|
RuntimeScene& scene, const TiledSpriteObject& tiledSpriteObject)
|
|
: RuntimeObject(scene, tiledSpriteObject),
|
|
width(32),
|
|
height(32),
|
|
xOffset(0),
|
|
yOffset(),
|
|
angle(0) {
|
|
SetWidth(tiledSpriteObject.GetWidth());
|
|
SetHeight(tiledSpriteObject.GetHeight());
|
|
|
|
textureName = tiledSpriteObject.textureName;
|
|
ChangeAndReloadImage(textureName, scene);
|
|
}
|
|
|
|
void RuntimeTiledSpriteObject::ChangeAndReloadImage(const gd::String& txtName,
|
|
const RuntimeScene& scene) {
|
|
textureName = txtName;
|
|
texture = scene.GetImageManager()->GetSFMLTexture(textureName);
|
|
}
|
|
|
|
/**
|
|
* Render object at runtime
|
|
*/
|
|
bool RuntimeTiledSpriteObject::Draw(sf::RenderTarget& window) {
|
|
// Don't draw anything if hidden
|
|
if (hidden) return true;
|
|
if (!texture) return true;
|
|
|
|
#if defined(ANDROID)
|
|
const unsigned int textureWidth = texture->texture.getSize().x;
|
|
const unsigned int textureHeight = texture->texture.getSize().y;
|
|
std::vector<sf::Vertex> vertices;
|
|
vertices.resize((static_cast<std::size_t>(GetWidth() / textureWidth) + 1u) *
|
|
(static_cast<std::size_t>(GetHeight() / textureHeight) + 1u) *
|
|
6);
|
|
for (unsigned int i = 0;
|
|
i < (static_cast<std::size_t>(GetWidth() / textureWidth) + 1u);
|
|
i++) {
|
|
for (unsigned int j = 0;
|
|
j < (static_cast<std::size_t>(GetHeight() / textureHeight) + 1u);
|
|
j++) {
|
|
// Create the four vertices
|
|
sf::Vector2f textureEndPosition(
|
|
(i < static_cast<std::size_t>(GetWidth() / textureWidth))
|
|
? textureWidth
|
|
: (GetWidth() - i * textureWidth),
|
|
(j < static_cast<std::size_t>(GetHeight() / textureHeight))
|
|
? textureHeight
|
|
: (GetHeight() - j * textureHeight));
|
|
|
|
sf::Vertex topLeftCorner(
|
|
sf::Vector2f(i * textureWidth, j * textureHeight),
|
|
sf::Vector2f(0.f, 0.f));
|
|
sf::Vertex topRightCorner(
|
|
sf::Vector2f(i * textureWidth + textureEndPosition.x,
|
|
j * textureHeight),
|
|
sf::Vector2f(textureEndPosition.x, 0.f));
|
|
sf::Vertex bottomRightCorner(
|
|
sf::Vector2f(i * textureWidth + textureEndPosition.x,
|
|
j * textureHeight + textureEndPosition.y),
|
|
sf::Vector2f(textureEndPosition.x, textureEndPosition.y));
|
|
sf::Vertex bottomLeftCorner(
|
|
sf::Vector2f(i * textureWidth,
|
|
j * textureHeight + textureEndPosition.y),
|
|
sf::Vector2f(0.f, textureEndPosition.y));
|
|
|
|
// Insert them to create two triangles
|
|
const unsigned int firstVerticePos =
|
|
(j * (static_cast<std::size_t>(GetWidth() / textureWidth) + 1u) + i) *
|
|
6;
|
|
vertices[firstVerticePos] = topLeftCorner;
|
|
vertices[firstVerticePos + 1u] = topRightCorner;
|
|
vertices[firstVerticePos + 2u] = bottomRightCorner;
|
|
vertices[firstVerticePos + 3u] = topLeftCorner;
|
|
vertices[firstVerticePos + 4u] = bottomRightCorner;
|
|
vertices[firstVerticePos + 5u] = bottomLeftCorner;
|
|
}
|
|
}
|
|
|
|
sf::Transform transform;
|
|
transform.translate(-GetWidth() / 2.f, -GetHeight() / 2.f);
|
|
transform.rotate(angle);
|
|
transform.translate(GetX() + GetWidth() / 2.f, GetY() + GetHeight() / 2.f);
|
|
|
|
window.draw(
|
|
vertices.data(),
|
|
vertices.size(),
|
|
sf::Triangles,
|
|
sf::RenderStates(sf::BlendAlpha, transform, &texture->texture, nullptr));
|
|
#else
|
|
sf::Vector2f centerPosition =
|
|
sf::Vector2f(GetX() + GetCenterX(), GetY() + GetCenterY());
|
|
float angleInRad = angle * 3.14159 / 180.0;
|
|
|
|
texture->texture.setRepeated(true);
|
|
sf::Vertex vertices[] = {
|
|
sf::Vertex(
|
|
centerPosition +
|
|
RotatePoint(sf::Vector2f(-width / 2, -height / 2), angleInRad),
|
|
sf::Vector2f(0 + xOffset, 0 + yOffset)),
|
|
sf::Vertex(
|
|
centerPosition +
|
|
RotatePoint(sf::Vector2f(+width / 2, -height / 2), angleInRad),
|
|
sf::Vector2f(width + xOffset, 0 + yOffset)),
|
|
sf::Vertex(
|
|
centerPosition +
|
|
RotatePoint(sf::Vector2f(-width / 2, +height / 2), angleInRad),
|
|
sf::Vector2f(0 + xOffset, height + yOffset)),
|
|
sf::Vertex(
|
|
centerPosition +
|
|
RotatePoint(sf::Vector2f(+width / 2, +height / 2), angleInRad),
|
|
sf::Vector2f(width + xOffset, height + yOffset))};
|
|
|
|
window.draw(vertices, 4, sf::TrianglesStrip, &texture->texture);
|
|
texture->texture.setRepeated(false);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
#if defined(GD_IDE_ONLY)
|
|
sf::Vector2f TiledSpriteObject::GetInitialInstanceDefaultSize(
|
|
gd::InitialInstance& instance,
|
|
gd::Project& project,
|
|
gd::Layout& layout) const {
|
|
return sf::Vector2f(width, height);
|
|
}
|
|
|
|
/**
|
|
* Render object at edittime
|
|
*/
|
|
void TiledSpriteObject::DrawInitialInstance(gd::InitialInstance& instance,
|
|
sf::RenderTarget& renderTarget,
|
|
gd::Project& project,
|
|
gd::Layout& layout) {
|
|
if (!texture) return;
|
|
|
|
float width =
|
|
instance.HasCustomSize()
|
|
? instance.GetCustomWidth()
|
|
: GetInitialInstanceDefaultSize(instance, project, layout).x;
|
|
float height =
|
|
instance.HasCustomSize()
|
|
? instance.GetCustomHeight()
|
|
: GetInitialInstanceDefaultSize(instance, project, layout).y;
|
|
float xOffset = 0;
|
|
float yOffset = 0;
|
|
|
|
sf::Vector2f centerPosition =
|
|
sf::Vector2f(instance.GetX() + width / 2, instance.GetY() + height / 2);
|
|
float angleInRad = instance.GetAngle() * 3.14159 / 180.0;
|
|
texture->texture.setRepeated(true);
|
|
sf::Vertex vertices[] = {
|
|
sf::Vertex(
|
|
centerPosition +
|
|
RotatePoint(sf::Vector2f(-width / 2, -height / 2), angleInRad),
|
|
sf::Vector2f(0 + xOffset, 0 + yOffset)),
|
|
sf::Vertex(
|
|
centerPosition +
|
|
RotatePoint(sf::Vector2f(+width / 2, -height / 2), angleInRad),
|
|
sf::Vector2f(width + xOffset, 0 + yOffset)),
|
|
sf::Vertex(
|
|
centerPosition +
|
|
RotatePoint(sf::Vector2f(-width / 2, +height / 2), angleInRad),
|
|
sf::Vector2f(0 + xOffset, height + yOffset)),
|
|
sf::Vertex(
|
|
centerPosition +
|
|
RotatePoint(sf::Vector2f(+width / 2, +height / 2), angleInRad),
|
|
sf::Vector2f(width + xOffset, height + yOffset))};
|
|
|
|
renderTarget.draw(vertices, 4, sf::TrianglesStrip, &texture->texture);
|
|
texture->texture.setRepeated(false);
|
|
}
|
|
|
|
void TiledSpriteObject::ExposeResources(gd::ArbitraryResourceWorker& worker) {
|
|
worker.ExposeImage(textureName);
|
|
}
|
|
|
|
bool TiledSpriteObject::GenerateThumbnail(const gd::Project& project,
|
|
wxBitmap& thumbnail) const {
|
|
#if !defined(GD_NO_WX_GUI)
|
|
thumbnail = wxBitmap("CppPlatform/Extensions/TiledSpriteIcon24.png",
|
|
wxBITMAP_TYPE_ANY);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
void TiledSpriteObject::EditObject(wxWindow* parent,
|
|
gd::Project& game,
|
|
gd::MainFrameWrapper& mainFrameWrapper) {
|
|
#if !defined(GD_NO_WX_GUI)
|
|
TiledSpriteObjectEditor dialog(parent, game, *this, mainFrameWrapper);
|
|
dialog.ShowModal();
|
|
#endif
|
|
}
|
|
|
|
void RuntimeTiledSpriteObject::GetPropertyForDebugger(std::size_t propertyNb,
|
|
gd::String& name,
|
|
gd::String& value) const {
|
|
if (propertyNb == 0) {
|
|
name = _("Width");
|
|
value = gd::String::From(width);
|
|
} else if (propertyNb == 1) {
|
|
name = _("Height");
|
|
value = gd::String::From(height);
|
|
} else if (propertyNb == 2) {
|
|
name = _("Angle");
|
|
value = gd::String::From(angle);
|
|
}
|
|
}
|
|
|
|
bool RuntimeTiledSpriteObject::ChangeProperty(std::size_t propertyNb,
|
|
gd::String newValue) {
|
|
if (propertyNb == 0) {
|
|
width = newValue.To<float>();
|
|
} else if (propertyNb == 1) {
|
|
height = newValue.To<float>();
|
|
} else if (propertyNb == 2) {
|
|
angle = newValue.To<float>();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::size_t RuntimeTiledSpriteObject::GetNumberOfProperties() const {
|
|
return 3;
|
|
}
|
|
#endif
|