PNG loading and major refactoring.
PNG loading is not working properly yet.
This commit is contained in:
parent
d0893cba3a
commit
28bd73a1f7
17 changed files with 254 additions and 43 deletions
BIN
resources/graphics/player.png
Normal file
BIN
resources/graphics/player.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
|
@ -35,4 +35,11 @@ namespace cloonel {
|
||||||
void Character::Destroy() noexcept {
|
void Character::Destroy() noexcept {
|
||||||
m_texture->Destroy();
|
m_texture->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
void Character::Draw() const {
|
||||||
|
const int2 pos(m_pos + 0.5f);
|
||||||
|
m_texture->Render(pos);
|
||||||
|
}
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define id0CEACFB045ED4C9F8688265AA41E30B0
|
#define id0CEACFB045ED4C9F8688265AA41E30B0
|
||||||
|
|
||||||
#include "placeable.hpp"
|
#include "placeable.hpp"
|
||||||
|
#include "drawable.hpp"
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -10,14 +11,15 @@ namespace cloonel {
|
||||||
class SDLMain;
|
class SDLMain;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
class Character : public Placeable {
|
class Character : public Placeable, public Drawable {
|
||||||
public:
|
public:
|
||||||
Character ( const std::string& parPath, SDLMain* parMain );
|
Character ( const std::string& parPath, SDLMain* parMain );
|
||||||
Character ( const std::string&& parPath, SDLMain* parMain );
|
Character ( const std::string&& parPath, SDLMain* parMain );
|
||||||
~Character ( void ) noexcept;
|
virtual ~Character ( void ) noexcept;
|
||||||
|
|
||||||
void Prepare ( void );
|
void Prepare ( void );
|
||||||
void Destroy ( void ) noexcept;
|
void Destroy ( void ) noexcept;
|
||||||
|
virtual void Draw ( void ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::unique_ptr<Texture> m_texture;
|
const std::unique_ptr<Texture> m_texture;
|
||||||
|
|
14
src/drawable.hpp
Normal file
14
src/drawable.hpp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef idC5A880D06A03407DB4E9FC21593A47FB
|
||||||
|
#define idC5A880D06A03407DB4E9FC21593A47FB
|
||||||
|
|
||||||
|
namespace cloonel {
|
||||||
|
class Drawable {
|
||||||
|
public:
|
||||||
|
Drawable ( void ) = default;
|
||||||
|
virtual ~Drawable ( void ) noexcept = default;
|
||||||
|
|
||||||
|
virtual void Draw ( void ) const = 0;
|
||||||
|
};
|
||||||
|
} //namespace cloonel
|
||||||
|
|
||||||
|
#endif
|
|
@ -19,6 +19,8 @@ namespace cloonel {
|
||||||
virtual void Prepare ( void ) = 0;
|
virtual void Prepare ( void ) = 0;
|
||||||
virtual void Destroy ( void ) noexcept = 0;
|
virtual void Destroy ( void ) noexcept = 0;
|
||||||
|
|
||||||
|
SDLMain* SDLObject ( void ) { return m_sdlmain; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void OnRender ( void ) = 0;
|
virtual void OnRender ( void ) = 0;
|
||||||
virtual void OnUpdate ( float parDelta ) = 0;
|
virtual void OnUpdate ( float parDelta ) = 0;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "gameplayscene.hpp"
|
#include "gameplayscene.hpp"
|
||||||
#include "mover.hpp"
|
#include "mover.hpp"
|
||||||
|
#include "drawable.hpp"
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
|
@ -20,5 +21,8 @@ namespace cloonel {
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
void GameplayScene::OnRender() {
|
void GameplayScene::OnRender() {
|
||||||
|
for (auto itDrawable : m_drawables) {
|
||||||
|
itDrawable->Draw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
|
@ -2,23 +2,27 @@
|
||||||
#define id1DF84BC48C0547D69F79499E3A25BFC5
|
#define id1DF84BC48C0547D69F79499E3A25BFC5
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
#include "gamebase.hpp"
|
#include "gamebase.hpp"
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
class Mover;
|
class Mover;
|
||||||
|
class Drawable;
|
||||||
|
|
||||||
class GameplayScene : public GameBase {
|
class GameplayScene : public GameBase {
|
||||||
public:
|
public:
|
||||||
explicit GameplayScene ( SDLMain* parSdlMain );
|
explicit GameplayScene ( SDLMain* parSdlMain );
|
||||||
virtual ~GameplayScene ( void ) noexcept = default;
|
virtual ~GameplayScene ( void ) noexcept = default;
|
||||||
|
|
||||||
void AddMover ( Mover* parMover ) { m_movers.push_back(parMover); }
|
void AddMover ( Mover* parMover ) { assert(parMover); m_movers.push_back(parMover); }
|
||||||
|
void AddDrawable ( const Drawable* parDrawable ) { assert(parDrawable); m_drawables.push_back(parDrawable); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void OnRender ( void );
|
virtual void OnRender ( void );
|
||||||
virtual void OnUpdate ( float parDelta );
|
virtual void OnUpdate ( float parDelta );
|
||||||
|
|
||||||
std::vector<Mover*> m_movers;
|
std::vector<Mover*> m_movers;
|
||||||
|
std::vector<const Drawable*> m_drawables;
|
||||||
};
|
};
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
#include "gameplaysceneclassic.hpp"
|
#include "gameplaysceneclassic.hpp"
|
||||||
|
#include "character.hpp"
|
||||||
|
#include "moversine.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
|
struct GameplaySceneClassic::LocalData {
|
||||||
|
};
|
||||||
|
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
GameplaySceneClassic::GameplaySceneClassic (SDLMain* parSdlMain) :
|
GameplaySceneClassic::GameplaySceneClassic (SDLMain* parSdlMain) :
|
||||||
GameplayScene(parSdlMain)
|
GameplayScene(parSdlMain),
|
||||||
|
m_local(new LocalData)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,10 +24,23 @@ namespace cloonel {
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
void GameplaySceneClassic::Prepare() {
|
void GameplaySceneClassic::Prepare() {
|
||||||
|
std::unique_ptr<MoverSine> moverSine(new MoverSine());
|
||||||
|
std::unique_ptr<Character> player(new Character("resources/graphics/player.png", SDLObject()));
|
||||||
|
|
||||||
|
player->Prepare();
|
||||||
|
player->SwapMover(moverSine.get());
|
||||||
|
|
||||||
|
std::swap(moverSine, m_moverSine);
|
||||||
|
std::swap(player, m_player);
|
||||||
|
|
||||||
|
AddMover(m_moverSine.get());
|
||||||
|
AddDrawable(m_player.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
void GameplaySceneClassic::Destroy() noexcept {
|
void GameplaySceneClassic::Destroy() noexcept {
|
||||||
|
m_moverSine = std::move(std::unique_ptr<MoverSine>(nullptr));
|
||||||
|
m_player = std::move(std::unique_ptr<Character>(nullptr));
|
||||||
}
|
}
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
#define idF6FF1F57C36842DC9B20E2F55C507C2E
|
#define idF6FF1F57C36842DC9B20E2F55C507C2E
|
||||||
|
|
||||||
#include "gameplayscene.hpp"
|
#include "gameplayscene.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
class SDLMain;
|
class SDLMain;
|
||||||
|
class Character;
|
||||||
|
class MoverSine;
|
||||||
|
|
||||||
class GameplaySceneClassic : public GameplayScene {
|
class GameplaySceneClassic : public GameplayScene {
|
||||||
public:
|
public:
|
||||||
|
@ -15,6 +18,11 @@ namespace cloonel {
|
||||||
virtual void Destroy ( void ) noexcept;
|
virtual void Destroy ( void ) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct LocalData;
|
||||||
|
|
||||||
|
const std::unique_ptr <LocalData> m_local;
|
||||||
|
std::unique_ptr<Character> m_player;
|
||||||
|
std::unique_ptr<MoverSine> m_moverSine;
|
||||||
};
|
};
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
||||||
|
|
12
src/main.cpp
12
src/main.cpp
|
@ -10,27 +10,25 @@ namespace {
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
void RunMainLoop (cloonel::GameplaySceneClassic& parGame) {
|
void RunMainLoop (cloonel::GameplaySceneClassic& parGame) {
|
||||||
|
parGame.Prepare();
|
||||||
do {
|
do {
|
||||||
parGame.Exec();
|
parGame.Exec();
|
||||||
} while (not parGame.WantsToQuit());
|
} while (not parGame.WantsToQuit());
|
||||||
|
parGame.Destroy();
|
||||||
}
|
}
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
///following http://twinklebeardev.blogspot.co.uk/2012/07/lesson-1-hello-world.html
|
///following http://twinklebeardev.blogspot.co.uk/2012/07/lesson-1-hello-world.html
|
||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
int main (int, char* []) {
|
int main (int, char* parArgv[]) {
|
||||||
std::cout << GameName << " v" << GameVersionMajor << "." << GameVersionMinor << std::endl;
|
std::cout << GameName << " v" << GameVersionMajor << "." << GameVersionMinor << std::endl;
|
||||||
|
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
cloonel::SDLMain sdlmain(GameName, DEF_WIN_WIDTH, DEF_WIN_HEIGHT);
|
cloonel::SDLMain sdlmain(GameName, DEF_WIN_WIDTH, DEF_WIN_HEIGHT);
|
||||||
try {
|
try {
|
||||||
#if defined(NDEBUG)
|
cloonel::PhysicsFSWrapper physfs(parArgv[0]);
|
||||||
cloonel::PhysicsFSWrapper physfs(parArgc[0]);
|
physfs.Append(GAME_BASE_PATH "/resources/", "resources");
|
||||||
#else
|
|
||||||
cloonel::PhysicsFSWrapper physfs(GAME_BASE_PATH);
|
|
||||||
#endif
|
|
||||||
physfs.Append("resources", "resources");
|
|
||||||
|
|
||||||
sdlmain.Init();
|
sdlmain.Init();
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,38 @@
|
||||||
#include "mover.hpp"
|
#include "mover.hpp"
|
||||||
#include "placeable.hpp"
|
#include "placeable.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
void Mover::ApplyOffsetToPlaceable (std::size_t parIndex, const float2& parOffset) {
|
void Mover::ApplyOffsetToPlaceables (const float2& parOffset) {
|
||||||
assert(m_placeables[parIndex]);
|
for (Placeable* currPlaceable : m_placeables) {
|
||||||
m_placeables[parIndex]->AddOffset(parOffset);
|
if (currPlaceable) {
|
||||||
|
currPlaceable->AddOffset(parOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
int Mover::RegisterPlaceable (Placeable* parPlaceable) {
|
||||||
|
assert(parPlaceable);
|
||||||
|
m_placeables.push_back(parPlaceable);
|
||||||
|
const std::size_t retVal = m_placeables.size();
|
||||||
|
return static_cast<int>(retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
void Mover::UnregisterPlaceable (int parID) {
|
||||||
|
assert(static_cast<std::size_t>(parID) <= m_placeables.size());
|
||||||
|
assert(m_placeables[parID - 1]);
|
||||||
|
|
||||||
|
m_placeables[parID - 1] = nullptr;
|
||||||
|
auto lastNull = std::find_if(m_placeables.rbegin(), m_placeables.rend(), [](const Placeable* parPlaceable) { return nullptr != parPlaceable; });
|
||||||
|
if (m_placeables.rend() != lastNull) {
|
||||||
|
m_placeables.resize(m_placeables.size() - (lastNull - m_placeables.rbegin()) + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
|
@ -13,12 +13,13 @@ namespace cloonel {
|
||||||
virtual ~Mover ( void ) noexcept = default;
|
virtual ~Mover ( void ) noexcept = default;
|
||||||
|
|
||||||
virtual void ApplyMotion ( float parDelta ) = 0;
|
virtual void ApplyMotion ( float parDelta ) = 0;
|
||||||
void AddPlaceable ( Placeable* parPlaceable ) { m_placeables.push_back(parPlaceable); }
|
int RegisterPlaceable ( Placeable* parPlaceable );
|
||||||
|
void UnregisterPlaceable ( int parID );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Update ( float parDelta ) = 0;
|
virtual void Update ( float parDelta ) = 0;
|
||||||
std::size_t PlaceableCount ( void ) const { return m_placeables.size(); }
|
std::size_t PlaceableCount ( void ) const { return m_placeables.size(); }
|
||||||
void ApplyOffsetToPlaceable ( std::size_t parIndex, const float2& parOffset );
|
void ApplyOffsetToPlaceables ( const float2& parOffset );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Placeable*> m_placeables;
|
std::vector<Placeable*> m_placeables;
|
||||||
|
|
|
@ -6,9 +6,6 @@ namespace cloonel {
|
||||||
void MoverOneShot::ApplyMotion (float parDelta) {
|
void MoverOneShot::ApplyMotion (float parDelta) {
|
||||||
Update(parDelta);
|
Update(parDelta);
|
||||||
const float2 offs(GetOffset());
|
const float2 offs(GetOffset());
|
||||||
const std::size_t placeableCount = PlaceableCount();
|
ApplyOffsetToPlaceables(offs);
|
||||||
for (std::size_t z = 0; z < placeableCount; ++z) {
|
|
||||||
ApplyOffsetToPlaceable(z, offs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
|
@ -1,10 +1,29 @@
|
||||||
#include "placeable.hpp"
|
#include "placeable.hpp"
|
||||||
|
#include "mover.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
Placeable::Placeable (float parX, float parY) :
|
Placeable::Placeable (float parX, float parY) :
|
||||||
m_pos(parX, parY)
|
m_pos(parX, parY),
|
||||||
|
m_mover(nullptr),
|
||||||
|
m_idForMover(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
void Placeable::SwapMover (Mover* parMover) {
|
||||||
|
if (m_mover) {
|
||||||
|
assert(0 != m_idForMover);
|
||||||
|
m_mover->UnregisterPlaceable(m_idForMover);
|
||||||
|
m_idForMover = 0;
|
||||||
|
m_mover = nullptr;
|
||||||
|
}
|
||||||
|
if (parMover) {
|
||||||
|
m_idForMover = parMover->RegisterPlaceable(this);
|
||||||
|
m_mover = parMover;
|
||||||
|
}
|
||||||
|
}
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
|
@ -4,16 +4,24 @@
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
|
class Mover;
|
||||||
|
|
||||||
class Placeable {
|
class Placeable {
|
||||||
public:
|
public:
|
||||||
const float2& GetPos ( void ) const noexcept { return m_pos; }
|
const float2& GetPos ( void ) const noexcept { return m_pos; }
|
||||||
void AddOffset ( const float2& parOffset ) noexcept { m_pos += parOffset; }
|
void AddOffset ( const float2& parOffset ) noexcept { m_pos += parOffset; }
|
||||||
|
|
||||||
|
void SwapMover ( Mover* parMover );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Placeable ( float parX, float parY );
|
Placeable ( float parX, float parY );
|
||||||
~Placeable ( void ) noexcept = default;
|
~Placeable ( void ) noexcept = default;
|
||||||
|
|
||||||
float2 m_pos;
|
float2 m_pos;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Mover* m_mover;
|
||||||
|
int m_idForMover;
|
||||||
};
|
};
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
||||||
|
|
135
src/texture.cpp
135
src/texture.cpp
|
@ -8,12 +8,31 @@
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
|
|
||||||
|
#define lengthof(a) (static_cast<int32_t>(sizeof(a)) / static_cast<int32_t>(sizeof(a[0])))
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
namespace {
|
namespace {
|
||||||
enum GraphicFormat {
|
enum GraphicFormat {
|
||||||
GraphicFormat_Unknown,
|
GraphicFormat_Unknown,
|
||||||
GraphicFormat_Png
|
GraphicFormat_Png
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ColorChannelMask {
|
||||||
|
#if SDL_BYTE_ORDER == SDL_BIGENDIAN
|
||||||
|
ColorChannelMask_Red = 0xff000000,
|
||||||
|
ColorChannelMask_Green = 0xff0000,
|
||||||
|
ColorChannelMask_Blue = 0xff00,
|
||||||
|
ColorChannelMask_Alpha = 0xff
|
||||||
|
#elif SDL_BYTE_ORDER == SDL_LITTLEENDIAN
|
||||||
|
ColorChannelMask_Red = 0xff,
|
||||||
|
ColorChannelMask_Green = 0xff00,
|
||||||
|
ColorChannelMask_Blue = 0xff0000,
|
||||||
|
ColorChannelMask_Alpha = 0xff000000
|
||||||
|
#else
|
||||||
|
# error "Unknonwn endianness"
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct GraphicFormatItem {
|
struct GraphicFormatItem {
|
||||||
const char* extension;
|
const char* extension;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
@ -26,8 +45,34 @@ namespace cloonel {
|
||||||
|
|
||||||
GraphicFormat GuessGraphicFormatFromName (const std::string& parPath) __attribute__((pure));
|
GraphicFormat GuessGraphicFormatFromName (const std::string& parPath) __attribute__((pure));
|
||||||
|
|
||||||
///--------------------------------------------------------------------
|
///----------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------
|
///----------------------------------------------------------------------
|
||||||
|
SDL_Surface* SurfaceFromPngRGBA (ushort2 parSize, int parBpp, const png_structp& parPngPtr, const png_infop& parInfoPtr) {
|
||||||
|
const png_size_t stride = png_get_rowbytes(parPngPtr, parInfoPtr);
|
||||||
|
assert(stride > 0);
|
||||||
|
|
||||||
|
std::unique_ptr<uint8_t[]> image(new uint8_t[stride * parSize.y()]);
|
||||||
|
uint8_t* const imagePtr = image.get();
|
||||||
|
for (uint16_t y = 0; y < parSize.y(); ++y) {
|
||||||
|
png_read_row(parPngPtr, imagePtr + stride * y, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* const retSurf = SDL_CreateRGBSurfaceFrom(
|
||||||
|
imagePtr,
|
||||||
|
parSize.x(),
|
||||||
|
parSize.y(),
|
||||||
|
parBpp,
|
||||||
|
static_cast<int>(stride),
|
||||||
|
ColorChannelMask_Red,
|
||||||
|
ColorChannelMask_Green,
|
||||||
|
ColorChannelMask_Blue,
|
||||||
|
ColorChannelMask_Alpha
|
||||||
|
);
|
||||||
|
return retSurf;
|
||||||
|
}
|
||||||
|
|
||||||
|
///----------------------------------------------------------------------
|
||||||
|
///----------------------------------------------------------------------
|
||||||
GraphicFormat GuessGraphicFormatFromName (const std::string& parPath) {
|
GraphicFormat GuessGraphicFormatFromName (const std::string& parPath) {
|
||||||
const size_t dotPos = parPath.find_last_of('.');
|
const size_t dotPos = parPath.find_last_of('.');
|
||||||
if (parPath.npos == dotPos) {
|
if (parPath.npos == dotPos) {
|
||||||
|
@ -44,27 +89,82 @@ namespace cloonel {
|
||||||
return GraphicFormat_Unknown;
|
return GraphicFormat_Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
///--------------------------------------------------------------------
|
///----------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------
|
///----------------------------------------------------------------------
|
||||||
|
void ReadDataFromInputStream (png_structp parPngPtr, png_bytep parOutBytes, png_size_t parByteCountToRead) {
|
||||||
|
if (not png_get_io_ptr(parPngPtr))
|
||||||
|
return;
|
||||||
|
PhysicsFSFile& rawfile = *static_cast<PhysicsFSFile*>(png_get_io_ptr(parPngPtr));
|
||||||
|
|
||||||
|
const int64_t read = rawfile.Read(static_cast<void*>(parOutBytes), static_cast<uint32_t>(parByteCountToRead), 1);
|
||||||
|
if (read != static_cast<int64_t>(parByteCountToRead))
|
||||||
|
return;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
///----------------------------------------------------------------------
|
||||||
|
///http://blog.hammerian.net/2009/reading-png-images-from-memory/
|
||||||
|
///----------------------------------------------------------------------
|
||||||
SDL_Surface* LoadNewPngSurface (const std::string& parPath) {
|
SDL_Surface* LoadNewPngSurface (const std::string& parPath) {
|
||||||
PhysicsFSFile rawfile(parPath.c_str(), PhysicsFSFile::OpenMode_Read, "graphics");
|
PhysicsFSFile rawfile(parPath.c_str(), PhysicsFSFile::OpenMode_Read, "graphics");
|
||||||
unsigned char header[8];
|
unsigned char header[8];
|
||||||
assert(rawfile.IsOpen());
|
assert(rawfile.IsOpen());
|
||||||
|
|
||||||
rawfile.Read(header, 8, 1);
|
//Read the signature from the input stream
|
||||||
if (png_sig_cmp(header, 0, 8))
|
rawfile.Read(header, lengthof(header), 1);
|
||||||
|
if (png_sig_cmp(header, 0, lengthof(header)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
//Get the file info struct
|
||||||
png_structp pngptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
png_structp pngptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
if (not pngptr)
|
if (not pngptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
//Get the data info struct
|
||||||
|
png_infop infoptr = png_create_info_struct(pngptr);
|
||||||
|
if (not infoptr) {
|
||||||
|
png_destroy_read_struct(&pngptr, nullptr, nullptr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Set the function that will be called to read data from the stream
|
||||||
|
png_set_read_fn(pngptr, &rawfile, ReadDataFromInputStream);
|
||||||
|
//Tell the lib we already verified the signature
|
||||||
|
png_set_sig_bytes(pngptr, lengthof(header));
|
||||||
|
|
||||||
|
//Read the header
|
||||||
|
png_uint_32 width, height;
|
||||||
|
int bitDepth, colorType;
|
||||||
|
png_read_info(pngptr, infoptr);
|
||||||
|
const png_uint_32 headerGetInfoRetVal = png_get_IHDR(pngptr, infoptr, &width, &height, &bitDepth, &colorType, nullptr, nullptr, nullptr);
|
||||||
|
if (static_cast<png_uint_32>(-1) == headerGetInfoRetVal) {
|
||||||
|
png_destroy_read_struct(&pngptr, &infoptr, nullptr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* retSurf;
|
||||||
|
switch (colorType) {
|
||||||
|
case PNG_COLOR_TYPE_RGB:
|
||||||
|
retSurf = nullptr; //SurfaceFromPngRGB();
|
||||||
|
assert(false); //not implemented
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||||
|
retSurf = SurfaceFromPngRGBA(ushort2(static_cast<uint8_t>(width), static_cast<uint8_t>(height)), bitDepth * 4, pngptr, infoptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
png_destroy_read_struct(&pngptr, &infoptr, nullptr);
|
||||||
|
retSurf = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retSurf;
|
||||||
|
}
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
Texture::Texture (const std::string& parPath, SDLMain* parMain, bool parLoadNow) :
|
Texture::Texture (const std::string& parPath, SDLMain* parMain, bool parLoadNow) :
|
||||||
m_path(parPath),
|
m_path(parPath),
|
||||||
m_texture(nullptr),
|
m_texture(nullptr),
|
||||||
|
@ -74,14 +174,14 @@ namespace cloonel {
|
||||||
Reload();
|
Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
Texture::~Texture() noexcept {
|
Texture::~Texture() noexcept {
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
void Texture::Destroy() noexcept {
|
void Texture::Destroy() noexcept {
|
||||||
if (m_texture) {
|
if (m_texture) {
|
||||||
SDL_DestroyTexture(m_texture);
|
SDL_DestroyTexture(m_texture);
|
||||||
|
@ -89,8 +189,8 @@ namespace cloonel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
void Texture::Reload() {
|
void Texture::Reload() {
|
||||||
const GraphicFormat fmt = GuessGraphicFormatFromName(m_path);
|
const GraphicFormat fmt = GuessGraphicFormatFromName(m_path);
|
||||||
Destroy();
|
Destroy();
|
||||||
|
@ -99,6 +199,7 @@ namespace cloonel {
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
case GraphicFormat_Png:
|
case GraphicFormat_Png:
|
||||||
surf = LoadNewPngSurface(m_path.c_str());
|
surf = LoadNewPngSurface(m_path.c_str());
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(std::string("Unsupported file format for \"") + m_path + "\"");
|
throw std::runtime_error(std::string("Unsupported file format for \"") + m_path + "\"");
|
||||||
|
@ -116,9 +217,9 @@ namespace cloonel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
void Texture::Render (const int2& parPos) {
|
void Texture::Render (int2 parPos) const {
|
||||||
assert(IsLoaded());
|
assert(IsLoaded());
|
||||||
const SDL_Rect dest = { parPos.x(), parPos.y(), m_size.x(), m_size.y() };
|
const SDL_Rect dest = { parPos.x(), parPos.y(), m_size.x(), m_size.y() };
|
||||||
SDL_RenderCopy(m_sdlmain->GetRenderer(), m_texture, nullptr, &dest);
|
SDL_RenderCopy(m_sdlmain->GetRenderer(), m_texture, nullptr, &dest);
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace cloonel {
|
||||||
void Reload ( void );
|
void Reload ( void );
|
||||||
void Destroy ( void ) noexcept;
|
void Destroy ( void ) noexcept;
|
||||||
bool IsLoaded ( void ) const { return nullptr != m_texture; }
|
bool IsLoaded ( void ) const { return nullptr != m_texture; }
|
||||||
void Render ( const int2& parPos );
|
void Render ( int2 parPos ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string m_path;
|
const std::string m_path;
|
||||||
|
|
Loading…
Reference in a new issue