mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Merge branch 'master' of github.com:4ian/GD
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -164,7 +164,7 @@ void DeclareTileMapObjectExtension(gd::PlatformExtension & extension)
|
||||
|
||||
obj.AddAction("ChangeTexture",
|
||||
_("Change the tileset texture"),
|
||||
_("Change the tileset texture."),
|
||||
_("Change the tileset texture.\nNote: if the texture has a different size, it may produce strange results such as texture offset..."),
|
||||
_("Change the tileset texture of _PARAM0_ to _PARAM1_"),
|
||||
_("Tileset"),
|
||||
"CppPlatform/Extensions/TileMapIcon24.png",
|
||||
|
@@ -43,7 +43,6 @@ RuntimeTileMapObject::RuntimeTileMapObject(RuntimeScene & scene, const gd::Objec
|
||||
|
||||
//Load the tileset and generate the vertex array
|
||||
tileSet.Get().LoadResources(*(scene.game));
|
||||
tileSet.Get().Generate(); //We don't need wxBitmaps
|
||||
vertexArray = TileMapExtension::GenerateVertexArray(tileSet.Get(), tileMap.Get());
|
||||
hitboxes = TileMapExtension::GenerateHitboxes(tileSet.Get(), tileMap.Get());
|
||||
}
|
||||
@@ -214,7 +213,6 @@ void RuntimeTileMapObject::ChangeTexture(const gd::String &textureName, RuntimeS
|
||||
{
|
||||
tileSet.Get().textureName = textureName;
|
||||
tileSet.Get().LoadResources(*(scene.game));
|
||||
tileSet.Get().Generate();
|
||||
needGeneration = true;
|
||||
}
|
||||
|
||||
|
@@ -62,8 +62,9 @@ void TileEditor::OnTileSetSelectionChanged(TileSelectionEvent &event)
|
||||
if(!m_tileset || m_tileset->IsDirty())
|
||||
return;
|
||||
|
||||
//Update the editor with the new tile
|
||||
m_currentTile = event.GetSelectedTile();
|
||||
m_mainToolbar->ToggleTool(COLLIDABLE_TOOL_ID, m_tileset->GetTileHitbox(m_currentTile).collidable);
|
||||
m_mainToolbar->ToggleTool(COLLIDABLE_TOOL_ID, m_tileset->IsTileCollidable(m_currentTile));
|
||||
UpdateScrollbars();
|
||||
m_tilePreviewPanel->Refresh();
|
||||
|
||||
@@ -150,7 +151,7 @@ void TileEditor::OnPreviewPaint(wxPaintEvent& event)
|
||||
|
||||
void TileEditor::OnCollidableToolToggled(wxCommandEvent& event)
|
||||
{
|
||||
m_tileset->GetTileHitbox(m_currentTile).collidable = event.IsChecked();
|
||||
m_tileset->SetTileCollidable(m_currentTile, event.IsChecked());
|
||||
}
|
||||
|
||||
void TileEditor::OnPredefinedShapeToolClicked(wxCommandEvent& event)
|
||||
@@ -167,33 +168,33 @@ void TileEditor::OnPredefinedShapeMenuItemClicked(wxCommandEvent& event)
|
||||
switch(event.GetId())
|
||||
{
|
||||
case RECTANGLE_SHAPE_TOOL_ID:
|
||||
m_tileset->GetTileHitbox(m_currentTile) = TileHitbox::Rectangle(m_tileset->tileSize);
|
||||
m_tileset->GetTileHitboxRef(m_currentTile) = TileHitbox::Rectangle(m_tileset->tileSize);
|
||||
break;
|
||||
case TRIANGLE_TL_SHAPE_TOOL_ID:
|
||||
m_tileset->GetTileHitbox(m_currentTile) = TileHitbox::Triangle(m_tileset->tileSize, TileHitbox::TopLeft);
|
||||
m_tileset->GetTileHitboxRef(m_currentTile) = TileHitbox::Triangle(m_tileset->tileSize, TileHitbox::TopLeft);
|
||||
break;
|
||||
case TRIANGLE_TR_SHAPE_TOOL_ID:
|
||||
m_tileset->GetTileHitbox(m_currentTile) = TileHitbox::Triangle(m_tileset->tileSize, TileHitbox::TopRight);
|
||||
m_tileset->GetTileHitboxRef(m_currentTile) = TileHitbox::Triangle(m_tileset->tileSize, TileHitbox::TopRight);
|
||||
break;
|
||||
case TRIANGLE_BR_SHAPE_TOOL_ID:
|
||||
m_tileset->GetTileHitbox(m_currentTile) = TileHitbox::Triangle(m_tileset->tileSize, TileHitbox::BottomRight);
|
||||
m_tileset->GetTileHitboxRef(m_currentTile) = TileHitbox::Triangle(m_tileset->tileSize, TileHitbox::BottomRight);
|
||||
break;
|
||||
case TRIANGLE_BL_SHAPE_TOOL_ID:
|
||||
m_tileset->GetTileHitbox(m_currentTile) = TileHitbox::Triangle(m_tileset->tileSize, TileHitbox::BottomLeft);
|
||||
m_tileset->GetTileHitboxRef(m_currentTile) = TileHitbox::Triangle(m_tileset->tileSize, TileHitbox::BottomLeft);
|
||||
break;
|
||||
case SEMIRECT_T_SHAPE_TOOL_ID:
|
||||
m_tileset->GetTileHitbox(m_currentTile) = TileHitbox::Rectangle(sf::Vector2f(m_tileset->tileSize.x, m_tileset->tileSize.y/2.f));
|
||||
m_tileset->GetTileHitboxRef(m_currentTile) = TileHitbox::Rectangle(sf::Vector2f(m_tileset->tileSize.x, m_tileset->tileSize.y/2.f));
|
||||
break;
|
||||
case SEMIRECT_R_SHAPE_TOOL_ID:
|
||||
m_tileset->GetTileHitbox(m_currentTile) = TileHitbox::Rectangle(sf::Vector2f(m_tileset->tileSize.x/2.f, m_tileset->tileSize.y));
|
||||
m_tileset->GetTileHitbox(m_currentTile).hitbox.Move(m_tileset->tileSize.x/2.f, 0);
|
||||
m_tileset->GetTileHitboxRef(m_currentTile) = TileHitbox::Rectangle(sf::Vector2f(m_tileset->tileSize.x/2.f, m_tileset->tileSize.y));
|
||||
m_tileset->GetTileHitboxRef(m_currentTile).hitbox.Move(m_tileset->tileSize.x/2.f, 0);
|
||||
break;
|
||||
case SEMIRECT_B_SHAPE_TOOL_ID:
|
||||
m_tileset->GetTileHitbox(m_currentTile) = TileHitbox::Rectangle(sf::Vector2f(m_tileset->tileSize.x, m_tileset->tileSize.y/2.f));
|
||||
m_tileset->GetTileHitbox(m_currentTile).hitbox.Move(0, m_tileset->tileSize.y/2.f);
|
||||
m_tileset->GetTileHitboxRef(m_currentTile) = TileHitbox::Rectangle(sf::Vector2f(m_tileset->tileSize.x, m_tileset->tileSize.y/2.f));
|
||||
m_tileset->GetTileHitboxRef(m_currentTile).hitbox.Move(0, m_tileset->tileSize.y/2.f);
|
||||
break;
|
||||
case SEMIRECT_L_SHAPE_TOOL_ID:
|
||||
m_tileset->GetTileHitbox(m_currentTile) = TileHitbox::Rectangle(sf::Vector2f(m_tileset->tileSize.x/2.f, m_tileset->tileSize.y));
|
||||
m_tileset->GetTileHitboxRef(m_currentTile) = TileHitbox::Rectangle(sf::Vector2f(m_tileset->tileSize.x/2.f, m_tileset->tileSize.y));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -207,7 +208,7 @@ void TileEditor::OnAddPointToolClicked(wxCommandEvent& event)
|
||||
if(!m_tileset || m_tileset->IsDirty())
|
||||
return;
|
||||
|
||||
Polygon2d &mask = m_tileset->GetTileHitbox(m_currentTile).hitbox;
|
||||
Polygon2d &mask = m_tileset->GetTileHitboxRef(m_currentTile).hitbox;
|
||||
|
||||
int selectedPoint = m_polygonHelper.GetSelectedPoint();
|
||||
if(selectedPoint >= mask.vertices.size() || selectedPoint < 0)
|
||||
@@ -234,7 +235,7 @@ void TileEditor::OnEditPointToolClicked(wxCommandEvent& event)
|
||||
if(!m_tileset || m_tileset->IsDirty())
|
||||
return;
|
||||
|
||||
Polygon2d &mask = m_tileset->GetTileHitbox(m_currentTile).hitbox;
|
||||
Polygon2d &mask = m_tileset->GetTileHitboxRef(m_currentTile).hitbox;
|
||||
int selectedPoint = m_polygonHelper.GetSelectedPoint();
|
||||
if(selectedPoint >= mask.vertices.size() || selectedPoint < 0)
|
||||
return;
|
||||
@@ -253,7 +254,7 @@ void TileEditor::OnRemovePointToolClicked(wxCommandEvent& event)
|
||||
if(!m_tileset || m_tileset->IsDirty())
|
||||
return;
|
||||
|
||||
Polygon2d &mask = m_tileset->GetTileHitbox(m_currentTile).hitbox;
|
||||
Polygon2d &mask = m_tileset->GetTileHitboxRef(m_currentTile).hitbox;
|
||||
if(mask.vertices.size() <= 3)
|
||||
return;
|
||||
|
||||
@@ -274,9 +275,9 @@ void TileEditor::OnPreviewLeftDown(wxMouseEvent& event)
|
||||
event.SetX(m_tilePreviewPanel->CalcUnscrolledPosition(wxPoint(event.GetX(), event.GetY())).x);
|
||||
event.SetY(m_tilePreviewPanel->CalcUnscrolledPosition(wxPoint(event.GetX(), event.GetY())).y);
|
||||
|
||||
std::vector<Polygon2d> polygonList(1, m_tileset->GetTileHitbox(m_currentTile).hitbox);
|
||||
std::vector<Polygon2d> polygonList(1, m_tileset->GetTileHitboxRef(m_currentTile).hitbox);
|
||||
m_polygonHelper.OnMouseLeftDown(polygonList, event, wxPoint(m_xOffset, m_yOffset));
|
||||
m_tileset->GetTileHitbox(m_currentTile).hitbox = polygonList[0];
|
||||
m_tileset->GetTileHitboxRef(m_currentTile).hitbox = polygonList[0];
|
||||
|
||||
m_tilePreviewPanel->Refresh();
|
||||
}
|
||||
@@ -299,9 +300,9 @@ void TileEditor::OnPreviewMotion(wxMouseEvent& event)
|
||||
event.SetX(m_tilePreviewPanel->CalcUnscrolledPosition(wxPoint(event.GetX(), event.GetY())).x);
|
||||
event.SetY(m_tilePreviewPanel->CalcUnscrolledPosition(wxPoint(event.GetX(), event.GetY())).y);
|
||||
|
||||
std::vector<Polygon2d> polygonList(1, m_tileset->GetTileHitbox(m_currentTile).hitbox);
|
||||
std::vector<Polygon2d> polygonList(1, m_tileset->GetTileHitboxRef(m_currentTile).hitbox);
|
||||
m_polygonHelper.OnMouseMove(polygonList, event, wxPoint(m_xOffset, m_yOffset), 0.f, 0.f, m_tileset->tileSize.x, m_tileset->tileSize.y);
|
||||
m_tileset->GetTileHitbox(m_currentTile).hitbox = polygonList[0];
|
||||
m_tileset->GetTileHitboxRef(m_currentTile).hitbox = polygonList[0];
|
||||
|
||||
m_tilePreviewPanel->Refresh();
|
||||
}
|
||||
|
@@ -90,7 +90,6 @@ void TileMapObject::DoSerializeTo(gd::SerializerElement & element) const
|
||||
void TileMapObject::LoadResources(gd::Project & project, gd::Layout & layout)
|
||||
{
|
||||
tileSet.Get().LoadResources(project);
|
||||
tileSet.Get().Generate();
|
||||
vertexArray = TileMapExtension::GenerateVertexArray(tileSet.Get(), tileMap.Get());
|
||||
}
|
||||
|
||||
@@ -156,4 +155,3 @@ gd::Object * CreateTileMapObject(gd::String name)
|
||||
{
|
||||
return new TileMapObject(name);
|
||||
}
|
||||
|
||||
|
@@ -125,6 +125,8 @@ void TileMapObjectEditor::OnCancelButtonPressed(wxCommandEvent& event)
|
||||
|
||||
void TileMapObjectEditor::OnOkButtonPressed(wxCommandEvent& event)
|
||||
{
|
||||
tileSet.StripUselessHitboxes();
|
||||
|
||||
object.tileSet = TileSetProxy(tileSet);
|
||||
object.tileMap = TileMapProxy(tileMap);
|
||||
|
||||
@@ -139,7 +141,6 @@ void TileMapObjectEditor::OnTileSetConfigureButtonClicked(wxCommandEvent& event)
|
||||
dialog.ShowModal();
|
||||
|
||||
tileSet.LoadResources(game);
|
||||
tileSet.Generate();
|
||||
|
||||
if(oldTextureName != tileSet.textureName)
|
||||
{
|
||||
|
@@ -87,7 +87,7 @@ std::vector<Polygon2d> GenerateHitboxes(TileSet &tileSet, TileMap &tileMap)
|
||||
//Note : a hitbox is also added for empty/non-collidable tiles to ease the hitbox update when changing a tile
|
||||
Polygon2d newPolygon;
|
||||
|
||||
if(tileMap.GetTile(layer, col, row) != -1 && tileSet.GetTileHitbox(tileMap.GetTile(layer, col, row)).collidable)
|
||||
if(tileMap.GetTile(layer, col, row) != -1 && tileSet.IsTileCollidable(tileMap.GetTile(layer, col, row)))
|
||||
{
|
||||
newPolygon = tileSet.GetTileHitbox(tileMap.GetTile(layer, col, row)).hitbox;
|
||||
}
|
||||
@@ -136,7 +136,7 @@ void UpdateHitboxes(std::vector<Polygon2d> &polygons, sf::Vector2f position, int
|
||||
const int tileWidth = tileSet.tileSize.x;
|
||||
const int tileHeight = tileSet.tileSize.y;
|
||||
|
||||
if(tileMap.GetTile(layer, col, row) != -1 && tileSet.GetTileHitbox(tileMap.GetTile(layer, col, row)).collidable)
|
||||
if(tileMap.GetTile(layer, col, row) != -1 && tileSet.IsTileCollidable(tileMap.GetTile(layer, col, row)))
|
||||
{
|
||||
polygons[vertexPos] = tileSet.GetTileHitbox(tileMap.GetTile(layer, col, row)).hitbox;
|
||||
}
|
||||
|
@@ -22,10 +22,30 @@ This project is released under the MIT License.
|
||||
wxBitmap TileSet::m_invalidBitmap = wxBitmap();
|
||||
#endif
|
||||
|
||||
bool TileHitbox::operator==(const TileHitbox &other) const
|
||||
{
|
||||
if(hitbox.vertices.size() == other.hitbox.vertices.size())
|
||||
{
|
||||
for(unsigned int i = 0; i < hitbox.vertices.size(); ++i)
|
||||
{
|
||||
if( fabs( hitbox.vertices[i].x - other.hitbox.vertices[i].x ) > 0.01f ||
|
||||
fabs( hitbox.vertices[i].y - other.hitbox.vertices[i].y ) > 0.01f )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TileHitbox::operator!=(const TileHitbox &other) const
|
||||
{
|
||||
return !(operator==(other));
|
||||
}
|
||||
|
||||
TileHitbox TileHitbox::Rectangle(sf::Vector2f tileSize)
|
||||
{
|
||||
TileHitbox hitbox;
|
||||
hitbox.collidable = true;
|
||||
hitbox.hitbox = Polygon2d::CreateRectangle(tileSize.x, tileSize.y);
|
||||
hitbox.hitbox.Move(tileSize.x/2.f, tileSize.y/2.f);
|
||||
|
||||
@@ -35,7 +55,6 @@ TileHitbox TileHitbox::Rectangle(sf::Vector2f tileSize)
|
||||
TileHitbox TileHitbox::Triangle(sf::Vector2f tileSize, TriangleOrientation orientation)
|
||||
{
|
||||
TileHitbox hitbox;
|
||||
hitbox.collidable = true;
|
||||
|
||||
if(orientation != TileHitbox::BottomRight)
|
||||
hitbox.hitbox.vertices.push_back(sf::Vector2f(0,0));
|
||||
@@ -54,8 +73,6 @@ TileHitbox TileHitbox::Triangle(sf::Vector2f tileSize, TriangleOrientation orien
|
||||
|
||||
void TileHitbox::SerializeTo(gd::SerializerElement &element) const
|
||||
{
|
||||
element.SetAttribute("collidable", collidable);
|
||||
|
||||
//Serialize the polygon
|
||||
gd::String polygonStr;
|
||||
for(std::vector<sf::Vector2f>::const_iterator vertexIt = hitbox.vertices.begin(); vertexIt != hitbox.vertices.end(); vertexIt++)
|
||||
@@ -70,8 +87,6 @@ void TileHitbox::SerializeTo(gd::SerializerElement &element) const
|
||||
|
||||
void TileHitbox::UnserializeFrom(const gd::SerializerElement &element, sf::Vector2f defaultTileSize)
|
||||
{
|
||||
collidable = element.GetBoolAttribute("collidable", true);
|
||||
|
||||
hitbox.vertices.clear();
|
||||
|
||||
gd::String defaultPolygonStr = "0;0|"
|
||||
@@ -89,7 +104,7 @@ void TileHitbox::UnserializeFrom(const gd::SerializerElement &element, sf::Vecto
|
||||
}
|
||||
}
|
||||
|
||||
TileSet::TileSet() : textureName(), tileSize(24, 24), tileSpacing(0, 0), m_tilesetTexture(), m_dirty(true)
|
||||
TileSet::TileSet() : textureName(), tileSize(24, 24), tileSpacing(0, 0), m_tilesetTexture()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -101,14 +116,11 @@ TileSet::~TileSet()
|
||||
|
||||
void TileSet::LoadResources(RuntimeGame &game)
|
||||
{
|
||||
m_dirty = true;
|
||||
m_tilesetTexture = game.GetImageManager()->GetSFMLTexture(textureName);
|
||||
}
|
||||
|
||||
void TileSet::LoadResources(gd::Project &game)
|
||||
{
|
||||
m_dirty = true;
|
||||
|
||||
if(game.GetResourcesManager().HasResource(textureName))
|
||||
{
|
||||
gd::ImageResource & image = dynamic_cast<gd::ImageResource&>(game.GetResourcesManager().GetResource(textureName));
|
||||
@@ -125,10 +137,12 @@ void TileSet::LoadResources(gd::Project &game)
|
||||
wxSetWorkingDirectory(oldWorkingDir);
|
||||
if ( wxFileExists(image.GetAbsoluteFile(game)) )
|
||||
{
|
||||
wxBitmap bmp( image.GetAbsoluteFile(game), wxBITMAP_TYPE_ANY);
|
||||
m_tilesetBitmap = bmp;
|
||||
m_tilesetBitmap.LoadFile(image.GetAbsoluteFile(game), wxBITMAP_TYPE_ANY);
|
||||
}
|
||||
#endif
|
||||
|
||||
//Readjust the m_collidable std::vector according to the number of tiles
|
||||
m_collidable.resize(GetTilesCount(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -136,60 +150,18 @@ void TileSet::LoadResources(gd::Project &game)
|
||||
}
|
||||
}
|
||||
|
||||
void TileSet::Generate()
|
||||
{
|
||||
m_dirty = true;
|
||||
|
||||
if (!m_tilesetTexture)
|
||||
return;
|
||||
|
||||
std::cout << "Generating texture coords..." << std::endl;
|
||||
|
||||
//Calculates the number of rows and columns in the tileset
|
||||
int columns(0), rows(0);
|
||||
if (tileSize.x == 0 || tileSize.y == 0)
|
||||
return;
|
||||
columns = (m_tilesetTexture->texture.getSize().x + tileSpacing.x) / (tileSize.x + tileSpacing.x);
|
||||
rows = (m_tilesetTexture->texture.getSize().y + tileSpacing.y) / (tileSize.y + tileSpacing.y);
|
||||
|
||||
//Generate the TextureCoords and the sub-bitmaps (only in IDE)
|
||||
m_coords.clear();
|
||||
for(int row = 0; row < rows; row++)
|
||||
{
|
||||
for(int col = 0; col < columns; col++)
|
||||
{
|
||||
//TileTextureCoords
|
||||
TileTextureCoords tileCoords;
|
||||
tileCoords.topLeft = sf::Vector2f(col * (tileSize.x + tileSpacing.x),
|
||||
row * (tileSize.y + tileSpacing.y));
|
||||
tileCoords.topRight = sf::Vector2f(col * (tileSize.x + tileSpacing.x) + tileSize.x,
|
||||
row * (tileSize.y + tileSpacing.y));
|
||||
tileCoords.bottomRight = sf::Vector2f(col * (tileSize.x + tileSpacing.x) + tileSize.x,
|
||||
row * (tileSize.y + tileSpacing.y) + tileSize.y);
|
||||
tileCoords.bottomLeft = sf::Vector2f(col * (tileSize.x + tileSpacing.x),
|
||||
row * (tileSize.y + tileSpacing.y) + tileSize.y);
|
||||
m_coords.push_back(tileCoords);
|
||||
}
|
||||
}
|
||||
|
||||
//Puts the default hitbox for new tiles (if there are more tiles than before)
|
||||
if (GetTilesCount() > m_hitboxes.size())
|
||||
m_hitboxes.insert(m_hitboxes.end(), (GetTilesCount()-m_hitboxes.size()), TileHitbox::Rectangle(tileSize));
|
||||
|
||||
std::cout << "OK" << std::endl;
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
void TileSet::ResetHitboxes()
|
||||
{
|
||||
m_collidable.clear();
|
||||
m_hitboxes.clear();
|
||||
if (m_dirty)
|
||||
|
||||
if (IsDirty())
|
||||
return;
|
||||
|
||||
m_hitboxes.assign(GetTilesCount(), TileHitbox::Rectangle(tileSize));
|
||||
m_collidable.assign(GetTilesCount(), true);
|
||||
}
|
||||
|
||||
int TileSet::GetTileIDFromPosition(sf::Vector2f position)
|
||||
int TileSet::GetTileIDFromPosition(sf::Vector2f position) const
|
||||
{
|
||||
int columns = GetColumnsCount();
|
||||
int rows = GetRowsCount();
|
||||
@@ -200,7 +172,7 @@ int TileSet::GetTileIDFromPosition(sf::Vector2f position)
|
||||
return (tileColumn * columns + tileRow);
|
||||
}
|
||||
|
||||
int TileSet::GetTileIDFromCell(int col, int row)
|
||||
int TileSet::GetTileIDFromCell(int col, int row) const
|
||||
{
|
||||
int columns = GetColumnsCount();
|
||||
int rows = GetRowsCount();
|
||||
@@ -208,6 +180,13 @@ int TileSet::GetTileIDFromCell(int col, int row)
|
||||
return (row * columns + col);
|
||||
}
|
||||
|
||||
sf::Vector2u TileSet::GetTileCellFromID(int id) const
|
||||
{
|
||||
int columns = GetColumnsCount();
|
||||
int rows = GetRowsCount();
|
||||
return sf::Vector2u(id - (id / columns) * columns, id / columns);
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI)
|
||||
const wxBitmap& TileSet::GetWxBitmap() const
|
||||
{
|
||||
@@ -227,7 +206,19 @@ const sf::Texture& TileSet::GetTexture() const
|
||||
|
||||
TileTextureCoords TileSet::GetTileTextureCoords(int id) const
|
||||
{
|
||||
return m_coords.at(id);
|
||||
//Calculate the tile coords
|
||||
sf::Vector2u cell = GetTileCellFromID(id);
|
||||
|
||||
TileTextureCoords tileCoords;
|
||||
tileCoords.topLeft = sf::Vector2f(cell.x * (tileSize.x + tileSpacing.x),
|
||||
cell.y * (tileSize.y + tileSpacing.y));
|
||||
tileCoords.topRight = sf::Vector2f(cell.x * (tileSize.x + tileSpacing.x) + tileSize.x,
|
||||
cell.y * (tileSize.y + tileSpacing.y));
|
||||
tileCoords.bottomRight = sf::Vector2f(cell.x * (tileSize.x + tileSpacing.x) + tileSize.x,
|
||||
cell.y * (tileSize.y + tileSpacing.y) + tileSize.y);
|
||||
tileCoords.bottomLeft = sf::Vector2f(cell.x * (tileSize.x + tileSpacing.x),
|
||||
cell.y * (tileSize.y + tileSpacing.y) + tileSize.y);
|
||||
return tileCoords;
|
||||
}
|
||||
|
||||
sf::Vector2u TileSet::GetSize() const
|
||||
@@ -238,14 +229,43 @@ sf::Vector2u TileSet::GetSize() const
|
||||
return m_tilesetTexture->texture.getSize();
|
||||
}
|
||||
|
||||
TileHitbox& TileSet::GetTileHitbox(int id)
|
||||
bool TileSet::IsTileCollidable(int id) const
|
||||
{
|
||||
return m_collidable[id];
|
||||
}
|
||||
|
||||
void TileSet::SetTileCollidable(int id, bool collidable)
|
||||
{
|
||||
m_collidable[id] = collidable;
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void TileSet::StripUselessHitboxes()
|
||||
{
|
||||
auto it = m_hitboxes.begin();
|
||||
while(it != m_hitboxes.end())
|
||||
{
|
||||
if( (it->second) == TileHitbox::Rectangle(tileSize) ) //This is an useless hitbox, remove it.
|
||||
it = m_hitboxes.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TileHitbox& TileSet::GetTileHitboxRef(int id)
|
||||
{
|
||||
if(m_hitboxes.count(id) == 0)
|
||||
m_hitboxes[id] = TileHitbox::Rectangle(tileSize);
|
||||
return m_hitboxes[id];
|
||||
}
|
||||
|
||||
const TileHitbox& TileSet::GetTileHitbox(int id) const
|
||||
TileHitbox TileSet::GetTileHitbox(int id) const
|
||||
{
|
||||
return m_hitboxes.at(id);
|
||||
if(m_hitboxes.count(id) == 0)
|
||||
return TileHitbox::Rectangle(tileSize);
|
||||
else
|
||||
return m_hitboxes.at(id);
|
||||
}
|
||||
|
||||
int TileSet::GetColumnsCount() const
|
||||
@@ -261,26 +281,35 @@ int TileSet::GetRowsCount() const
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void TileSet::SerializeTo(gd::SerializerElement &element) const
|
||||
{
|
||||
element.SetAttribute("version", 2);
|
||||
element.SetAttribute("textureName", textureName);
|
||||
element.SetAttribute("tileSizeX", tileSize.x);
|
||||
element.SetAttribute("tileSizeY", tileSize.y);
|
||||
element.SetAttribute("tileSpacingX", tileSpacing.x);
|
||||
element.SetAttribute("tileSpacingY", tileSpacing.y);
|
||||
|
||||
gd::SerializerElement &tilesElem = element.AddChild("hitboxes");
|
||||
//Save if it is collidable or not
|
||||
gd::SerializerElement &collidableElem = element.AddChild("collidable");
|
||||
for(auto it = m_collidable.begin(); it != m_collidable.end(); ++it)
|
||||
{
|
||||
gd::SerializerElement &tileElem = collidableElem.AddChild("tile");
|
||||
tileElem.SetAttribute("collidable", *it);
|
||||
}
|
||||
|
||||
//Save polygons
|
||||
for(std::vector<TileHitbox>::const_iterator it = m_hitboxes.begin(); it != m_hitboxes.end(); it++)
|
||||
//Save polygons hitboxes
|
||||
gd::SerializerElement &tilesElem = element.AddChild("hitboxes");
|
||||
for(auto it = m_hitboxes.begin(); it != m_hitboxes.end(); ++it)
|
||||
{
|
||||
gd::SerializerElement &hitboxElem = tilesElem.AddChild("tileHitbox");
|
||||
it->SerializeTo(hitboxElem);
|
||||
hitboxElem.SetAttribute("tileId", it->first);
|
||||
it->second.SerializeTo(hitboxElem);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void TileSet::UnserializeFrom(const gd::SerializerElement &element)
|
||||
{
|
||||
ResetHitboxes();
|
||||
int serializationVersion = element.GetIntAttribute("version", 1);
|
||||
|
||||
textureName = element.GetStringAttribute("textureName", "");
|
||||
tileSize.x = element.GetIntAttribute("tileSizeX", 32);
|
||||
@@ -288,17 +317,39 @@ void TileSet::UnserializeFrom(const gd::SerializerElement &element)
|
||||
tileSpacing.x = element.GetIntAttribute("tileSpacingX", 0);
|
||||
tileSpacing.y = element.GetIntAttribute("tileSpacingY", 0);
|
||||
|
||||
if (element.HasChild("hitboxes"))
|
||||
ResetHitboxes();
|
||||
m_collidable.clear();
|
||||
|
||||
if(serializationVersion == 1)
|
||||
{
|
||||
gd::SerializerElement &tilesElem = element.GetChild("hitboxes");
|
||||
tilesElem.ConsiderAsArrayOf("tileHitbox");
|
||||
for(int i = 0; i < tilesElem.GetChildrenCount("tileHitbox"); i++)
|
||||
if(element.HasChild("hitboxes"))
|
||||
{
|
||||
TileHitbox newHitbox;
|
||||
newHitbox.UnserializeFrom(tilesElem.GetChild(i), tileSize);
|
||||
m_hitboxes.push_back(newHitbox);
|
||||
gd::SerializerElement &tilesElem = element.GetChild("hitboxes");
|
||||
tilesElem.ConsiderAsArrayOf("tileHitbox");
|
||||
for(int i = 0; i < tilesElem.GetChildrenCount("tileHitbox"); i++)
|
||||
{
|
||||
m_collidable.push_back(tilesElem.GetChild(i).GetBoolAttribute("collidable", true));
|
||||
TileHitbox newHitbox;
|
||||
newHitbox.UnserializeFrom(tilesElem.GetChild(i), tileSize);
|
||||
if(newHitbox != TileHitbox::Rectangle(tileSize))
|
||||
m_hitboxes[i] = newHitbox;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(serializationVersion == 2)
|
||||
{
|
||||
gd::SerializerElement &collidableElem = element.GetChild("collidable");
|
||||
collidableElem.ConsiderAsArrayOf("tile");
|
||||
for(int i = 0; i < collidableElem.GetChildrenCount("tile"); i++)
|
||||
{
|
||||
m_collidable.push_back(collidableElem.GetChild(i).GetBoolAttribute("collidable", true));
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
gd::SerializerElement &hitboxesElem = element.GetChild("hitboxes");
|
||||
hitboxesElem.ConsiderAsArrayOf("tileHitbox");
|
||||
for(int i = 0; i < hitboxesElem.GetChildrenCount("tileHitbox"); i++)
|
||||
{
|
||||
m_hitboxes[hitboxesElem.GetChild(i).GetIntAttribute("tileId", -1)].UnserializeFrom(hitboxesElem.GetChild(i), tileSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ This project is released under the MIT License.
|
||||
#include <wx/bitmap.h>
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
@@ -47,9 +48,11 @@ struct TileHitbox
|
||||
BottomLeft ///< In the bottom-left hand corner
|
||||
};
|
||||
|
||||
bool collidable; ///< True to make the tile collidable
|
||||
Polygon2d hitbox; ///< The polygonal hitbox
|
||||
|
||||
bool operator==(const TileHitbox &other) const;
|
||||
bool operator!=(const TileHitbox &other) const;
|
||||
|
||||
/**
|
||||
* Generates a default hitbox (rectangle of the size of the tile).
|
||||
*/
|
||||
@@ -98,11 +101,10 @@ public:
|
||||
*/
|
||||
///\{
|
||||
/**
|
||||
* Returns true if the tileset hasn't been loaded and generated from a picture.
|
||||
* \warning Can return true even if the loaded texture doesn't correspond to the TileSet::textureName or
|
||||
* if the TileSet::tileSize or TileSet::tileSpacing have been modified as the object is not in a invalid state.
|
||||
* Returns true if the tileset hasn't been loaded (texture not loaded) or have an invalid tile size.
|
||||
* \warning Can return true even if the loaded texture doesn't correspond to the TileSet::textureName
|
||||
*/
|
||||
bool IsDirty() const {return m_dirty;};
|
||||
bool IsDirty() const {return (!m_tilesetTexture || tileSize.x == 0.f || tileSize.y == 0.f);}
|
||||
|
||||
/**
|
||||
* Load the image for the tilemap. Need to be called when using the TileSet for the first or after a texture change.
|
||||
@@ -117,13 +119,6 @@ public:
|
||||
* in the scene preview or in a release game.
|
||||
*/
|
||||
void LoadResources(RuntimeGame &game);
|
||||
|
||||
/**
|
||||
* Generate the tile texture coords and temporary bitmaps for the IDE.
|
||||
* Need to be called after a change in TileSet::textureName (in that case after TileSet::LoadResources) or after a change in the TileSet::tileSize or TileSet::tileSpacing.
|
||||
* \sa TileSet::LoadResources
|
||||
*/
|
||||
void Generate();
|
||||
///\}
|
||||
|
||||
/**
|
||||
@@ -167,15 +162,29 @@ public:
|
||||
*/
|
||||
void ResetHitboxes();
|
||||
|
||||
bool IsTileCollidable(int id) const;
|
||||
|
||||
void SetTileCollidable(int id, bool collidable);
|
||||
|
||||
/**
|
||||
* \return the hitbox of a tile.
|
||||
* \return a reference to the hitbox of a tile.
|
||||
* Allows the edition of the hitbox.
|
||||
*/
|
||||
TileHitbox& GetTileHitbox(int id);
|
||||
TileHitbox& GetTileHitboxRef(int id);
|
||||
|
||||
/**
|
||||
* \return the hitbox of a tile.
|
||||
*/
|
||||
const TileHitbox& GetTileHitbox(int id) const;
|
||||
TileHitbox GetTileHitbox(int id) const;
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief Strips useless hitboxes (the default rectangle hitbox) from the hitboxes data of the tileset.
|
||||
* The tileset keeps only non-default hitboxes in memory (the default hitbox for tiles is a rectangle with the same size as tiles).
|
||||
* This method checks if the tileset stores default hitbox and remove them as they are useless.
|
||||
*/
|
||||
void StripUselessHitboxes();
|
||||
#endif
|
||||
///\}
|
||||
|
||||
/**
|
||||
@@ -185,12 +194,17 @@ public:
|
||||
/**
|
||||
* Return the tile ID according to its position.
|
||||
*/
|
||||
int GetTileIDFromPosition(sf::Vector2f position);
|
||||
int GetTileIDFromPosition(sf::Vector2f position) const;
|
||||
|
||||
/**
|
||||
* Return the tile ID according to its row and column.
|
||||
*/
|
||||
int GetTileIDFromCell(int col, int row);
|
||||
int GetTileIDFromCell(int col, int row) const;
|
||||
|
||||
/**
|
||||
* Return the tile cell (col, row) from its ID.
|
||||
*/
|
||||
sf::Vector2u GetTileCellFromID(int id) const;
|
||||
|
||||
/**
|
||||
* \return the number of tiles of the tileset.
|
||||
@@ -230,17 +244,15 @@ public:
|
||||
private:
|
||||
|
||||
std::shared_ptr<SFMLTextureWrapper> m_tilesetTexture; ///< The tileset texture (SFML)
|
||||
std::vector<TileTextureCoords> m_coords; ///< The tileset coords
|
||||
|
||||
std::vector<TileHitbox> m_hitboxes;
|
||||
std::vector<bool> m_collidable;
|
||||
std::map<int, TileHitbox> m_hitboxes;
|
||||
|
||||
#if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI)
|
||||
wxBitmap m_tilesetBitmap; ///< The tileset texture
|
||||
static wxBitmap m_invalidBitmap;
|
||||
#endif
|
||||
|
||||
bool m_dirty;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -58,17 +58,24 @@ TileSetConfigurationEditor::~TileSetConfigurationEditor()
|
||||
|
||||
}
|
||||
|
||||
void TileSetConfigurationEditor::UpdatePreviewTileSetPanel()
|
||||
void TileSetConfigurationEditor::UpdatePreviewTileSetPanel(bool newTexture)
|
||||
{
|
||||
previewTileSet.textureName = m_textureNameTextCtrl->GetValue();
|
||||
std::cout << "Reloading texture..." << std::endl;
|
||||
previewTileSet.LoadResources(game);
|
||||
std::cout << "OK." << std::endl;
|
||||
|
||||
if(newTexture)
|
||||
{
|
||||
//If the texture has changed, put default values for tile size/spacing
|
||||
m_tileWidthSpin->SetValue(std::max(1.f, static_cast<float>(previewTileSet.GetSize().x)/10.f));
|
||||
m_tileHeightSpin->SetValue(std::max(1.f, static_cast<float>(previewTileSet.GetSize().y)/10.f));
|
||||
}
|
||||
previewTileSet.tileSize.x = m_tileWidthSpin->GetValue();
|
||||
previewTileSet.tileSize.y = m_tileHeightSpin->GetValue();
|
||||
previewTileSet.tileSpacing.x = m_spacingWidthSpin->GetValue();
|
||||
previewTileSet.tileSpacing.y = m_spacingHeightSpin->GetValue();
|
||||
|
||||
previewTileSet.LoadResources(game);
|
||||
previewTileSet.Generate();
|
||||
|
||||
if(previewTileSet.GetSize().x >= 1 && previewTileSet.GetSize().y >= 1)
|
||||
{
|
||||
m_tileWidthSpin->SetRange(1, previewTileSet.GetSize().x);
|
||||
@@ -113,7 +120,7 @@ void TileSetConfigurationEditor::OnOkButtonClicked(wxCommandEvent& event)
|
||||
|
||||
void TileSetConfigurationEditor::OnTileSetTextureUpdated(wxCommandEvent& event)
|
||||
{
|
||||
UpdatePreviewTileSetPanel();
|
||||
UpdatePreviewTileSetPanel(true);
|
||||
}
|
||||
|
||||
void TileSetConfigurationEditor::OnTileSetParameterUpdated(wxSpinEvent& event)
|
||||
|
@@ -28,7 +28,7 @@ private:
|
||||
TileSet previewTileSet;
|
||||
ResourcesEditor *resourcesEditorPnl;
|
||||
|
||||
void UpdatePreviewTileSetPanel();
|
||||
void UpdatePreviewTileSetPanel(bool newTexture = false);
|
||||
|
||||
protected:
|
||||
virtual void OnHelpButtonClicked(wxHyperlinkEvent& event);
|
||||
|
@@ -66,8 +66,8 @@ void TileSetPanel::OnPaint(wxPaintEvent& event)
|
||||
if(m_tileset && !m_tileset->IsDirty())
|
||||
{
|
||||
//Determine the first and last columns and rows to draw
|
||||
int firstCol = std::max((int)(minPos.x / (m_tileset->tileSize.x + m_tileset->tileSpacing.x) - 1), 0);
|
||||
int firstRow = std::max((int)(minPos.y / (m_tileset->tileSize.y + m_tileset->tileSpacing.y) - 1), 0);
|
||||
int firstCol = std::max((int)(minPos.x / (m_tileset->tileSize.x + m_tileset->tileSpacing.x) - 1), 1);
|
||||
int firstRow = std::max((int)(minPos.y / (m_tileset->tileSize.y + m_tileset->tileSpacing.y) - 1), 1);
|
||||
int lastCol = std::min((int)(maxPos.x / (m_tileset->tileSize.x + m_tileset->tileSpacing.x) + 1), m_tileset->GetColumnsCount());
|
||||
int lastRow = std::min((int)(maxPos.y / (m_tileset->tileSize.y + m_tileset->tileSpacing.y) + 1), m_tileset->GetRowsCount());
|
||||
|
||||
|
Reference in New Issue
Block a user