Tile maps can now be painted to correctly

Gui_Panel_Refactor
Joeyrp 4 years ago
parent 60bb47f25e
commit 8360eceabf

@ -1,3 +1,5 @@
High Importance: High Importance:
☐ The Map Editor does not get the tile maps when a project is opened @high ✔ The Map Editor does not get the tile maps when a project is opened @high @done (3/3/2022, 2:47:41 PM)
✔ Tile Set IDs (as opposed to the Asset ID) is not saved or loaded yet @high @done (3/11/2022, 2:10:30 PM)
✔ Had to flip the V component of the UVs for the sprite vertices. This fixes the partial image drawing but will need to be accounted for in other places in the editor. @done (3/14/2022, 1:46:48 PM)

@ -3,7 +3,7 @@ Editor:
✔ Come up with project directory structure @done (9/17/2021, 6:46:44 PM) ✔ Come up with project directory structure @done (9/17/2021, 6:46:44 PM)
✔ Make the editor a separate module @high @done (11/1/2021, 2:24:35 PM) ✔ Make the editor a separate module @high @done (11/1/2021, 2:24:35 PM)
✔ Implement Run Mode interface class @high @done (2/8/2022, 4:05:17 PM) ✔ Implement Run Mode interface class @high @done (2/8/2022, 4:05:17 PM)
Reference raw asset files in a "content" folder@high Reference raw asset files in a "content" folder@high @done (3/3/2022, 3:15:32 PM)
✔ Platform independant file browsing @done (2/8/2022, 4:05:29 PM) ✔ Platform independant file browsing @done (2/8/2022, 4:05:29 PM)
☐ Scan script files to make sure they don't overwrite globals ☐ Scan script files to make sure they don't overwrite globals
☐ Figure out how to make game asset types integrate with editor asset types @critical ☐ Figure out how to make game asset types integrate with editor asset types @critical
@ -14,22 +14,22 @@ Editor:
Raw Asset Importers: Raw Asset Importers:
- Need classes to import raw resource files for the editor - Need classes to import raw resource files for the editor
✔ Raw Resource importer interface class (EditorAsset) @done (2/24/2022, 3:14:04 PM) ✔ Raw Resource importer interface class (EditorAsset) @done (2/24/2022, 3:14:04 PM)
☐ Raw Image importer class ✔ Raw Image importer method @done (3/3/2022, 3:15:51 PM)
☐ Raw Sound importer class ☐ Raw Sound importer method
☐ Raw font file importer class ☐ Raw font file importer method
☐ Tile Set ✔ Tile Set @done (3/3/2022, 3:16:08 PM)
☐ Tile Map ☐ Tile Map
Project (Class for loading and tracking project data): Project (Class for loading and tracking project data):
✔ Generate new project at given location @done (11/9/2021, 3:26:03 PM) ✔ Generate new project at given location @done (11/9/2021, 3:26:03 PM)
☐ Save project data ✔ Save project data @done (3/3/2022, 3:16:16 PM)
✔ Open existing project @done (2/8/2022, 4:05:42 PM) ✔ Open existing project @done (2/8/2022, 4:05:42 PM)
Content Manager: Content Manager:
✔ Design interface @done (2/24/2022, 3:15:39 PM) ✔ Design interface @done (2/24/2022, 3:15:39 PM)
✔ Generate new content file @done (2/24/2022, 3:16:00 PM) ✔ Generate new content file @done (2/24/2022, 3:16:00 PM)
☐ Load existing contents ✔ Load existing contents @done (3/3/2022, 3:16:21 PM)
☐ Save/Update contents file ✔ Save/Update contents file @done (3/3/2022, 3:16:23 PM)
GUI Panels: GUI Panels:
Project Overview (Tree view): Project Overview (Tree view):
@ -43,7 +43,14 @@ Editor:
Tools: Tools:
Tile Map Editor: Tile Map Editor:
☐ Tile map canvas ☐ Allow Tile Maps to be named
Tile Map Canvas:
Implement drawing tiles:
✔ Connect Selected Tile Set to the Canvas @done (3/11/2022, 6:11:07 PM)
✔ Handle mouse clicking in update @done (3/11/2022, 6:11:09 PM)
✔ Update current Map with current Tile on mouse click @done (3/11/2022, 6:11:12 PM)
✔ Tile map pallete @done (2/24/2022, 3:15:26 PM) ✔ Tile map pallete @done (2/24/2022, 3:15:26 PM)
☐ Hideable grid ☐ Hideable grid
☐ Stamp creater ☐ Stamp creater

@ -11,6 +11,7 @@
namespace lunarium namespace lunarium
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// COLOR // COLOR
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

@ -13,6 +13,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <box2d/box2d.h> #include <box2d/box2d.h>
namespace lunarium namespace lunarium
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -23,6 +24,9 @@ namespace lunarium
{ {
T X; T X;
T Y; T Y;
bool operator==(const Vec2<T>& rhs) const { return (this->X == rhs.X && this->Y == rhs.Y); }
bool operator!=(const Vec2<T>& rhs) const { return !((*this) == rhs); }
}; };
typedef Vec2<int> Vec2i; typedef Vec2<int> Vec2i;
@ -37,6 +41,9 @@ namespace lunarium
{ {
T Width; T Width;
T Height; T Height;
bool operator==(const Size<T>& rhs) const { return (this->Width == rhs.Width && this->Height == rhs.Height); }
bool operator!=(const Size<T>& rhs) const { return !((*this) == rhs); }
}; };
typedef Size<int> Sizei; typedef Size<int> Sizei;

@ -50,7 +50,7 @@ namespace lunarium
\ \
void main()\ void main()\
{\ {\
TexCoords = vec2(vertex.z * uvManip.x + uvManip.y, vertex.w * uvManip.z + uvManip.w);\ TexCoords = vec2(vertex.z * uvManip.x + uvManip.y, vertex.w * uvManip.z - uvManip.w);\
gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0);\ gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0);\
}"; }";

@ -479,35 +479,21 @@ namespace lunarium
trans = glm::rotate(trans, angle, glm::vec3(0.0f, 0.0f, 1.0f)); trans = glm::rotate(trans, angle, glm::vec3(0.0f, 0.0f, 1.0f));
trans = glm::scale(trans, glm::vec3(destination.HalfWidth * 2, destination.HalfHeight * 2, 1.0f)); trans = glm::scale(trans, glm::vec3(destination.HalfWidth * 2, destination.HalfHeight * 2, 1.0f));
mImageShader.MakeActive();
// float widthDiff = image.GetWidth() - source.Width;
// if (source.Width == image.GetWidth() && source.Height == image.GetHeight()) mImageShader.MakeActive();
// {
// mImageShader.SetUniformf("uvManip", { 1.0f, 0.0f, 1.0f, 0.0f }); // No uv Manipulation float xScale = (source.HalfWidth * 2) / image.GetWidth();
// mImageShader.SetUniformMatrix("model", 1, glm::value_ptr(trans)); float xOffset = source.left() / image.GetWidth();
// mImageShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection)); float yScale = (source.HalfHeight * 2) / image.GetHeight();
// mImageShader.SetUniformf("spriteColor", { color.Red, color.Green, color.Blue, color.Alpha }); float yOffset = source.top() / image.GetHeight();
// }
// else
// {
// NOTE: Pretty sure these values will work out to be correct with out the if check
float xScale = (source.HalfWidth * 2) / image.GetWidth();
float xOffset = source.left() / image.GetWidth();
float yScale = (source.HalfHeight * 2) / image.GetHeight();
float yOffset = source.top() / image.GetHeight();
// Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO_VERBOSE, "uvManip Values: %f, %f, %f, %f", xScale, xOffset, yScale, yOffset); // * -1.0f on yScale will flip the image vertically
mImageShader.SetUniformf("uvManip", { xScale, xOffset, yScale * -1.0f, yOffset});
mImageShader.SetUniformMatrix("model", 1, glm::value_ptr(trans));
mImageShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection));
mImageShader.SetUniformf("spriteColor", { color.R, color.G, color.B, color.A });
// * -1.0f on yScale will flip the image vertically
mImageShader.SetUniformf("uvManip", { xScale, xOffset, yScale /** -1.0f*/, yOffset});
mImageShader.SetUniformMatrix("model", 1, glm::value_ptr(trans));
mImageShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection));
mImageShader.SetUniformf("spriteColor", { color.R, color.G, color.B, color.A });
//}
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, image.GetGLTextureID()); glBindTexture(GL_TEXTURE_2D, image.GetGLTextureID());
@ -515,7 +501,6 @@ namespace lunarium
glBindVertexArray(mImageVAO); glBindVertexArray(mImageVAO);
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0); glBindVertexArray(0);
} }
void OglGraphics::DrawString(const char* string, Rectangle boundingArea, Color color, float scale, int font) void OglGraphics::DrawString(const char* string, Rectangle boundingArea, Color color, float scale, int font)
@ -600,15 +585,26 @@ namespace lunarium
// Setup geometry // Setup geometry
// https://learnopengl.com/In-Practice/2D-Game/Rendering-Sprites // https://learnopengl.com/In-Practice/2D-Game/Rendering-Sprites
GLuint VBO; GLuint VBO;
// GLfloat vertices[] = {
// //Pos // Tex
// -0.5f, 0.5f, 0.0f, 0.0f,
// 0.5f, -0.5f, 1.0f, 1.0f,
// -0.5f, -0.5f, 0.0f, 1.0f,
// -0.5f, 0.5f, 0.0f, 0.0f,
// 0.5f, 0.5f, 1.0f, 0.0f,
// 0.5f, -0.5f, 1.0f, 1.0f
// };
GLfloat vertices[] = { GLfloat vertices[] = {
// Pos // Tex //Pos // Tex
-0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 1.0f, 1.0f 0.5f, -0.5f, 1.0f, 0.0f
}; };
// GLfloat vertices[] = { // GLfloat vertices[] = {

@ -4,16 +4,16 @@ set(EDITOR_SRC
"editor.cpp" "editor.cpp"
"editor_helpers.cpp" "editor_helpers.cpp"
"panel_manager.cpp" "panel_manager.cpp"
"project/project.cpp" "project.cpp"
"panels/about.cpp" "panels/about.cpp"
"panels/assetBrowser.cpp" "panels/assetBrowser.cpp"
"panels/worldTree.cpp" "panels/worldTree.cpp"
"panels/worldView.cpp" "panels/worldView.cpp"
"panels/propertiesView.cpp" "panels/propertiesView.cpp"
"project/contents/content_manager.cpp" "contents/content_manager.cpp"
"project/contents/editor_asset.cpp" "contents/editor_asset.cpp"
"project/contents/tile_map.cpp" "contents/tile_map.cpp"
"project/contents/tile_set.cpp" "contents/tile_set.cpp"
"tools/map_editor/map_editor.cpp" "tools/map_editor/map_editor.cpp"
"tools/map_editor/panels/map_canvas.cpp" "tools/map_editor/panels/map_canvas.cpp"
"tools/map_editor/panels/tile_set_view.cpp" "tools/map_editor/panels/tile_set_view.cpp"

@ -9,8 +9,23 @@
#ifndef EDITOR_ASSETS_DEFINITIONS_H_ #ifndef EDITOR_ASSETS_DEFINITIONS_H_
#define EDITOR_ASSETS_DEFINITIONS_H_ #define EDITOR_ASSETS_DEFINITIONS_H_
#include <core/types.h>
namespace lunarium { namespace editor namespace lunarium { namespace editor
{ {
// Allows tiles from multiple tilesets to be used in one map
// A tile ID of -1 will mean "no tile" and result in a transparent spot
// when rendered
struct TileRef
{
int TileSetID;
Vec2i TileIndex;
bool operator==(const TileRef& rhs) const { return this->TileSetID == rhs.TileSetID && this->TileIndex == rhs.TileIndex; }
bool operator!=(const TileRef& rhs) const { return !((*this) == rhs); }
};
enum AssetType enum AssetType
{ {
EATYPE_IMAGE, EATYPE_IMAGE,

@ -0,0 +1,200 @@
/******************************************************************************
* File - tile_map.h
* Author - Joey Pollack
* Date - 2022/02/15 (y/m/d)
* Mod Date - 2022/02/15 (y/m/d)
* Description - Contains a single tile map
******************************************************************************/
#include "tile_map.h"
#include "tile_set.h"
#include <core/core.h>
#include <graphics/graphics.h>
#include <editor/editor.h>
#include <utils/logger.h>
namespace lunarium { namespace editor
{
TileMap::TileMap(Sizei tile_size)
: mpMap(nullptr), mTileSize(tile_size), mIsDirty(false)
{
}
OpRes TileMap::AddTileSet(int id, TileSet* set)
{
if (mTileSets.find(id) != mTileSets.end())
{
return OpRes::Fail("Cannot add tile set to Tile Map - Tile Set with id: %d already exists", id);
}
if (set->GetTileSize() != mTileSize)
{
return OpRes::Fail("Cannot add tile set to Tile Map - Tile size does not match");
}
mTileSets[id] = set;
return OpRes::OK();
}
// NOTE: This could probably be replaced with code that marks it clean on save
// since this class will have to implement saving to a file (because it's an asset).
void TileMap::MarkClean()
{
mIsDirty = false;
}
bool TileMap::IsDirty() const
{
return mIsDirty;
}
void TileMap::ClearMap()
{
for(int i = 0; i < mSizeInTiles.Width; i++)
{
for (int j = 0; j < mSizeInTiles.Height; j++)
{
mpMap[i][j] = { -1, {-1, -1} };
}
}
mIsDirty = true;
}
void TileMap::SetTile(TileRef tile, Vec2i location)
{
if (location.X < 0 || location.X >= mSizeInTiles.Width || location.Y < 0 || location.Y >= mSizeInTiles.Height)
{
return;
}
mpMap[location.X][location.Y] = tile;
mIsDirty = true;
}
TileRef TileMap::GetTile(Vec2i location)
{
if (location.X < 0 || location.X >= mSizeInTiles.Width || location.Y < 0 || location.Y >= mSizeInTiles.Height)
{
return {-1, {-1, -1 }};
}
TileRef tile = mpMap[location.X][location.Y];
// Make sure the tileset exists
if (mTileSets.find(tile.TileSetID) == mTileSets.end())
{
return {-1, {-1, -1 }};
}
return tile;
}
Sizei TileMap::GetSizeInTiles()
{
return mSizeInTiles;
}
Sizei TileMap::GetSizeInPixels()
{
if (!mpMap)
return { 0, 0 };
return { mTileSize.Width * mSizeInTiles.Width, mTileSize.Height * mSizeInTiles.Height };
}
Sizei TileMap::GetTileSize()
{
return mTileSize;
}
void TileMap::ResizeMap(Sizei size)
{
TileRef** new_map = new TileRef*[size.Width];
for(int i = 0; i < size.Width; i++)
{
new_map[i] = new TileRef[size.Height];
}
int smaller_width = mSizeInTiles.Width < size.Width ? mSizeInTiles.Width : size.Width;
int smaller_height = mSizeInTiles.Height < size.Height ? mSizeInTiles.Height : size.Height;
for(int i = 0; i < smaller_width; i++)
{
for (int j = 0; j < smaller_height; j++)
{
new_map[i][j] = mpMap[i][j];
}
}
for(int i = 0; i < mSizeInTiles.Width; i++)
{
delete[] mpMap[i];
}
delete[] mpMap;
mSizeInTiles = size;
mpMap = new_map;
mIsDirty = true;
}
void TileMap::Render(lunarium::IGraphics* g)
{
if (!mpMap)
return;
Sizei map_size_pixels = { mTileSize.Width * mSizeInTiles.Width, mTileSize.Height * mSizeInTiles.Height };
// Draw Map
for (int i = 0; i < mSizeInTiles.Width; i++)
{
for (int j = 0; j < mSizeInTiles.Height; j++)
{
// If there is no tile here skip this spot
if (mpMap[i][j].TileIndex.X == -1 || mpMap[i][j].TileIndex.Y == -1)
continue;
int id = mpMap[i][j].TileSetID;
// -1 means an intentionally empty tile
if (-1 == id)
{
continue;
}
// Make sure the tileset exists
if (mTileSets.find(id) == mTileSets.end())
{
Logger::Log(Editor::LogCat, LogLevel::WARNING, "Tile Map is missing tile set. No Tile Set with id: %d", id);
continue;
}
TileSet* set = mTileSets[id];
Rectangle dest = Rectangle::MakeFromTopLeft(i * mTileSize.Width, j * mTileSize.Height, mTileSize.Width, mTileSize.Height);
Rectangle src = set->GetTileRect(mpMap[i][j].TileIndex);
g->DrawImage(*set->GetImage(), src, dest, Color::White());
//g->DrawImage(*set->GetImage(), glm::vec2(dest.left(), dest.top()), Color::White());
//g->DrawImage(*set->GetImage(), Rectangle::MakeFromTopLeft(0, 0, 1024, 1024), dest, Color::White());
//g->DrawImage(*set->GetImage(), Rectangle::MakeFromTopLeft(16, 0, 16, 16), Rectangle::MakeFromTopLeft(0, 0, 500, 500), Color::White());
}
}
// Draw grid
for (int i = 0; i < mSizeInTiles.Width; i++)
{
g->DrawLine(glm::vec2(i * mTileSize.Width, 0), glm::vec2(i * mTileSize.Width, map_size_pixels.Height), Color::Black(), 1.0f);
}
g->DrawLine(glm::vec2(map_size_pixels.Width, 0), glm::vec2(map_size_pixels.Width, map_size_pixels.Height), Color::Black(), 1.0f);
for (int j = 0; j < mSizeInTiles.Height; j++)
{
g->DrawLine(glm::vec2(0, j * mTileSize.Height), glm::vec2(map_size_pixels.Width, j * mTileSize.Height), Color::Black(), 1.0f);
}
g->DrawLine(glm::vec2(0, map_size_pixels.Height), glm::vec2(map_size_pixels.Width, map_size_pixels.Height), Color::Black(), 1.0f);
}
}}

@ -9,7 +9,9 @@
#ifndef TILE_MAP_H_ #ifndef TILE_MAP_H_
#define TILE_MAP_H_ #define TILE_MAP_H_
#include "definitions.h"
#include <core/types.h> #include <core/types.h>
#include <utils/opRes.h>
#include <map> #include <map>
namespace lunarium { class IGraphics; } namespace lunarium { class IGraphics; }
@ -18,19 +20,15 @@ namespace lunarium { namespace editor
{ {
class TileSet; class TileSet;
// Allows tiles from multiple tilesets to be used in one map
// A tile ID of -1 will mean "no tile" and result in a transparent spot
// when rendered
struct TileRef
{
int TileSetID;
Vec2i TileIndex;
};
class TileMap class TileMap
{ {
public: public:
TileMap(std::map<int, TileSet*>* tilesets); TileMap(Sizei tile_size);
[[NoDiscard]] OpRes AddTileSet(int id, TileSet*);
void MarkClean();
bool IsDirty() const;
void SetTile(TileRef, Vec2i location); void SetTile(TileRef, Vec2i location);
TileRef GetTile(Vec2i location); TileRef GetTile(Vec2i location);
@ -39,6 +37,7 @@ namespace lunarium { namespace editor
Sizei GetSizeInTiles(); Sizei GetSizeInTiles();
Sizei GetSizeInPixels(); Sizei GetSizeInPixels();
Sizei GetTileSize();
// Call during render to texture phase // Call during render to texture phase
void Render(lunarium::IGraphics* g); void Render(lunarium::IGraphics* g);
@ -46,7 +45,9 @@ namespace lunarium { namespace editor
private: private:
TileRef** mpMap; TileRef** mpMap;
Sizei mSizeInTiles; Sizei mSizeInTiles;
std::map<int, TileSet*>* mpTileSets; Sizei mTileSize;
std::map<int, TileSet*> mTileSets;
bool mIsDirty;
}; };
}} }}

@ -17,7 +17,7 @@
namespace lunarium { namespace editor namespace lunarium { namespace editor
{ {
TileSet::TileSet() TileSet::TileSet()
: EditorAsset(AssetType::EATYPE_TILE_SET), mSetImage(nullptr), mTileSize({ 0, 0}) : EditorAsset(AssetType::EATYPE_TILE_SET), mTileSetID(-1), mSetImage(nullptr), mTileSize({ 0, 0})
{ {
} }
@ -46,6 +46,7 @@ namespace lunarium { namespace editor
return OpRes::Fail("Could not load image file: %s", GetFileLocation().string().c_str()); return OpRes::Fail("Could not load image file: %s", GetFileLocation().string().c_str());
} }
mTileSetID = node.attribute("TileSetID").as_int();
mTileSize.Width = node.attribute("TileSizeWidth").as_int(); mTileSize.Width = node.attribute("TileSizeWidth").as_int();
mTileSize.Height = node.attribute("TileSizeHeight").as_int(); mTileSize.Height = node.attribute("TileSizeHeight").as_int();
mNumTiles.Width = node.attribute("NumTilesCol").as_int(); mNumTiles.Width = node.attribute("NumTilesCol").as_int();
@ -56,6 +57,7 @@ namespace lunarium { namespace editor
OpRes TileSet::SaveToXML(pugi::xml_node& node) OpRes TileSet::SaveToXML(pugi::xml_node& node)
{ {
node.append_attribute("TileSetID").set_value(mTileSetID);
node.append_attribute("TileSizeWidth").set_value(mTileSize.Width); node.append_attribute("TileSizeWidth").set_value(mTileSize.Width);
node.append_attribute("TileSizeHeight").set_value(mTileSize.Height); node.append_attribute("TileSizeHeight").set_value(mTileSize.Height);
node.append_attribute("NumTilesCol").set_value(mNumTiles.Width); node.append_attribute("NumTilesCol").set_value(mNumTiles.Width);
@ -64,6 +66,16 @@ namespace lunarium { namespace editor
return OpRes::OK(); return OpRes::OK();
} }
void TileSet::SetTileSetID(int id)
{
mTileSetID = id;
}
int TileSet::GetTileSetID() const
{
return mTileSetID;
}
void TileSet::SetImage(Image* image) void TileSet::SetImage(Image* image)
{ {
mSetImage = image; mSetImage = image;

@ -27,6 +27,9 @@ namespace lunarium { namespace editor
OpRes LoadFromXML(pugi::xml_node& node); OpRes LoadFromXML(pugi::xml_node& node);
OpRes SaveToXML(pugi::xml_node& node); OpRes SaveToXML(pugi::xml_node& node);
void SetTileSetID(int id);
int GetTileSetID() const;
void SetImage(Image* image); void SetImage(Image* image);
void SetTileSize(Sizei size); void SetTileSize(Sizei size);
@ -40,6 +43,7 @@ namespace lunarium { namespace editor
Image* mSetImage; Image* mSetImage;
Sizei mTileSize; // in pixels, must be a square power of 2 Sizei mTileSize; // in pixels, must be a square power of 2
Sizei mNumTiles; Sizei mNumTiles;
int mTileSetID;
}; };
}} }}

@ -12,7 +12,7 @@
#include <core/iRunMode.h> #include <core/iRunMode.h>
#include <utils/opRes.h> #include <utils/opRes.h>
#include "project/project.h" #include "project.h"
#include "panel_manager.h" #include "panel_manager.h"
#include "panels/about.h" #include "panels/about.h"
#include <gui/file_browser.h> #include <gui/file_browser.h>

@ -1,118 +0,0 @@
/******************************************************************************
* File - tile_map.h
* Author - Joey Pollack
* Date - 2022/02/15 (y/m/d)
* Mod Date - 2022/02/15 (y/m/d)
* Description - Contains a single tile map
******************************************************************************/
#include "tile_map.h"
#include "tile_set.h"
#include <core/core.h>
#include <graphics/graphics.h>
namespace lunarium { namespace editor
{
TileMap::TileMap(std::map<int, TileSet*>* tilesets)
: mpTileSets(tilesets), mpMap(nullptr)
{
}
void TileMap::ClearMap()
{
for(int i = 0; i < mSizeInTiles.Width; i++)
{
for (int j = 0; j < mSizeInTiles.Height; j++)
{
mpMap[i][j] = { -1, {-1, -1} };
}
}
}
Sizei TileMap::GetSizeInTiles()
{
return mSizeInTiles;
}
Sizei TileMap::GetSizeInPixels()
{
if (!mpMap)
return { 0, 0 };
Sizei tile_size = (*mpTileSets)[mpMap[0][0].TileSetID]->GetTileSize();
return { tile_size.Width * mSizeInTiles.Width, tile_size.Height * mSizeInTiles.Height };
}
void TileMap::ResizeMap(Sizei size)
{
TileRef** new_map = new TileRef*[size.Width];
for(int i = 0; i < size.Width; i++)
{
new_map[i] = new TileRef[size.Height];
}
int smaller_width = mSizeInTiles.Width < size.Width ? mSizeInTiles.Width : size.Width;
int smaller_height = mSizeInTiles.Height < size.Height ? mSizeInTiles.Height : size.Height;
for(int i = 0; i < smaller_width; i++)
{
for (int j = 0; j < smaller_height; j++)
{
new_map[i][j] = mpMap[i][j];
}
}
for(int i = 0; i < mSizeInTiles.Width; i++)
{
delete[] mpMap[i];
}
delete[] mpMap;
mSizeInTiles = size;
mpMap = new_map;
}
void TileMap::Render(lunarium::IGraphics* g)
{
if (!mpMap)
return;
// Check the size of the tiles - each tileset should have the same sized tiles for the same map
Sizei tile_size = (*mpTileSets)[mpMap[0][0].TileSetID]->GetTileSize();
Sizei map_size_pixels = { tile_size.Width * mSizeInTiles.Width, tile_size.Height * mSizeInTiles.Height };
// Draw Map
for (int i = 0; i < mSizeInTiles.Width; i++)
{
for (int j = 0; j < mSizeInTiles.Height; j++)
{
// If there is no tile here skip this spot
if (mpMap[i][j].TileIndex.X == -1 || mpMap[i][j].TileIndex.Y == -1)
continue;
TileSet* set = (*mpTileSets)[mpMap[i][j].TileSetID];
Rectangle dest = Rectangle::MakeFromTopLeft(i * tile_size.Width, j * tile_size.Height, tile_size.Width, tile_size.Height);
Rectangle src = set->GetTileRect(mpMap[i][j].TileIndex);
g->DrawImage(*set->GetImage(), src, dest, Color::White());
}
}
// Draw grid
for (int i = 0; i < mSizeInTiles.Width; i++)
{
g->DrawLine(glm::vec2(i * tile_size.Width, 0), glm::vec2(i * tile_size.Width, map_size_pixels.Height), Color::Black(), 1.0f);
}
g->DrawLine(glm::vec2(map_size_pixels.Width, 0), glm::vec2(map_size_pixels.Width, map_size_pixels.Height), Color::Black(), 1.0f);
for (int j = 0; j < mSizeInTiles.Height; j++)
{
g->DrawLine(glm::vec2(0, j * tile_size.Height), glm::vec2(map_size_pixels.Width, j * tile_size.Height), Color::Black(), 1.0f);
}
g->DrawLine(glm::vec2(0, map_size_pixels.Height), glm::vec2(map_size_pixels.Width, map_size_pixels.Height), Color::Black(), 1.0f);
}
}}

@ -10,13 +10,13 @@
#include <core/core.h> #include <core/core.h>
#include <graphics/graphics.h> #include <graphics/graphics.h>
#include <editor/project/contents/content_manager.h>
#include <assets/types/image.h> #include <assets/types/image.h>
#include <editor/editor.h> #include <editor/editor.h>
#include <gui/panel.h> #include <gui/panel.h>
#include <gui/dearimgui/imgui.h> #include <gui/dearimgui/imgui.h>
#include <editor/project/contents/tile_set.h> #include <editor/contents/content_manager.h>
#include <editor/project/contents/tile_map.h> #include <editor/contents/tile_set.h>
#include <editor/contents/tile_map.h>
// Panels // Panels
#include "panels/map_canvas.h" #include "panels/map_canvas.h"
@ -28,7 +28,7 @@
namespace lunarium { namespace editor namespace lunarium { namespace editor
{ {
MapEditor::MapEditor() MapEditor::MapEditor()
: mpEditor(nullptr), mIsOpen(false), mMapLoaded(false), mImportTileSet(false), mTileSetNextID(0) : mpEditor(nullptr), mIsOpen(false), mMapLoaded(false), mImportTileSet(false), mTileSetNextID(0), mpMap(nullptr)
{ {
} }
@ -52,6 +52,15 @@ namespace lunarium { namespace editor
Open(); Open();
std::vector<EditorAsset*> tile_sets;
ContentManager::GetInstance().GetAllAssetsByType(tile_sets, AssetType::EATYPE_TILE_SET);
for (int i = 0; i < tile_sets.size(); i++)
{
TileSet* ts = (TileSet*) tile_sets[i];
mTileSets[ts->GetTileSetID()] = ts;
//((TileSetView*)mPanelManager.GetPanel(gui::PanelType::PT_TILE_SET_VIEW))->SetTileSet((TileSet*)tile_sets[i]);
}
return OpRes::OK(); return OpRes::OK();
} }
@ -133,11 +142,50 @@ namespace lunarium { namespace editor
void MapEditor::NewMap() void MapEditor::NewMap()
{ {
if (mpMap && mpMap->IsDirty())
{
// TODO: Do last chance save
}
delete mpMap;
// HACK: Hardcoding the tile size to 16, 16
mpMap = new TileMap({16, 16});
// HACK: Map size hardcoded for testing
mpMap->ResizeMap({50, 50});
mpMap->ClearMap();
// Add all tilesets that match the Map's tile size
((TileSetView*)mPanelManager.GetPanel(gui::PanelType::PT_TILE_SET_VIEW))->ClearTileSets();
for (auto iter = mTileSets.begin(); iter != mTileSets.end(); iter++)
{
if (iter->second->GetTileSize() == mpMap->GetTileSize())
{
mpMap->AddTileSet(iter->second->GetTileSetID(), iter->second);
((TileSetView*)mPanelManager.GetPanel(gui::PanelType::PT_TILE_SET_VIEW))->AddTileSet(iter->second);
}
}
((MapCanvas*)mPanelManager.GetPanel(gui::PanelType::PT_MAP_CANVAS))->SetTileMap(mpMap);
} }
OpRes MapEditor::LoadMap(std::string map) OpRes MapEditor::LoadMap(std::string map)
{ {
{
// TODO: Do last chance save if needed
// TODO: Clean up currrent map
}
// TODO: Clear out the tileset view
// TODO: Load the new map
// TODO: Add all tilesets that match the Map's tile size
// to the Map and the TileSetView panel
// TODO: Set the map for the MapCanvas panel
return OpRes::Fail("MapEditor::LoadMap not implemented"); return OpRes::Fail("MapEditor::LoadMap not implemented");
} }
@ -165,6 +213,12 @@ namespace lunarium { namespace editor
if (ImGui::BeginMenu("File")) if (ImGui::BeginMenu("File"))
{ {
if (ImGui::MenuItem("New Map"))
{
NewMap();
}
ImGui::Separator();
if (ImGui::MenuItem("Import Tile Set")) if (ImGui::MenuItem("Import Tile Set"))
{ {
mImportTileSet = true; mImportTileSet = true;
@ -218,37 +272,18 @@ namespace lunarium { namespace editor
uint64_t id = 0; uint64_t id = 0;
ContentManager::GetInstance().ImportFile(*path, mpEditor->GetAssetBrowserLocation() / path->filename(), AssetType::EATYPE_TILE_SET, id).LogIfFailed(Editor::LogCat); ContentManager::GetInstance().ImportFile(*path, mpEditor->GetAssetBrowserLocation() / path->filename(), AssetType::EATYPE_TILE_SET, id).LogIfFailed(Editor::LogCat);
// For now just directly load the file and make a tileset out of it
// int w, h, n;
// stbi_set_flip_vertically_on_load(1);
// unsigned char* buffer = stbi_load(path->string().c_str(), &w, &h, &n, 0);
// Image* i = new Image();
// i->SetData(buffer);
// i->SetFormat(ImageFormat::RGBA);
// if (n == 3)
// {
// i->SetFormat(ImageFormat::RGB);
// }
// i->SetWidth(w);
// i->SetHeight(h);
// Core::Graphics().RegisterImage(*i);
// TileSet* ts = new TileSet();
// // ts->SetFileLocation(*path);
// ts->SetImage(i);
TileSet* ts = (TileSet*)ContentManager::GetInstance().GetAsset(id); TileSet* ts = (TileSet*)ContentManager::GetInstance().GetAsset(id);
ts->SetTileSize({16, 16}); // NOTE: Hardcoding the tile size for testing ts->SetTileSize({16, 16}); // NOTE: Hardcoding the tile size for testing
ts->SetTileSetID(mTileSetNextID);
mTileSets[mTileSetNextID] = ts; mTileSets[mTileSetNextID] = ts;
mTileSetNextID++; mTileSetNextID++;
// FOR TESTING // Check if the tile set can be used on the current map
((TileSetView*)mPanelManager.GetPanel(gui::PanelType::PT_TILE_SET_VIEW))->SetTileSet(ts); if (mpMap && mpMap->GetTileSize() == ts->GetTileSize())
{
mpMap->AddTileSet(ts->GetTileSetID(), ts);
((TileSetView*)mPanelManager.GetPanel(gui::PanelType::PT_TILE_SET_VIEW))->AddTileSet(ts);
}
mImportTileSet = false; mImportTileSet = false;
} }
@ -261,4 +296,10 @@ namespace lunarium { namespace editor
} }
} }
void MapEditor::ChangeSelectedTile(TileRef tile)
{
((MapCanvas*)mPanelManager.GetPanel(gui::PanelType::PT_MAP_CANVAS))->SetSelectedTile(tile);
}
}} }}

@ -15,6 +15,7 @@
#include <utils/opRes.h> #include <utils/opRes.h>
#include "../../panel_manager.h" #include "../../panel_manager.h"
#include <gui/file_browser.h> #include <gui/file_browser.h>
#include <editor/contents/definitions.h>
namespace lunarium { namespace lunarium {
class IGraphics; class IGraphics;
@ -25,6 +26,7 @@ namespace lunarium {
namespace editor namespace editor
{ {
class TileMap;
class TileSet; class TileSet;
class Editor; class Editor;
class MapEditor class MapEditor
@ -48,11 +50,13 @@ namespace editor
const std::map<int, TileSet*>* GetTileSets() const; const std::map<int, TileSet*>* GetTileSets() const;
void ChangeSelectedTile(TileRef tile);
private: private:
bool mIsOpen; bool mIsOpen;
bool mMapLoaded; bool mMapLoaded;
bool mIsDirty; TileMap* mpMap;
Editor* mpEditor; Editor* mpEditor;
PanelManager mPanelManager; PanelManager mPanelManager;

@ -9,6 +9,7 @@
#include "map_canvas.h" #include "map_canvas.h"
#include "../map_editor.h" #include "../map_editor.h"
#include <editor/editor.h> #include <editor/editor.h>
#include <editor/contents/tile_map.h>
#include <gui/dearimgui/imgui.h> #include <gui/dearimgui/imgui.h>
#include <core/core.h> #include <core/core.h>
#include <graphics/graphics.h> #include <graphics/graphics.h>
@ -28,6 +29,37 @@ namespace lunarium { namespace editor
void MapCanvas::Update(float delta) void MapCanvas::Update(float delta)
{ {
// Check for input and update map
if (mMap && ImGui::GetIO().MouseDown[ImGuiMouseButton_Left] && mSelectedTile.TileSetID > -1
&& mSelectedTile.TileIndex.X > -1&& mSelectedTile.TileIndex.Y > -1)
{
// Get mouse coords
float x = ImGui::GetMousePos().x;
float y = ImGui::GetMousePos().y;
// Adjust for window pos
x -= mWorkAreaPos.X;
y -= mWorkAreaPos.Y;
// Check that mouse pos is within the window
bool is_in_window = x >= 0.0f && x < mWorkAreaSize.X && y >= 0.0f && y < mWorkAreaSize.Y;
if (is_in_window)
{
// Convert to tile grid index
x /= mMap->GetTileSize().Width;
y /= mMap->GetTileSize().Height;
// Don't update the map if the current tile is already set to the selected tile
if (mMap->GetTile({ (int)x, (int)y }) != mSelectedTile)
{
mMap->SetTile(mSelectedTile, { (int)x, (int)y });
mpCanvasImage = nullptr;
}
}
}
// Check if redraw is needed
if (!mpCanvasImage) if (!mpCanvasImage)
{ {
if (mMap) if (mMap)
@ -75,8 +107,6 @@ namespace lunarium { namespace editor
float x = io.MousePos.x - pos.x; float x = io.MousePos.x - pos.x;
float y = io.MousePos.y - pos.y; float y = io.MousePos.y - pos.y;
std::ostringstream oss; std::ostringstream oss;
oss << "Mouse Position on Panel: "; oss << "Mouse Position on Panel: ";
if (x < 0.0f || y < 0.0f || x > size.x || y > size.y) if (x < 0.0f || y < 0.0f || x > size.x || y > size.y)
@ -92,10 +122,19 @@ namespace lunarium { namespace editor
oss <<"\nFrameHeightWithSpacing: " << ImGui::GetFrameHeightWithSpacing(); oss <<"\nFrameHeightWithSpacing: " << ImGui::GetFrameHeightWithSpacing();
mMouseStatusInfo = oss.str(); mMouseStatusInfo = oss.str();
mWorkAreaPos = { ImGui::GetWindowPos().x, ImGui::GetWindowPos().y };
mWorkAreaSize = { ImGui::GetWindowSize().x, ImGui::GetWindowSize().y };
mScrollOffset = { ImGui::GetScrollX(), ImGui::GetScrollY() };
// Adjust pos and size to account for the title bar
mWorkAreaPos.Y += ImGui::GetFrameHeight();
mWorkAreaSize.Y -= ImGui::GetFrameHeight();
//ImGui::Text(mMouseStatusInfo.c_str()); //ImGui::Text(mMouseStatusInfo.c_str());
if (mpCanvasImage) if (mpCanvasImage)
{ {
ImGui::Image((ImTextureID)mpCanvasImage->GetGLTextureID64(), ImVec2(mpCanvasImage->GetWidth(), mpCanvasImage->GetHeight())); ImGui::Image((ImTextureID)mpCanvasImage->GetGLTextureID64(),
ImVec2(mpCanvasImage->GetWidth(), mpCanvasImage->GetHeight()), ImVec2(0, 1), ImVec2(1, 0));
} }
// TODO: If a tile on the map was changed this frame null out the canvas image so it will be redrawn // TODO: If a tile on the map was changed this frame null out the canvas image so it will be redrawn
@ -107,6 +146,11 @@ namespace lunarium { namespace editor
void MapCanvas::SetTileMap(TileMap* pMap) void MapCanvas::SetTileMap(TileMap* pMap)
{ {
if (mMap && mMap->GetSizeInPixels() != pMap->GetSizeInPixels())
{
mMapSizeChanged = true;
}
mMap = pMap; mMap = pMap;
// Force the image to redraw // Force the image to redraw

@ -10,8 +10,7 @@
#define MAP_CANVAS_H_ #define MAP_CANVAS_H_
#include <gui/panel.h> #include <gui/panel.h>
#include <editor/project/contents/tile_map.h> #include <editor/contents/definitions.h>
#include <core/types.h>
#include <string> #include <string>
namespace lunarium { class Image; class IGraphics; } namespace lunarium { class Image; class IGraphics; }
@ -19,6 +18,7 @@ namespace lunarium { class Image; class IGraphics; }
namespace lunarium { namespace editor namespace lunarium { namespace editor
{ {
class MapEditor; class MapEditor;
class TileMap;
class MapCanvas : public gui::Panel class MapCanvas : public gui::Panel
{ {
@ -38,6 +38,9 @@ namespace lunarium { namespace editor
private: private:
MapEditor* mpMapEditor; MapEditor* mpMapEditor;
Vec2f mWorkAreaPos;
Vec2f mWorkAreaSize;
Vec2f mScrollOffset;
std::string mMouseStatusInfo; std::string mMouseStatusInfo;
int mFrameBuffer; int mFrameBuffer;
Image* mpCanvasImage; Image* mpCanvasImage;

@ -8,7 +8,7 @@
#include "tile_set_view.h" #include "tile_set_view.h"
#include "../map_editor.h" #include "../map_editor.h"
#include <editor/project/contents/tile_set.h> #include <editor/contents/tile_set.h>
#include <assets/types/image.h> #include <assets/types/image.h>
#include <editor/editor.h> #include <editor/editor.h>
#include <core/core.h> #include <core/core.h>
@ -61,6 +61,9 @@ namespace lunarium { namespace editor
//Logger::Log(Editor::LogCat, LogLevel::INFO_VERBOSE, "Updating Tile Selection: tile (%d, %d)", mSelectedTile.X, mSelectedTile.Y); //Logger::Log(Editor::LogCat, LogLevel::INFO_VERBOSE, "Updating Tile Selection: tile (%d, %d)", mSelectedTile.X, mSelectedTile.Y);
// Notify the editor that the selected tile has changed
mpEditor->ChangeSelectedTile({ mpSelectedTileSet->GetTileSetID(), mSelectedTile });
Invalidate(); Invalidate();
} }
} }
@ -134,8 +137,7 @@ namespace lunarium { namespace editor
} }
if (ImGui::BeginCombo("Tile Sets", name.c_str())) if (ImGui::BeginCombo("Tile Sets", name.c_str()))
{ {
auto tile_sets = mpEditor->GetTileSets(); for (auto iter = mTileSets.begin(); iter != mTileSets.end(); iter++)
for (auto iter = tile_sets->begin(); iter != tile_sets->end(); iter++)
{ {
bool selected = false; bool selected = false;
if (ImGui::Selectable(iter->second->GetFileLocation().filename().string().c_str(), &selected)) if (ImGui::Selectable(iter->second->GetFileLocation().filename().string().c_str(), &selected))
@ -174,12 +176,25 @@ namespace lunarium { namespace editor
return mIsOpen; return mIsOpen;
} }
void TileSetView::SetTileSet(TileSet* set) void TileSetView::ClearTileSets()
{ {
mpSelectedTileSet = set; mTileSets.clear();
mpSelectedTileSet = nullptr;
mSelectedTile = {-1, -1};
Invalidate(true); Invalidate(true);
} }
void TileSetView::AddTileSet(TileSet* set)
{
mTileSets[set->GetTileSetID()] = set;
if (!mpSelectedTileSet)
{
mpSelectedTileSet = set;
Invalidate(true);
}
}
TileSet* TileSetView::GetTileSet() TileSet* TileSetView::GetTileSet()
{ {
return mpSelectedTileSet; return mpSelectedTileSet;

@ -12,6 +12,7 @@
#include <gui/panel.h> #include <gui/panel.h>
#include <core/types.h> #include <core/types.h>
#include <utils/highResTimer.h> #include <utils/highResTimer.h>
#include <map>
namespace lunarium { class Image; } namespace lunarium { class Image; }
@ -27,7 +28,8 @@ namespace lunarium { namespace editor
void Update(float delta); void Update(float delta);
bool DoFrame(); bool DoFrame();
void SetTileSet(TileSet* set); void ClearTileSets();
void AddTileSet(TileSet* set);
TileSet* GetTileSet(); TileSet* GetTileSet();
Vec2i GetSelectedTile(); Vec2i GetSelectedTile();
@ -36,6 +38,7 @@ namespace lunarium { namespace editor
private: private:
MapEditor* mpEditor; MapEditor* mpEditor;
std::map<int, TileSet*> mTileSets;
TileSet* mpSelectedTileSet; TileSet* mpSelectedTileSet;
int mFrameBuffer; int mFrameBuffer;
bool mInvalidate; bool mInvalidate;

@ -61,6 +61,9 @@ namespace lunarium
mpTestImageLoad->SetWidth(w); mpTestImageLoad->SetWidth(w);
mpTestImageLoad->SetHeight(h); mpTestImageLoad->SetHeight(h);
mSrcWidth = w;
mSrcHeight = h;
Core::Graphics().RegisterImage(*mpTestImageLoad); Core::Graphics().RegisterImage(*mpTestImageLoad);
angle = 0.0f; angle = 0.0f;
@ -88,6 +91,18 @@ namespace lunarium
mTextBoxWidth += 10; mTextBoxWidth += 10;
} }
if (Core::Input().IsKeyDown(KeyCode::R))
{
mSrcWidth -= 10.0f;
mSrcHeight -= 10.0f;
}
if (Core::Input().IsKeyDown(KeyCode::F))
{
mSrcWidth += 10.0f;
mSrcHeight += 10.0f;
}
mTextBoxWidth = Math::ClampI(mTextBoxWidth, 20, 500); mTextBoxWidth = Math::ClampI(mTextBoxWidth, 20, 500);
// Image Size adjustment // Image Size adjustment
@ -159,8 +174,6 @@ namespace lunarium
mpRenderedImage = Core::GetInstance().EndRenderToTexture(); mpRenderedImage = Core::GetInstance().EndRenderToTexture();
box_angle += 0.01f; box_angle += 0.01f;
} }
@ -176,7 +189,14 @@ namespace lunarium
g->DrawString((*mGrid[{-2, 0,}])->msg.c_str(), Rectangle::MakeFromTopLeft(200.0f, 500.0f, 500.0f, 200.0f), Color(0.5f, 0.0f, 0.75f, 1.0f)); g->DrawString((*mGrid[{-2, 0,}])->msg.c_str(), Rectangle::MakeFromTopLeft(200.0f, 500.0f, 500.0f, 200.0f), Color(0.5f, 0.0f, 0.75f, 1.0f));
//g->DrawImage(*mpTestImageLoad, glm::vec2(0.0f, 0.0f), Color::White()); //g->DrawImage(*mpTestImageLoad, glm::vec2(0.0f, 0.0f), Color::White());
// g->DrawImage(*mpTestImageLoad, Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mpTestImageLoad->GetWidth(), (float)mpTestImageLoad->GetHeight()), //Rectangle src = Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mpTestImageLoad->GetWidth(), (float)mpTestImageLoad->GetHeight());
// Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mpTestImageLoad->GetWidth(), (float)mpTestImageLoad->GetHeight()), Color::White()); //Rectangle src = Rectangle::MakeFromTopLeft(0.0f, 0.0f, mSrcWidth, mSrcHeight);
Rectangle src = Rectangle::MakeFromTopLeft(0.0f, 0.0f, 16, 16);
Rectangle dest = Rectangle::MakeFromTopLeft(100.0f, 100.0f, 512.0f, 512.0f);
g->DrawImage(*mpTestImageLoad, src,
dest, Color(1.0f, 1.0f, 1.0f, 0.9f));
// g->DrawImage(*mpTestImageLoad, src,
// dest, Color(1.0f, 1.0f, 1.0f, 0.8f));
} }
} }

@ -37,6 +37,9 @@ namespace lunarium
float angle; float angle;
float box_angle; float box_angle;
float mSrcWidth;
float mSrcHeight;
struct GridTestObj struct GridTestObj
{ {
int X; int X;

Loading…
Cancel
Save