Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load tilesets #94

Merged
merged 13 commits into from
Jul 1, 2023
92 changes: 91 additions & 1 deletion OP2-Landlord/Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,39 @@

#include <SDL2/SDL_image.h>

#include <functional>
#include <iostream>
#include <sstream>


namespace
{

struct SurfaceDeleter
{
void operator()(SDL_Surface* srf)
{
SDL_FreeSurface(srf);
}
};

using SdlSurface = std::unique_ptr <SDL_Surface, SurfaceDeleter> ;

SdlSurface createSurfaceFromBuffer(const void* buffer, const size_t buffersize)
{
auto rwops = SDL_RWFromConstMem(buffer, static_cast<int>(buffersize));
SDL_Surface* surface = IMG_LoadBMP_RW(rwops);
SDL_RWclose(rwops);

if (!surface)
{
const std::string msg{ "createSurfaceFromBuffer(): Unable to load from memory buffer: " + std::string(SDL_GetError()) };
throw std::runtime_error(msg);
}

return SdlSurface{ surface };
}
};


Graphics::Graphics(ImVec2 windowSize) :
Expand Down Expand Up @@ -41,7 +73,7 @@ void Graphics::present()
}


Graphics::Texture Graphics::loadTexture(const std::string& filename)
Graphics::Texture Graphics::loadTexture(const std::string& filename) const
{
SDL_Surface* temp = IMG_Load(filename.c_str());
if (!temp)
Expand All @@ -66,6 +98,64 @@ Graphics::Texture Graphics::loadTexture(const std::string& filename)
}


Graphics::Texture Graphics::loadTexture(const void* buffer, const size_t buffersize) const
{
auto out = SDL_CreateTextureFromSurface(mRenderer, createSurfaceFromBuffer(buffer, buffersize).get());

if (!out)
{
const std::string msg{ std::string("loadTexture(): Unable to load from memory buffer: ") + SDL_GetError() };
throw std::runtime_error(msg);
}

int width = 0, height = 0;
SDL_QueryTexture(out, nullptr, nullptr, &width, &height);

return Texture{ out, SDL_Rect{ 0, 0, width, height }, { static_cast<float>(width), static_cast<float>(height) } };
}


Graphics::Texture Graphics::loadTexturePacked(const void* buffer, const size_t buffersize) const
{
SdlSurface src{ SDL_ConvertSurfaceFormat(createSurfaceFromBuffer(buffer, buffersize).get(), SDL_PIXELFORMAT_RGB888, 0) };

SdlSurface destinationSurface(SDL_CreateRGBSurface(
src.get()->flags,
1024, 1024,
src->format->BitsPerPixel,
src->format->Rmask,
src->format->Gmask,
src->format->Bmask,
src->format->Amask));

if (!destinationSurface.get())
{
throw std::runtime_error("loadTexturePacked(): Unable to create new surface: " + std::string(SDL_GetError()));
}

SDL_Rect sourceRect{ 0, 0, 32, 32 };
SDL_Rect destRect{ 0, 0, 32, 32 };
for (size_t i = 0; i < src->h / 32; ++i)
{
destRect = { (static_cast<int>(i) % 32) * 32, (static_cast<int>(i) / 32) * 32, 32, 32 };
SDL_BlitSurface(src.get(), &sourceRect, destinationSurface.get(), &destRect);
sourceRect.y += 32;
}

auto out = SDL_CreateTextureFromSurface(mRenderer, destinationSurface.get());
if (!out)
{
const std::string msg{ std::string("loadTexturePacked(): Unable to load from memory buffer: ") + SDL_GetError() };
throw std::runtime_error(msg);
}

int width = 0, height = 0;
SDL_QueryTexture(out, nullptr, nullptr, &width, &height);

return Texture{ out, SDL_Rect{ 0, 0, width, height }, { static_cast<float>(width), static_cast<float>(height) } };
}


void Graphics::init()
{
if (SDL_Init(SDL_INIT_VIDEO))
Expand Down
4 changes: 3 additions & 1 deletion OP2-Landlord/Graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ class Graphics
void clear();
void present();

Texture loadTexture(const std::string& filename);
Texture loadTexture(const std::string& filename) const;
Texture loadTexture(const void* buffer, const size_t bufferSize) const;
Texture loadTexturePacked(const void* buffer, const size_t buffersize) const;

SDL_Window* window() { return mWindow; }
SDL_Renderer* renderer() { return mRenderer; }
Expand Down
4 changes: 2 additions & 2 deletions OP2-Landlord/OP2-Landlord.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>../nas2d-core/;../OP2Utility/header/;../json/include;$(IncludePath)</IncludePath>
<IncludePath>../nas2d-core/;../OP2Utility/include/;../json/include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>../nas2d-core/;../OP2Utility/header/;../json/include;$(IncludePath)</IncludePath>
<IncludePath>../nas2d-core/;../OP2Utility/include/;../json/include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
Expand Down
82 changes: 76 additions & 6 deletions OP2-Landlord/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <memory>

#if defined(_WIN32)
#define NOMINMAX
#include <windows.h>
#endif

Expand All @@ -23,6 +24,11 @@
#include "StringTable.h"
#include "Utility.h"

#include "OP2Utility.h"


using namespace OP2Utility;


namespace
{
Expand All @@ -33,12 +39,14 @@ namespace
using StateGuiFunction = std::function<Gui::AppState(void)>;
std::map<Gui::AppState, StateGuiFunction> StateFunctionTable;

using StateTransitionFunction = std::function<void(Gui&)>;
using StateTransitionFunction = std::function<void(EditorConfig&, Graphics&, Gui&)>;
std::map<Gui::AppState, StateTransitionFunction> StateTransitionFunctionTable;

std::vector<Graphics::Texture> TileSets;
};


void mainLoop(Graphics& graphics, Gui& gui)
void mainLoop(EditorConfig& config, Graphics& graphics, Gui& gui)
{
std::string pathToOutpost2{};

Expand All @@ -56,14 +64,32 @@ void mainLoop(Graphics& graphics, Gui& gui)
{
try
{
StateTransitionFunctionTable.at(ApplicationState)(gui);
StateTransitionFunctionTable.at(ApplicationState)(config, graphics, gui);
}
catch (std::out_of_range)
{
std::cout << "[Warning] No transition handler for ApplicationState '" << static_cast<int>(ApplicationState) << "'" << std::endl;
}
}

if (!TileSets.empty())
{
const auto& tset = TileSets.back();

int offset = 250;
for (const auto& tset : TileSets)
{
const SDL_Rect destRect{
offset, 100,
static_cast<int>(tset.dimensions.x),
static_cast<int>(tset.dimensions.y)
};

SDL_RenderCopy(graphics.renderer(), tset.texture, nullptr, &destRect);
offset += 40;
}
}

gui.endFrame();
graphics.present();
}
Expand All @@ -76,8 +102,52 @@ void checkConfig(EditorConfig& config)
}


void loadOrCreateTransition(Gui& gui)
Graphics::Texture bmpToTexture(Graphics& graphics, EditorConfig& config, BitmapFile& bmp)
{
std::size_t pixelOffset = sizeof(BmpHeader) + sizeof(ImageHeader) + bmp.palette.size() * sizeof(Color);
std::size_t bufferSize = pixelOffset + ImageHeader::CalculatePitch(bmp.imageHeader.bitCount, bmp.imageHeader.width) * std::abs(bmp.imageHeader.height);

auto buffer = new uint8_t[bufferSize];
memset(buffer, 0, bufferSize);

Stream::MemoryWriter writer(buffer, bufferSize);

bmp.WriteIndexed(writer);

return graphics.loadTexturePacked(buffer, bufferSize);
}


void loadOrCreateTransition(EditorConfig& config, Graphics& graphics, Gui& gui)
{
Archive::VolFile artVol(config["Op2FilePath"] + "/" + "art.vol");
const auto indexCount = artVol.GetCount();

std::vector<size_t> tilesetIndicies;
for (size_t i = 0; i < indexCount; ++i)
{
const auto artName{ StringUtility::ConvertToUpper(artVol.GetName(i)) };

if (artName.find("WELL") != std::string::npos)
{
tilesetIndicies.push_back(i);
}
}

for (size_t i = 0; i < tilesetIndicies.size(); ++i)
{
const auto tsetIndex = tilesetIndicies[i];

try
{
auto bitmap = Tileset::ReadTileset(*artVol.OpenStream(tsetIndex));
TileSets.push_back(bmpToTexture(graphics, config, bitmap));
}
catch(std::runtime_error e)
{
std::cout << "[Warning] Unable to load tilset '" << artVol.GetName(tsetIndex) << "' : " << e.what() << std::endl;
}
}
}


Expand Down Expand Up @@ -107,10 +177,10 @@ int main(int argc, char* argv[])

if (ApplicationState != Gui::AppState::InitialSetup)
{
loadOrCreateTransition(gui);
loadOrCreateTransition(config, graphics, gui);
}

mainLoop(graphics, gui);
mainLoop(config, graphics, gui);

SDL_Quit();
}
Expand Down
Loading