@@ -54,7 +54,7 @@ liblol_core_headers = \ | |||||
lol/sys/threadtypes.h lol/sys/timer.h \ | lol/sys/threadtypes.h lol/sys/timer.h \ | ||||
\ | \ | ||||
lol/image/all.h \ | lol/image/all.h \ | ||||
lol/image/pixel.h lol/image/color.h lol/image/image.h lol/image/movie.h \ | |||||
lol/image/pixel.h lol/image/color.h lol/image/image.h lol/image/resource.h lol/image/movie.h \ | |||||
\ | \ | ||||
lol/gpu/all.h \ | lol/gpu/all.h \ | ||||
lol/gpu/shader.h lol/gpu/indexbuffer.h lol/gpu/vertexbuffer.h \ | lol/gpu/shader.h lol/gpu/indexbuffer.h lol/gpu/vertexbuffer.h \ | ||||
@@ -115,6 +115,7 @@ liblol_core_sources = \ | |||||
sys/init.cpp sys/file.cpp sys/hacks.cpp \ | sys/init.cpp sys/file.cpp sys/hacks.cpp \ | ||||
sys/thread.cpp sys/threadtypes.cpp sys/getopt.cpp \ | sys/thread.cpp sys/threadtypes.cpp sys/getopt.cpp \ | ||||
\ | \ | ||||
image/resource.cpp image/resource-private.h \ | |||||
image/image.cpp image/image-private.h image/kernel.cpp image/pixel.cpp \ | image/image.cpp image/image-private.h image/kernel.cpp image/pixel.cpp \ | ||||
image/crop.cpp image/resample.cpp image/noise.cpp image/combine.cpp \ | image/crop.cpp image/resample.cpp image/noise.cpp image/combine.cpp \ | ||||
image/codec/gdiplus-image.cpp image/codec/imlib2-image.cpp \ | image/codec/gdiplus-image.cpp image/codec/imlib2-image.cpp \ | ||||
@@ -21,7 +21,7 @@ extern "C" { | |||||
#include <android_native_app_glue.h> | #include <android_native_app_glue.h> | ||||
} | } | ||||
#include "../../image/image-private.h" | |||||
#include "../../image/resource-private.h" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -32,12 +32,12 @@ extern ANativeActivity *g_activity; | |||||
* Image implementation class | * Image implementation class | ||||
*/ | */ | ||||
class AndroidImageCodec : public ImageCodec | |||||
class AndroidImageCodec : public ResourceCodec | |||||
{ | { | ||||
public: | public: | ||||
virtual char const *GetName() { return "<AndroidImageCodec>"; } | virtual char const *GetName() { return "<AndroidImageCodec>"; } | ||||
virtual bool Load(Image *image, char const *path); | |||||
virtual bool Save(Image *image, char const *path); | |||||
virtual ResourceCodecData* Load(char const *path); | |||||
virtual bool Save(char const *path, ResourceCodecData* data); | |||||
virtual bool Close(); | virtual bool Close(); | ||||
virtual uint8_t *GetData() const; | virtual uint8_t *GetData() const; | ||||
@@ -50,7 +50,7 @@ private: | |||||
DECLARE_IMAGE_CODEC(AndroidImageCodec, 100) | DECLARE_IMAGE_CODEC(AndroidImageCodec, 100) | ||||
bool AndroidImageCodec::Load(Image *image, char const *path) | |||||
ResourceCodecData* AndroidImageCodec::Load(char const *path) | |||||
{ | { | ||||
JNIEnv *env; | JNIEnv *env; | ||||
jint res = g_activity->vm->GetEnv((void **)&env, JNI_VERSION_1_2); | jint res = g_activity->vm->GetEnv((void **)&env, JNI_VERSION_1_2); | ||||
@@ -106,12 +106,12 @@ bool AndroidImageCodec::Load(Image *image, char const *path) | |||||
} | } | ||||
m_format = PixelFormat::RGBA_8; | m_format = PixelFormat::RGBA_8; | ||||
return true; | |||||
return new ResourceCodecData(); | |||||
} | } | ||||
bool AndroidImageCodec::Save(Image *image, char const *path) | |||||
bool AndroidImageCodec::Save(char const *path, ResourceCodecData* data) | |||||
{ | { | ||||
UNUSED(path); | |||||
UNUSED(path, data); | |||||
/* TODO: unimplemented */ | /* TODO: unimplemented */ | ||||
} | } | ||||
@@ -10,7 +10,7 @@ | |||||
#include <lol/engine-internal.h> | #include <lol/engine-internal.h> | ||||
#include "../../image/image-private.h" | |||||
#include "../../image/resource-private.h" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -19,12 +19,12 @@ namespace lol | |||||
* Image implementation class | * Image implementation class | ||||
*/ | */ | ||||
class DummyImageCodec : public ImageCodec | |||||
class DummyImageCodec : public ResourceCodec | |||||
{ | { | ||||
public: | public: | ||||
virtual char const *GetName() { return "<DummyImageCodec>"; } | virtual char const *GetName() { return "<DummyImageCodec>"; } | ||||
virtual bool Load(Image *image, char const *path); | |||||
virtual bool Save(Image *image, char const *path); | |||||
virtual ResourceCodecData* Load(char const *path); | |||||
virtual bool Save(char const *path, ResourceCodecData* data); | |||||
}; | }; | ||||
//Priority 0 because it's supposed to be the last one | //Priority 0 because it's supposed to be the last one | ||||
@@ -34,11 +34,13 @@ DECLARE_IMAGE_CODEC(DummyImageCodec, 0) | |||||
* Public Image class | * Public Image class | ||||
*/ | */ | ||||
bool DummyImageCodec::Load(Image *image, char const *path) | |||||
ResourceCodecData* DummyImageCodec::Load(char const *path) | |||||
{ | { | ||||
UNUSED(path); | |||||
if (strcmp("DUMMY", path)) | |||||
return nullptr; | |||||
image->SetSize(ivec2(256)); | |||||
auto data = new ResourceImageData(new Image(ivec2(256))); | |||||
auto image = data->m_image; | |||||
u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>(), *tmp = pixels; | u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>(), *tmp = pixels; | ||||
for (int j = 0; j < 256; j++) | for (int j = 0; j < 256; j++) | ||||
for (int i = 0; i < 256; i++) | for (int i = 0; i < 256; i++) | ||||
@@ -51,13 +53,12 @@ bool DummyImageCodec::Load(Image *image, char const *path) | |||||
} | } | ||||
image->Unlock(pixels); | image->Unlock(pixels); | ||||
//return false, because we're not supposed to be here. | |||||
return false; | |||||
return data; | |||||
} | } | ||||
bool DummyImageCodec::Save(Image *image, char const *path) | |||||
bool DummyImageCodec::Save(char const *path, ResourceCodecData* data) | |||||
{ | { | ||||
UNUSED(path); | |||||
UNUSED(path, data); | |||||
return false; | return false; | ||||
} | } | ||||
@@ -26,7 +26,7 @@ using std::max; | |||||
#if LOL_USE_GDIPLUS | #if LOL_USE_GDIPLUS | ||||
#include "../../image/image-private.h" | |||||
#include "../../image/resource-private.h" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -35,12 +35,12 @@ namespace lol | |||||
* Image implementation class | * Image implementation class | ||||
*/ | */ | ||||
class GdiPlusImageCodec : public ImageCodec | |||||
class GdiPlusImageCodec : public ResourceCodec | |||||
{ | { | ||||
public: | public: | ||||
virtual char const *GetName() { return "<GdiPlusImageCodec>"; } | virtual char const *GetName() { return "<GdiPlusImageCodec>"; } | ||||
virtual bool Load(Image *image, char const *path); | |||||
virtual bool Save(Image *image, char const *path); | |||||
virtual ResourceCodecData* Load(char const *path); | |||||
virtual bool Save(char const *path, ResourceCodecData* data); | |||||
}; | }; | ||||
DECLARE_IMAGE_CODEC(GdiPlusImageCodec, 100) | DECLARE_IMAGE_CODEC(GdiPlusImageCodec, 100) | ||||
@@ -49,7 +49,7 @@ DECLARE_IMAGE_CODEC(GdiPlusImageCodec, 100) | |||||
* Public Image class | * Public Image class | ||||
*/ | */ | ||||
bool GdiPlusImageCodec::Load(Image *image, char const *path) | |||||
ResourceCodecData* GdiPlusImageCodec::Load(char const *path) | |||||
{ | { | ||||
Gdiplus::Status status; | Gdiplus::Status status; | ||||
ULONG_PTR token; | ULONG_PTR token; | ||||
@@ -58,7 +58,7 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path) | |||||
if (status != Gdiplus::Ok) | if (status != Gdiplus::Ok) | ||||
{ | { | ||||
msg::error("error %d while initialising GDI+\n", status); | msg::error("error %d while initialising GDI+\n", status); | ||||
return false; | |||||
return nullptr; | |||||
} | } | ||||
array<String> pathlist = sys::get_path_list(path); | array<String> pathlist = sys::get_path_list(path); | ||||
@@ -99,7 +99,7 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path) | |||||
if (!bitmap) | if (!bitmap) | ||||
{ | { | ||||
msg::error("could not load %s\n", path); | msg::error("could not load %s\n", path); | ||||
return false; | |||||
return nullptr; | |||||
} | } | ||||
ivec2 size(bitmap->GetWidth(), bitmap->GetHeight()); | ivec2 size(bitmap->GetWidth(), bitmap->GetHeight()); | ||||
@@ -110,13 +110,14 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path) | |||||
{ | { | ||||
msg::error("could not lock bits in %s\n", path); | msg::error("could not lock bits in %s\n", path); | ||||
delete bitmap; | delete bitmap; | ||||
return false; | |||||
return nullptr; | |||||
} | } | ||||
/* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't | /* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't | ||||
* know about ARGB, only RGBA. So we swap bytes. We could also fix | * know about ARGB, only RGBA. So we swap bytes. We could also fix | ||||
* this in the shader. */ | * this in the shader. */ | ||||
image->SetSize(size); | |||||
auto data = new ResourceImageData(new Image(ivec2(size))); | |||||
auto image = data->m_image; | |||||
u8vec4 *pdst = image->Lock<PixelFormat::RGBA_8>(); | u8vec4 *pdst = image->Lock<PixelFormat::RGBA_8>(); | ||||
u8vec4 *psrc = static_cast<u8vec4 *>(bdata.Scan0); | u8vec4 *psrc = static_cast<u8vec4 *>(bdata.Scan0); | ||||
for (int n = 0; n < size.x * size.y; n++) | for (int n = 0; n < size.x * size.y; n++) | ||||
@@ -126,11 +127,15 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path) | |||||
bitmap->UnlockBits(&bdata); | bitmap->UnlockBits(&bdata); | ||||
delete bitmap; | delete bitmap; | ||||
return true; | |||||
return data; | |||||
} | } | ||||
bool GdiPlusImageCodec::Save(Image *image, char const *path) | |||||
bool GdiPlusImageCodec::Save(char const *path, ResourceCodecData* data) | |||||
{ | { | ||||
auto data_image = dynamic_cast<ResourceImageData*>(data); | |||||
if (data_image == nullptr) | |||||
return false; | |||||
ULONG_PTR token; | ULONG_PTR token; | ||||
Gdiplus::GdiplusStartupInput input; | Gdiplus::GdiplusStartupInput input; | ||||
Gdiplus::GdiplusStartup(&token, &input, nullptr); | Gdiplus::GdiplusStartup(&token, &input, nullptr); | ||||
@@ -178,6 +183,7 @@ bool GdiPlusImageCodec::Save(Image *image, char const *path) | |||||
return false; | return false; | ||||
} | } | ||||
auto image = data_image->m_image; | |||||
ivec2 size = image->GetSize(); | ivec2 size = image->GetSize(); | ||||
Gdiplus::Bitmap *b = new Gdiplus::Bitmap(size.x, size.y, | Gdiplus::Bitmap *b = new Gdiplus::Bitmap(size.x, size.y, | ||||
@@ -22,7 +22,7 @@ static_assert(sizeof(DATA32) == sizeof(uint32_t), "Imlib2 type DATA32 is broken" | |||||
static_assert(sizeof(DATA16) == sizeof(uint16_t), "Imlib2 type DATA16 is broken"); | static_assert(sizeof(DATA16) == sizeof(uint16_t), "Imlib2 type DATA16 is broken"); | ||||
static_assert(sizeof(DATA8) == sizeof(uint8_t), "Imlib2 type DATA8 is broken"); | static_assert(sizeof(DATA8) == sizeof(uint8_t), "Imlib2 type DATA8 is broken"); | ||||
#include "../../image/image-private.h" | |||||
#include "../../image/resource-private.h" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -31,17 +31,18 @@ namespace lol | |||||
* Imlib2 image codec | * Imlib2 image codec | ||||
*/ | */ | ||||
class Imlib2ImageCodec : public ImageCodec | |||||
class Imlib2ImageCodec : public ResourceCodec | |||||
{ | { | ||||
public: | public: | ||||
virtual bool Load(Image *image, char const *path); | |||||
virtual bool Save(Image *image, char const *path); | |||||
virtual char const *GetName() { return "<Imlib2ImageCodec>"; } | |||||
virtual ResourceCodecData* Load(char const *path); | |||||
virtual bool Save(char const *path, ResourceCodecData* data); | |||||
}; | }; | ||||
/* Set priority higher than SDL because we can save in many formats. */ | /* Set priority higher than SDL because we can save in many formats. */ | ||||
DECLARE_IMAGE_CODEC(Imlib2ImageCodec, 70) | DECLARE_IMAGE_CODEC(Imlib2ImageCodec, 70) | ||||
bool Imlib2ImageCodec::Load(Image *image, char const *path) | |||||
ResourceCodecData *Imlib2ImageCodec::Load(char const *path) | |||||
{ | { | ||||
Imlib_Image im = nullptr; | Imlib_Image im = nullptr; | ||||
@@ -57,7 +58,7 @@ bool Imlib2ImageCodec::Load(Image *image, char const *path) | |||||
#if !LOL_BUILD_RELEASE | #if !LOL_BUILD_RELEASE | ||||
msg::error("could not load image %s\n", path); | msg::error("could not load image %s\n", path); | ||||
#endif | #endif | ||||
return false; | |||||
return nullptr; | |||||
} | } | ||||
imlib_context_set_image(im); | imlib_context_set_image(im); | ||||
@@ -69,11 +70,12 @@ bool Imlib2ImageCodec::Load(Image *image, char const *path) | |||||
#if !LOL_BUILD_RELEASE | #if !LOL_BUILD_RELEASE | ||||
msg::error("could not get image data for %s\n", path); | msg::error("could not get image data for %s\n", path); | ||||
#endif | #endif | ||||
return false; | |||||
return nullptr; | |||||
} | } | ||||
ivec2 size(imlib_image_get_width(), imlib_image_get_height()); | ivec2 size(imlib_image_get_width(), imlib_image_get_height()); | ||||
image->SetSize(size); | |||||
auto data = new ResourceImageData(new Image(size)); | |||||
auto image = data->m_image; | |||||
u8vec4 *dstdata = image->Lock<PixelFormat::RGBA_8>(); | u8vec4 *dstdata = image->Lock<PixelFormat::RGBA_8>(); | ||||
@@ -88,11 +90,16 @@ bool Imlib2ImageCodec::Load(Image *image, char const *path) | |||||
imlib_free_image(); | imlib_free_image(); | ||||
return true; | |||||
return data; | |||||
} | } | ||||
bool Imlib2ImageCodec::Save(Image *image, char const *path) | |||||
bool Imlib2ImageCodec::Save(char const *path, ResourceCodecData *data) | |||||
{ | { | ||||
auto data_image = dynamic_cast<ResourceImageData*>(data); | |||||
if (data_image == nullptr) | |||||
return false; | |||||
auto image = data_image->m_image; | |||||
ivec2 size = image->GetSize(); | ivec2 size = image->GetSize(); | ||||
Imlib_Image priv = imlib_create_image(size.x, size.y); | Imlib_Image priv = imlib_create_image(size.x, size.y); | ||||
@@ -16,7 +16,7 @@ | |||||
#import <UIKit/UIKit.h> | #import <UIKit/UIKit.h> | ||||
#include "../../image/image-private.h" | |||||
#include "../../image/resource-private.h" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -25,12 +25,12 @@ namespace lol | |||||
* Image implementation class | * Image implementation class | ||||
*/ | */ | ||||
class IosImageCodec : public ImageCodec | |||||
class IosImageCodec : public ResourceCodec | |||||
{ | { | ||||
public: | public: | ||||
virtual char const *GetName() { return "<IosImageCodec>"; } | virtual char const *GetName() { return "<IosImageCodec>"; } | ||||
virtual bool Load(Image *image, char const *path); | |||||
virtual bool Save(Image *image, char const *path); | |||||
virtual ResourceCodecData* Load(char const *path); | |||||
virtual bool Save(char const *path, ResourceCodecData* data); | |||||
}; | }; | ||||
DECLARE_IMAGE_CODEC(IosImageCodec, 100) | DECLARE_IMAGE_CODEC(IosImageCodec, 100) | ||||
@@ -39,7 +39,7 @@ DECLARE_IMAGE_CODEC(IosImageCodec, 100) | |||||
* Public Image class | * Public Image class | ||||
*/ | */ | ||||
bool IosImageCodec::Load(Image *image, char const *path) | |||||
ResourceCodecData* IosImageCodec::Load(char const *path) | |||||
{ | { | ||||
NSString *fullpath = [NSString stringWithUTF8String:path]; | NSString *fullpath = [NSString stringWithUTF8String:path]; | ||||
NSArray *chunks = [fullpath componentsSeparatedByString: @"/"]; | NSArray *chunks = [fullpath componentsSeparatedByString: @"/"]; | ||||
@@ -54,7 +54,7 @@ bool IosImageCodec::Load(Image *image, char const *path) | |||||
#if !LOL_BUILD_RELEASE | #if !LOL_BUILD_RELEASE | ||||
msg::error("could not load %s\n", path); | msg::error("could not load %s\n", path); | ||||
#endif | #endif | ||||
return false; | |||||
return nullptr; | |||||
} | } | ||||
int w = CGImageGetWidth(image.CGImage); | int w = CGImageGetWidth(image.CGImage); | ||||
@@ -75,12 +75,12 @@ bool IosImageCodec::Load(Image *image, char const *path) | |||||
[image release]; | [image release]; | ||||
[pngdata release]; | [pngdata release]; | ||||
return true; | |||||
return new ResourceCodecData(); | |||||
} | } | ||||
bool IosImageCodec::Save(Image *image, char const *path) | |||||
bool IosImageCodec::Save(char const *path, ResourceCodecData* data) | |||||
{ | { | ||||
UNUSED(path); | |||||
UNUSED(path, data); | |||||
/* TODO: unimplemented */ | /* TODO: unimplemented */ | ||||
return true; | return true; | ||||
@@ -12,7 +12,7 @@ | |||||
#include <cctype> | #include <cctype> | ||||
#include "../../image/image-private.h" | |||||
#include "../../image/resource-private.h" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -27,12 +27,12 @@ namespace lol | |||||
* Image implementation class | * Image implementation class | ||||
*/ | */ | ||||
class OricImageCodec : public ImageCodec | |||||
class OricImageCodec : public ResourceCodec | |||||
{ | { | ||||
public: | public: | ||||
virtual char const *GetName() { return "<OricImageCodec>"; } | virtual char const *GetName() { return "<OricImageCodec>"; } | ||||
virtual bool Load(Image *image, char const *path); | |||||
virtual bool Save(Image *image, char const *path); | |||||
virtual ResourceCodecData* Load(char const *path); | |||||
virtual bool Save(char const *path, ResourceCodecData* data); | |||||
private: | private: | ||||
static String ReadScreen(char const *name); | static String ReadScreen(char const *name); | ||||
@@ -45,7 +45,7 @@ DECLARE_IMAGE_CODEC(OricImageCodec, 100) | |||||
* Public Image class | * Public Image class | ||||
*/ | */ | ||||
bool OricImageCodec::Load(Image *image, char const *path) | |||||
ResourceCodecData* OricImageCodec::Load(char const *path) | |||||
{ | { | ||||
static u8vec4 const pal[8] = | static u8vec4 const pal[8] = | ||||
{ | { | ||||
@@ -61,9 +61,10 @@ bool OricImageCodec::Load(Image *image, char const *path) | |||||
String screen = ReadScreen(path); | String screen = ReadScreen(path); | ||||
if (screen.count() == 0) | if (screen.count() == 0) | ||||
return false; | |||||
return nullptr; | |||||
image->SetSize(ivec2(WIDTH, screen.count() * 6 / WIDTH)); | |||||
auto data = new ResourceImageData(new Image(ivec2(WIDTH, screen.count() * 6 / WIDTH))); | |||||
auto image = data->m_image; | |||||
u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>(); | u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>(); | ||||
@@ -102,12 +103,16 @@ bool OricImageCodec::Load(Image *image, char const *path) | |||||
image->Unlock(pixels); | image->Unlock(pixels); | ||||
return true; | |||||
return data; | |||||
} | } | ||||
bool OricImageCodec::Save(Image *image, char const *path) | |||||
bool OricImageCodec::Save(char const *path, ResourceCodecData* data) | |||||
{ | { | ||||
int len = strlen(path); | |||||
auto data_image = dynamic_cast<ResourceImageData*>(data); | |||||
if (data_image == nullptr) | |||||
return false; | |||||
int len = (int)strlen(path); | |||||
if (len < 4 || path[len - 4] != '.' | if (len < 4 || path[len - 4] != '.' | ||||
|| toupper(path[len - 3]) != 'T' | || toupper(path[len - 3]) != 'T' | ||||
|| toupper(path[len - 2]) != 'A' | || toupper(path[len - 2]) != 'A' | ||||
@@ -124,6 +129,7 @@ bool OricImageCodec::Save(Image *image, char const *path) | |||||
result << (uint8_t)name[0]; | result << (uint8_t)name[0]; | ||||
result << 0; | result << 0; | ||||
auto image = data_image->m_image; | |||||
Image tmp; | Image tmp; | ||||
ivec2 size = image->GetSize(); | ivec2 size = image->GetSize(); | ||||
if (size.x != WIDTH) | if (size.x != WIDTH) | ||||
@@ -481,7 +487,7 @@ void OricImageCodec::WriteScreen(Image &image, array<uint8_t> &result) | |||||
for (int y = 0; y < size.y; y++) | for (int y = 0; y < size.y; y++) | ||||
for (int x = 0; x < size.x; x++) | for (int x = 0; x < size.x; x++) | ||||
for (int c = 0; c < 3; c++) | for (int c = 0; c < 3; c++) | ||||
src[x][y][c] = 0xffff * pixels[y * size.x + x][2 - c]; | |||||
src[x][y][c] = 0xffff * (int32_t)pixels[y * size.x + x][2 - c]; | |||||
/* Let the fun begin */ | /* Let the fun begin */ | ||||
for (int y = 0; y < size.y; y++) | for (int y = 0; y < size.y; y++) | ||||
@@ -25,7 +25,7 @@ | |||||
# include <SDL_image.h> | # include <SDL_image.h> | ||||
#endif | #endif | ||||
#include "../../image/image-private.h" | |||||
#include "../../image/resource-private.h" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -34,19 +34,19 @@ namespace lol | |||||
* Image implementation class | * Image implementation class | ||||
*/ | */ | ||||
class SdlImageCodec : public ImageCodec | |||||
class SdlImageCodec : public ResourceCodec | |||||
{ | { | ||||
public: | public: | ||||
virtual char const *GetName() { return "<SdlImageCodec>"; } | virtual char const *GetName() { return "<SdlImageCodec>"; } | ||||
virtual bool Load(Image *image, char const *path); | |||||
virtual bool Save(Image *image, char const *path); | |||||
virtual ResourceCodecData* Load(char const *path); | |||||
virtual bool Save(char const *path, ResourceCodecData* data); | |||||
static SDL_Surface *Create32BppSurface(ivec2 size); | static SDL_Surface *Create32BppSurface(ivec2 size); | ||||
}; | }; | ||||
DECLARE_IMAGE_CODEC(SdlImageCodec, 50) | DECLARE_IMAGE_CODEC(SdlImageCodec, 50) | ||||
bool SdlImageCodec::Load(Image *image, char const *path) | |||||
ResourceCodecData* SdlImageCodec::Load(char const *path) | |||||
{ | { | ||||
SDL_Surface *surface = nullptr; | SDL_Surface *surface = nullptr; | ||||
@@ -62,7 +62,7 @@ bool SdlImageCodec::Load(Image *image, char const *path) | |||||
#if !LOL_BUILD_RELEASE | #if !LOL_BUILD_RELEASE | ||||
msg::error("could not load image %s\n", path); | msg::error("could not load image %s\n", path); | ||||
#endif | #endif | ||||
return false; | |||||
return nullptr; | |||||
} | } | ||||
ivec2 size(surface->w, surface->h); | ivec2 size(surface->w, surface->h); | ||||
@@ -75,24 +75,30 @@ bool SdlImageCodec::Load(Image *image, char const *path) | |||||
surface = tmp; | surface = tmp; | ||||
} | } | ||||
image->SetSize(size); | |||||
u8vec4 *data = image->Lock<PixelFormat::RGBA_8>(); | |||||
memcpy(data, surface->pixels, 4 * size.x * size.y); | |||||
image->Unlock(data); | |||||
auto data = new ResourceImageData(new Image(size)); | |||||
auto image = data->m_image; | |||||
u8vec4 *pixel_data = image->Lock<PixelFormat::RGBA_8>(); | |||||
memcpy(pixel_data, surface->pixels, 4 * size.x * size.y); | |||||
image->Unlock(pixel_data); | |||||
SDL_FreeSurface(surface); | SDL_FreeSurface(surface); | ||||
return true; | |||||
return data; | |||||
} | } | ||||
bool SdlImageCodec::Save(Image *image, char const *path) | |||||
bool SdlImageCodec::Save(char const *path, ResourceCodecData* data) | |||||
{ | { | ||||
auto data_image = dynamic_cast<ResourceImageData*>(data); | |||||
if (data_image == nullptr) | |||||
return false; | |||||
auto image = data_image->m_image; | |||||
ivec2 size = image->GetSize(); | ivec2 size = image->GetSize(); | ||||
SDL_Surface *surface = Create32BppSurface(size); | SDL_Surface *surface = Create32BppSurface(size); | ||||
u8vec4 *data = image->Lock<PixelFormat::RGBA_8>(); | |||||
memcpy(surface->pixels, data, 4 * size.x * size.y); | |||||
image->Unlock(data); | |||||
u8vec4 *pixel_data = image->Lock<PixelFormat::RGBA_8>(); | |||||
memcpy(surface->pixels, pixel_data, 4 * size.x * size.y); | |||||
image->Unlock(pixel_data); | |||||
int ret = SDL_SaveBMP(surface, path); | int ret = SDL_SaveBMP(surface, path); | ||||
SDL_FreeSurface(surface); | SDL_FreeSurface(surface); | ||||
@@ -11,7 +11,7 @@ | |||||
#include <lol/engine-internal.h> | #include <lol/engine-internal.h> | ||||
#include "../../image/image-private.h" | |||||
#include "../../image/resource-private.h" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -20,24 +20,12 @@ namespace lol | |||||
* Image implementation class | * Image implementation class | ||||
*/ | */ | ||||
class ZedImageCodec : public ImageCodec | |||||
class ZedImageCodec : public ResourceCodec | |||||
{ | { | ||||
public: | public: | ||||
virtual char const *GetName() { return "<ZedImageCodec>"; } | virtual char const *GetName() { return "<ZedImageCodec>"; } | ||||
virtual bool Load(Image *image, char const *path); | |||||
virtual bool Save(Image *image, char const *path); | |||||
virtual bool RetrieveTiles(array<ivec2, ivec2>& tiles) | |||||
{ | |||||
bool result = m_tiles.count() > 0; | |||||
tiles += m_tiles; | |||||
m_tiles.empty(); | |||||
return result; | |||||
} | |||||
private: | |||||
//<Pos, Size> | |||||
array<ivec2, ivec2> m_tiles; | |||||
virtual ResourceCodecData* Load(char const *path); | |||||
virtual bool Save(char const *path, ResourceCodecData* data); | |||||
}; | }; | ||||
DECLARE_IMAGE_CODEC(ZedImageCodec, 10) | DECLARE_IMAGE_CODEC(ZedImageCodec, 10) | ||||
@@ -46,10 +34,10 @@ DECLARE_IMAGE_CODEC(ZedImageCodec, 10) | |||||
* Public Image class | * Public Image class | ||||
*/ | */ | ||||
bool ZedImageCodec::Load(Image *image, char const *path) | |||||
ResourceCodecData* ZedImageCodec::Load(char const *path) | |||||
{ | { | ||||
if (!lol::String(path).ends_with(".RSC")) | if (!lol::String(path).ends_with(".RSC")) | ||||
return false; | |||||
return nullptr; | |||||
// Compacter definition | // Compacter definition | ||||
struct CompactSecondary | struct CompactSecondary | ||||
@@ -142,7 +130,9 @@ bool ZedImageCodec::Load(Image *image, char const *path) | |||||
} | } | ||||
file_offset << file_size; | file_offset << file_size; | ||||
m_tiles.reserve(file_count); | |||||
//<Pos, Size> | |||||
array<ivec2, ivec2> tiles; | |||||
tiles.reserve(file_count); | |||||
Compacter2d compacter; | Compacter2d compacter; | ||||
compacter.StepSetup(8, 8, 10); | compacter.StepSetup(8, 8, 10); | ||||
@@ -151,6 +141,7 @@ bool ZedImageCodec::Load(Image *image, char const *path) | |||||
array<uint8_t> file_convert; | array<uint8_t> file_convert; | ||||
file_convert.reserve(file_size); | file_convert.reserve(file_size); | ||||
array<ivec2> available_sizes; | array<ivec2> available_sizes; | ||||
//got through all the files and store them | |||||
for (int i = 0; i < file_count; i++) | for (int i = 0; i < file_count; i++) | ||||
{ | { | ||||
file_pos = file_offset[i]; | file_pos = file_offset[i]; | ||||
@@ -187,8 +178,10 @@ bool ZedImageCodec::Load(Image *image, char const *path) | |||||
//Prepare buffer and tiles infos | //Prepare buffer and tiles infos | ||||
int32_t convert_pos = file_convert.count(); | int32_t convert_pos = file_convert.count(); | ||||
ivec2 size = ivec2(size_x, size_y); | ivec2 size = ivec2(size_x, size_y); | ||||
compacter.Store(m_tiles.count(), ivec2(size_x, size_y)); | |||||
m_tiles.push(ivec2(file_convert.count(), data_length), ivec2(size_x, size_y)); | |||||
//store tile in compacter | |||||
compacter.Store(tiles.count(), ivec2(size_x, size_y)); | |||||
//push tile on the stack | |||||
tiles.push(ivec2(file_convert.count(), data_length), ivec2(size_x, size_y)); | |||||
file_convert.resize(convert_pos + data_length); | file_convert.resize(convert_pos + data_length); | ||||
//Retrieve actual datas | //Retrieve actual datas | ||||
@@ -233,8 +226,9 @@ bool ZedImageCodec::Load(Image *image, char const *path) | |||||
while (tex_size < tex_sqrt) | while (tex_size < tex_sqrt) | ||||
tex_size <<= 1; | tex_size <<= 1; | ||||
//Prepare final imqge | |||||
image->SetSize(ivec2(tex_size)); | |||||
//Prepare final image | |||||
auto data = new ResourceTilesetData(new Image(ivec2(tex_size))); | |||||
auto image = data->m_image; | |||||
uint8_t *pixels = image->Lock<PixelFormat::Y_8>(); | uint8_t *pixels = image->Lock<PixelFormat::Y_8>(); | ||||
//Data refactor stage | //Data refactor stage | ||||
@@ -255,8 +249,8 @@ bool ZedImageCodec::Load(Image *image, char const *path) | |||||
compacter.m_primary[j].m_count--; | compacter.m_primary[j].m_count--; | ||||
int i = compacter.m_primary[j].m_secondary[k].m_tiles.pop(); | int i = compacter.m_primary[j].m_secondary[k].m_tiles.pop(); | ||||
int32_t file_off = m_tiles[i].m1[0]; | |||||
ivec2 t_size = m_tiles[i].m2; | |||||
int32_t file_off = tiles[i].m1[0]; | |||||
ivec2 t_size = tiles[i].m2; | |||||
ASSERT(pos.y + t_size.y < tex_size); | ASSERT(pos.y + t_size.y < tex_size); | ||||
@@ -277,7 +271,7 @@ bool ZedImageCodec::Load(Image *image, char const *path) | |||||
} | } | ||||
//Register new pos and move to next | //Register new pos and move to next | ||||
m_tiles[i].m1 = pos; | |||||
tiles[i].m1 = pos; | |||||
pos.x += t_size.x; | pos.x += t_size.x; | ||||
} | } | ||||
} | } | ||||
@@ -292,12 +286,14 @@ bool ZedImageCodec::Load(Image *image, char const *path) | |||||
} | } | ||||
image->Unlock(pixels); | image->Unlock(pixels); | ||||
return true; | |||||
data->m_tiles = tiles; | |||||
return data; | |||||
} | } | ||||
bool ZedImageCodec::Save(Image *image, char const *path) | |||||
bool ZedImageCodec::Save(char const *path, ResourceCodecData* data) | |||||
{ | { | ||||
UNUSED(path); | |||||
UNUSED(path, data); | |||||
/* FIXME: do we need to implement this? */ | /* FIXME: do we need to implement this? */ | ||||
return true; | return true; | ||||
} | } | ||||
@@ -10,7 +10,7 @@ | |||||
#include <lol/engine-internal.h> | #include <lol/engine-internal.h> | ||||
#include "../../image/image-private.h" | |||||
#include "../../image/resource-private.h" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -19,12 +19,12 @@ namespace lol | |||||
* Image implementation class | * Image implementation class | ||||
*/ | */ | ||||
class ZedPaletteImageCodec : public ImageCodec | |||||
class ZedPaletteImageCodec : public ResourceCodec | |||||
{ | { | ||||
public: | public: | ||||
virtual char const *GetName() { return "<ZedPaletteImageCodec>"; } | virtual char const *GetName() { return "<ZedPaletteImageCodec>"; } | ||||
virtual bool Load(Image *image, char const *path); | |||||
virtual bool Save(Image *image, char const *path); | |||||
virtual ResourceCodecData* Load(char const *path); | |||||
virtual bool Save(char const *path, ResourceCodecData* data); | |||||
}; | }; | ||||
DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 10) | DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 10) | ||||
@@ -33,10 +33,10 @@ DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 10) | |||||
* Public Image class | * Public Image class | ||||
*/ | */ | ||||
bool ZedPaletteImageCodec::Load(Image *image, char const *path) | |||||
ResourceCodecData* ZedPaletteImageCodec::Load(char const *path) | |||||
{ | { | ||||
if (!lol::String(path).ends_with(".pal")) | if (!lol::String(path).ends_with(".pal")) | ||||
return false; | |||||
return nullptr; | |||||
File file; | File file; | ||||
file.Open(path, FileAccess::Read, true); | file.Open(path, FileAccess::Read, true); | ||||
@@ -53,13 +53,15 @@ bool ZedPaletteImageCodec::Load(Image *image, char const *path) | |||||
int32_t tex_size = 2; | int32_t tex_size = 2; | ||||
while (tex_size < tex_sqrt) | while (tex_size < tex_sqrt) | ||||
tex_size <<= 1; | tex_size <<= 1; | ||||
image->m_data->m_size = ivec2(tex_size); | |||||
auto data = new ResourceImageData(new Image(ivec2(tex_size))); | |||||
auto image = data->m_image; | |||||
#else | #else | ||||
int32_t tex_sqrt = file_size / 3; | int32_t tex_sqrt = file_size / 3; | ||||
int32_t tex_size = 2; | int32_t tex_size = 2; | ||||
while (tex_size < tex_sqrt) | while (tex_size < tex_sqrt) | ||||
tex_size <<= 1; | tex_size <<= 1; | ||||
image->SetSize(ivec2(tex_size, 1)); | |||||
auto data = new ResourceImageData(new Image(ivec2(tex_size, 1))); | |||||
auto image = data->m_image; | |||||
#endif | #endif | ||||
u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>(); | u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>(); | ||||
@@ -73,12 +75,12 @@ bool ZedPaletteImageCodec::Load(Image *image, char const *path) | |||||
} | } | ||||
image->Unlock(pixels); | image->Unlock(pixels); | ||||
return true; | |||||
return data; | |||||
} | } | ||||
bool ZedPaletteImageCodec::Save(Image *image, char const *path) | |||||
bool ZedPaletteImageCodec::Save(char const *path, ResourceCodecData* data) | |||||
{ | { | ||||
UNUSED(path); | |||||
UNUSED(path, data); | |||||
/* FIXME: do we need to implement this? */ | /* FIXME: do we need to implement this? */ | ||||
return true; | return true; | ||||
} | } | ||||
@@ -66,38 +66,5 @@ public: | |||||
PixelFormat m_format; | PixelFormat m_format; | ||||
}; | }; | ||||
class ImageCodec | |||||
{ | |||||
public: | |||||
virtual char const *GetName() { return "<ImageCodec>"; } | |||||
virtual bool Load(Image *image, char const *path) = 0; | |||||
virtual bool Save(Image *image, char const *path) = 0; | |||||
/* TODO: this should become more fine-grained */ | |||||
int m_priority; | |||||
}; | |||||
#define REGISTER_IMAGE_CODEC(name) \ | |||||
extern ImageCodec *Register##name(); \ | |||||
{ \ | |||||
/* Insert image codecs in a sorted list */ \ | |||||
ImageCodec *codec = Register##name(); \ | |||||
int i = 0, prio = codec->m_priority; \ | |||||
for ( ; i < codeclist.count(); ++i) \ | |||||
{ \ | |||||
if (codeclist[i]->m_priority <= prio) \ | |||||
break; \ | |||||
} \ | |||||
codeclist.insert(codec, i); \ | |||||
} | |||||
#define DECLARE_IMAGE_CODEC(name, priority) \ | |||||
ImageCodec *Register##name() \ | |||||
{ \ | |||||
ImageCodec *ret = new name(); \ | |||||
ret->m_priority = priority; \ | |||||
return ret; \ | |||||
} | |||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -19,61 +19,6 @@ | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
/* HACK: We cannot make this an ImageLoader member function, because the | |||||
* REGISTER_IMAGE_CODEC macro forward-declares free functions from | |||||
* the "lol" namespace. An apparent bug in Visual Studio's compiler | |||||
* makes it think these functions are actually in the top-level | |||||
* namespace when the forward declaration is in a class member function. | |||||
* To avoid the problem, we make the forward declaration in a free | |||||
* function. | |||||
* The bug was reported to Microsoft and fixed by them, but the fix | |||||
* is not yet available. | |||||
* https://connect.microsoft.com/VisualStudio/feedback/details/730878/ */ | |||||
static bool RegisterAllCodecs(array<ImageCodec *> &codeclist) | |||||
{ | |||||
#if defined __ANDROID__ | |||||
REGISTER_IMAGE_CODEC(AndroidImageCodec) | |||||
#endif | |||||
#if defined LOL_USE_GDIPLUS | |||||
REGISTER_IMAGE_CODEC(GdiPlusImageCodec) | |||||
#endif | |||||
#if defined __APPLE__ && defined __MACH__ && defined __arm__ | |||||
REGISTER_IMAGE_CODEC(IosImageCodec) | |||||
#endif | |||||
#if defined LOL_USE_SDL_IMAGE | |||||
REGISTER_IMAGE_CODEC(SdlImageCodec) | |||||
#endif | |||||
#if defined LOL_USE_IMLIB2 | |||||
REGISTER_IMAGE_CODEC(Imlib2ImageCodec) | |||||
#endif | |||||
REGISTER_IMAGE_CODEC(DummyImageCodec) | |||||
REGISTER_IMAGE_CODEC(ZedImageCodec) | |||||
REGISTER_IMAGE_CODEC(ZedPaletteImageCodec) | |||||
REGISTER_IMAGE_CODEC(OricImageCodec) | |||||
return true; | |||||
} | |||||
/* | |||||
* Our static image loader | |||||
*/ | |||||
static class ImageLoader | |||||
{ | |||||
friend class Image; | |||||
public: | |||||
inline ImageLoader() | |||||
{ | |||||
RegisterAllCodecs(m_codecs); | |||||
} | |||||
private: | |||||
array<ImageCodec *> m_codecs; | |||||
map<String, Image *> m_images; | |||||
} | |||||
g_image_loader; | |||||
/* | /* | ||||
* Public Image class | * Public Image class | ||||
*/ | */ | ||||
@@ -117,77 +62,59 @@ Image::~Image() | |||||
delete m_data; | delete m_data; | ||||
} | } | ||||
void Image::DummyFill() | |||||
{ | |||||
//TODO: This is not very beautiful | |||||
for (auto codec : g_image_loader.m_codecs) | |||||
{ | |||||
if (String(codec->GetName()).contains("Dummy")) | |||||
{ | |||||
codec->Load(this, nullptr); | |||||
return; | |||||
} | |||||
} | |||||
} | |||||
void Image::Copy(uint8_t* pixels, ivec2 const& size, PixelFormat fmt) | |||||
void Image::Copy(uint8_t* src_pixels, ivec2 const& size, PixelFormat fmt) | |||||
{ | { | ||||
ASSERT(fmt != PixelFormat::Unknown); | ASSERT(fmt != PixelFormat::Unknown); | ||||
SetSize(size); | SetSize(size); | ||||
SetFormat(fmt); | SetFormat(fmt); | ||||
memcpy(m_data->m_pixels[(int)fmt]->data(), pixels, | |||||
memcpy(m_data->m_pixels[(int)fmt]->data(), src_pixels, | |||||
size.x * size.y * BytesPerPixel(fmt)); | size.x * size.y * BytesPerPixel(fmt)); | ||||
} | } | ||||
void Image::Copy(Image const &other) | |||||
void Image::Copy(Image const &src) | |||||
{ | { | ||||
ivec2 size = other.GetSize(); | |||||
PixelFormat fmt = other.GetFormat(); | |||||
ivec2 size = src.GetSize(); | |||||
PixelFormat fmt = src.GetFormat(); | |||||
SetSize(size); | SetSize(size); | ||||
if (fmt != PixelFormat::Unknown) | if (fmt != PixelFormat::Unknown) | ||||
{ | { | ||||
SetFormat(fmt); | SetFormat(fmt); | ||||
memcpy(m_data->m_pixels[(int)fmt]->data(), | memcpy(m_data->m_pixels[(int)fmt]->data(), | ||||
other.m_data->m_pixels[(int)fmt]->data(), | |||||
src.m_data->m_pixels[(int)fmt]->data(), | |||||
size.x * size.y * BytesPerPixel(fmt)); | size.x * size.y * BytesPerPixel(fmt)); | ||||
} | } | ||||
} | } | ||||
void Image::DummyFill() | |||||
{ | |||||
Load("DUMMY"); | |||||
} | |||||
bool Image::Load(char const *path) | bool Image::Load(char const *path) | ||||
{ | { | ||||
ImageCodec* last_codec = nullptr; | |||||
for (auto codec : g_image_loader.m_codecs) | |||||
auto resource = ResourceLoader::Load(path); | |||||
if (resource == nullptr) | |||||
return false; | |||||
auto image_resource = dynamic_cast<ResourceImageData*>(resource); | |||||
if (image_resource == nullptr) | |||||
{ | { | ||||
last_codec = codec; | |||||
if (codec->Load(this, path)) | |||||
{ | |||||
msg::info("Image::Load: Codec %s succesfully loaded %s.\n", codec->GetName(), path); | |||||
return true; | |||||
} | |||||
delete image_resource; | |||||
return false; | |||||
} | } | ||||
//Log error, because we shouldn't be here | |||||
msg::error("Image::Load: Last codec %s, Error loading image %s.\n", last_codec->GetName(), path); | |||||
return false; | |||||
Copy(*image_resource->m_image); | |||||
delete image_resource; | |||||
return true; | |||||
} | } | ||||
bool Image::Save(char const *path) | bool Image::Save(char const *path) | ||||
{ | { | ||||
ImageCodec* last_codec = nullptr; | |||||
for (auto codec : g_image_loader.m_codecs) | |||||
{ | |||||
last_codec = codec; | |||||
if (codec->Save(this, path)) | |||||
{ | |||||
msg::info("Image::Save: Codec %s succesfully saved %s.\n", codec->GetName(), path); | |||||
return true; | |||||
} | |||||
} | |||||
//Log error, because we shouldn't be here | |||||
msg::error("Image::Save: Last codec %s, Error saving image %s.\n", last_codec->GetName(), path); | |||||
return false; | |||||
auto data = new ResourceImageData(new Image(*this)); | |||||
auto result = ResourceLoader::Save(path, data); | |||||
delete data; | |||||
return result; | |||||
} | } | ||||
ivec2 Image::GetSize() const | ivec2 Image::GetSize() const | ||||
@@ -281,12 +208,5 @@ void Image::Unlock(void const *pixels) | |||||
ASSERT(pixels == m_data->m_pixels[(int)m_data->m_format]->data()); | ASSERT(pixels == m_data->m_pixels[(int)m_data->m_format]->data()); | ||||
} | } | ||||
bool Image::RetrieveTiles(array<ivec2, ivec2>& tiles) const | |||||
{ | |||||
/* TODO: re-implement this */ | |||||
//return m_data->m_codecdata->RetrieveTiles(tiles); | |||||
return false; | |||||
} | |||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -0,0 +1,57 @@ | |||||
// | |||||
// Lol Engine | |||||
// | |||||
// Copyright: (c) 2016—2017 Sam Hocevar <sam@hocevar.net> | |||||
// Copyright © 2016—2017 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
// | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// | |||||
#pragma once | |||||
// | |||||
// The ResourceCodecData class | |||||
// ------------------------ | |||||
// | |||||
namespace lol | |||||
{ | |||||
class ResourceCodec | |||||
{ | |||||
public: | |||||
virtual char const *GetName() { return "<ResourceCodec>"; } | |||||
virtual ResourceCodecData* Load(char const *path) = 0; | |||||
virtual bool Save(char const *path, ResourceCodecData* data) = 0; | |||||
/* TODO: this should become more fine-grained */ | |||||
int m_priority; | |||||
}; | |||||
#define REGISTER_IMAGE_CODEC(name) \ | |||||
extern ResourceCodec *Register##name(); \ | |||||
{ \ | |||||
/* Insert image codecs in a sorted list */ \ | |||||
ResourceCodec *codec = Register##name(); \ | |||||
int i = 0, prio = codec->m_priority; \ | |||||
for ( ; i < codeclist.count(); ++i) \ | |||||
{ \ | |||||
if (codeclist[i]->m_priority <= prio) \ | |||||
break; \ | |||||
} \ | |||||
codeclist.insert(codec, i); \ | |||||
} | |||||
#define DECLARE_IMAGE_CODEC(name, priority) \ | |||||
ResourceCodec *Register##name() \ | |||||
{ \ | |||||
ResourceCodec *ret = new name(); \ | |||||
ret->m_priority = priority; \ | |||||
return ret; \ | |||||
} | |||||
} /* namespace lol */ | |||||
@@ -0,0 +1,121 @@ | |||||
// | |||||
// Lol Engine | |||||
// | |||||
// Copyright © 2016—2017 Sam Hocevar <sam@hocevar.net> | |||||
// Copyright © 2016—2017 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
// | |||||
// Lol Engine is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | |||||
#include <lol/engine-internal.h> | |||||
#include "resource-private.h" | |||||
#include <algorithm> /* for std::swap */ | |||||
namespace lol | |||||
{ | |||||
/* HACK: We cannot make this an ImageLoader member function, because the | |||||
* REGISTER_IMAGE_CODEC macro forward-declares free functions from | |||||
* the "lol" namespace. An apparent bug in Visual Studio's compiler | |||||
* makes it think these functions are actually in the top-level | |||||
* namespace when the forward declaration is in a class member function. | |||||
* To avoid the problem, we make the forward declaration in a free | |||||
* function. | |||||
* The bug was reported to Microsoft and fixed by them, but the fix | |||||
* is not yet available. | |||||
* https://connect.microsoft.com/VisualStudio/feedback/details/730878/ */ | |||||
static bool RegisterAllCodecs(array<ResourceCodec *> &codeclist) | |||||
{ | |||||
#if defined __ANDROID__ | |||||
REGISTER_IMAGE_CODEC(AndroidImageCodec) | |||||
#endif | |||||
#if defined LOL_USE_GDIPLUS | |||||
REGISTER_IMAGE_CODEC(GdiPlusImageCodec) | |||||
#endif | |||||
#if defined __APPLE__ && defined __MACH__ && defined __arm__ | |||||
REGISTER_IMAGE_CODEC(IosImageCodec) | |||||
#endif | |||||
#if defined LOL_USE_SDL_IMAGE | |||||
REGISTER_IMAGE_CODEC(SdlImageCodec) | |||||
#endif | |||||
#if defined LOL_USE_IMLIB2 | |||||
REGISTER_IMAGE_CODEC(Imlib2ImageCodec) | |||||
#endif | |||||
REGISTER_IMAGE_CODEC(ZedImageCodec) | |||||
REGISTER_IMAGE_CODEC(ZedPaletteImageCodec) | |||||
REGISTER_IMAGE_CODEC(OricImageCodec) | |||||
REGISTER_IMAGE_CODEC(DummyImageCodec) | |||||
return true; | |||||
} | |||||
/* | |||||
* Our static image loader | |||||
*/ | |||||
static class StaticResourceLoader | |||||
{ | |||||
friend class ResourceLoader; | |||||
public: | |||||
inline StaticResourceLoader() | |||||
{ | |||||
RegisterAllCodecs(m_codecs); | |||||
} | |||||
private: | |||||
array<ResourceCodec *> m_codecs; | |||||
} | |||||
g_resource_loader; | |||||
/* | |||||
* The public resource loader | |||||
*/ | |||||
ResourceCodecData* ResourceLoader::Load(char const *path) | |||||
{ | |||||
ResourceCodec* last_codec = nullptr; | |||||
for (auto codec : g_resource_loader.m_codecs) | |||||
{ | |||||
last_codec = codec; | |||||
auto data = codec->Load(path); | |||||
if (data != nullptr) | |||||
{ | |||||
msg::info("Image::Load: Codec %s succesfully loaded %s.\n", codec->GetName(), path); | |||||
return data; | |||||
} | |||||
} | |||||
//Log error, because we shouldn't be here | |||||
msg::error("Image::Load: Last codec %s, Error loading resource %s.\n", last_codec->GetName(), path); | |||||
return nullptr; | |||||
} | |||||
bool ResourceLoader::Save(char const *path, ResourceCodecData* data) | |||||
{ | |||||
ResourceCodec* last_codec = nullptr; | |||||
for (auto codec : g_resource_loader.m_codecs) | |||||
{ | |||||
last_codec = codec; | |||||
if (codec->Save(path, data)) | |||||
{ | |||||
msg::info("Image::Save: Codec %s succesfully saved %s.\n", codec->GetName(), path); | |||||
return true; | |||||
} | |||||
} | |||||
//Log error, because we shouldn't be here | |||||
msg::error("Image::Save: Last codec %s, Error saving resource %s.\n", last_codec->GetName(), path); | |||||
return false; | |||||
} | |||||
} /* namespace lol */ | |||||
@@ -148,6 +148,7 @@ | |||||
<ClCompile Include="image\noise.cpp" /> | <ClCompile Include="image\noise.cpp" /> | ||||
<ClCompile Include="image\pixel.cpp" /> | <ClCompile Include="image\pixel.cpp" /> | ||||
<ClCompile Include="image\resample.cpp" /> | <ClCompile Include="image\resample.cpp" /> | ||||
<ClCompile Include="image\resource.cpp" /> | |||||
<ClCompile Include="input\controller.cpp" /> | <ClCompile Include="input\controller.cpp" /> | ||||
<ClCompile Include="input\input.cpp" /> | <ClCompile Include="input\input.cpp" /> | ||||
<ClCompile Include="light.cpp" /> | <ClCompile Include="light.cpp" /> | ||||
@@ -238,6 +239,7 @@ | |||||
<ClInclude Include="forge.h" /> | <ClInclude Include="forge.h" /> | ||||
<ClInclude Include="gradient.h" /> | <ClInclude Include="gradient.h" /> | ||||
<ClInclude Include="image\image-private.h" /> | <ClInclude Include="image\image-private.h" /> | ||||
<ClInclude Include="image\resource-private.h" /> | |||||
<ClInclude Include="input\controller.h" /> | <ClInclude Include="input\controller.h" /> | ||||
<ClInclude Include="input\input.h" /> | <ClInclude Include="input\input.h" /> | ||||
<ClInclude Include="input\input_internal.h" /> | <ClInclude Include="input\input_internal.h" /> | ||||
@@ -285,6 +287,7 @@ | |||||
<ClInclude Include="lol\image\image.h" /> | <ClInclude Include="lol\image\image.h" /> | ||||
<ClInclude Include="lol\image\movie.h" /> | <ClInclude Include="lol\image\movie.h" /> | ||||
<ClInclude Include="lol\image\pixel.h" /> | <ClInclude Include="lol\image\pixel.h" /> | ||||
<ClInclude Include="lol\image\resource.h" /> | |||||
<ClInclude Include="lol\math\all.h" /> | <ClInclude Include="lol\math\all.h" /> | ||||
<ClInclude Include="lol\math\arraynd.h" /> | <ClInclude Include="lol\math\arraynd.h" /> | ||||
<ClInclude Include="lol\math\bigint.h" /> | <ClInclude Include="lol\math\bigint.h" /> | ||||
@@ -397,4 +400,4 @@ | |||||
<ImportGroup Label="ExtensionTargets"> | <ImportGroup Label="ExtensionTargets"> | ||||
<Import Project="$(LolDir)\build\msbuild\lolfx.targets" /> | <Import Project="$(LolDir)\build\msbuild\lolfx.targets" /> | ||||
</ImportGroup> | </ImportGroup> | ||||
</Project> | |||||
</Project> |
@@ -15,5 +15,6 @@ | |||||
#include <lol/image/pixel.h> | #include <lol/image/pixel.h> | ||||
#include <lol/image/color.h> | #include <lol/image/color.h> | ||||
#include <lol/image/image.h> | #include <lol/image/image.h> | ||||
#include <lol/image/resource.h> | |||||
#include <lol/image/movie.h> | #include <lol/image/movie.h> | ||||
@@ -106,9 +106,6 @@ public: | |||||
template<typename T> | template<typename T> | ||||
void Unlock2D(array2d<T> const &); | void Unlock2D(array2d<T> const &); | ||||
/* XXX: this does not belong here */ | |||||
bool RetrieveTiles(array<ivec2, ivec2>& tiles) const; | |||||
/* Image processing kernels */ | /* Image processing kernels */ | ||||
static array2d<float> BayerKernel(ivec2 size); | static array2d<float> BayerKernel(ivec2 size); | ||||
static array2d<float> HalftoneKernel(ivec2 size); | static array2d<float> HalftoneKernel(ivec2 size); | ||||
@@ -0,0 +1,74 @@ | |||||
// | |||||
// Lol Engine | |||||
// | |||||
// Copyright © 2016—2017 Sam Hocevar <sam@hocevar.net> | |||||
// Copyright © 2016—2017 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
// | |||||
// Lol Engine is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | |||||
#pragma once | |||||
// | |||||
// The Resource class | |||||
// --------------- | |||||
// | |||||
#include <lol/math/arraynd.h> | |||||
#include <lol/math/vector.h> | |||||
#include <lol/math/geometry.h> | |||||
#include <lol/image/pixel.h> | |||||
namespace lol | |||||
{ | |||||
//ResourceCodecData ----------------------------------------------------------- | |||||
class ResourceCodecData | |||||
{ | |||||
public: | |||||
ResourceCodecData() { } | |||||
virtual ~ResourceCodecData() { } | |||||
}; | |||||
//ResourceImageData ----------------------------------------------------------- | |||||
class ResourceImageData : public ResourceCodecData | |||||
{ | |||||
public: | |||||
ResourceImageData(Image* image) | |||||
{ | |||||
m_image = image; | |||||
} | |||||
virtual ~ResourceImageData() | |||||
{ | |||||
if (m_image) | |||||
delete m_image; | |||||
} | |||||
Image* m_image = nullptr; | |||||
}; | |||||
//ResourceImageData ----------------------------------------------------------- | |||||
class ResourceTilesetData : public ResourceImageData | |||||
{ | |||||
public: | |||||
ResourceTilesetData(Image* image) | |||||
: ResourceImageData(image) | |||||
{ } | |||||
array<ivec2, ivec2> m_tiles; | |||||
}; | |||||
//ResourceLoader -------------------------------------------------------------- | |||||
class ResourceLoader | |||||
{ | |||||
public: | |||||
static ResourceCodecData* Load(char const *path); | |||||
static bool Save(char const *path, ResourceCodecData* data); | |||||
}; | |||||
} /* namespace lol */ | |||||
@@ -232,17 +232,17 @@ protected: | |||||
template <typename TLuaClass> static int Store(lua_State * l); | template <typename TLuaClass> static int Store(lua_State * l); | ||||
template <typename TLuaClass> static int Del(lua_State * l); | template <typename TLuaClass> static int Del(lua_State * l); | ||||
//------------------------------------------------------------------------- | //------------------------------------------------------------------------- | ||||
template <typename TLuaClass> static int ToString(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpAdd(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpSubstract(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpMultiply(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpDivide(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpModulo(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpUnaryNeg(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpConcat(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int CmpEqual(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int CmpLessThan(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int CmpLessEqual(lua_State* l) { ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int ToString(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpAdd(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpSubstract(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpMultiply(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpDivide(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpModulo(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpUnaryNeg(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int OpConcat(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int CmpEqual(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int CmpLessThan(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
template <typename TLuaClass> static int CmpLessEqual(lua_State* l) { UNUSED(l); ASSERT(false); return 0; } | |||||
}; | }; | ||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
@@ -334,7 +334,7 @@ private: | |||||
} | } | ||||
public: | public: | ||||
//------------------------------------------------------------------------- | |||||
//------------------------------------------------------------------------- | |||||
template<typename T> T Get() { return Get(InnerDefault<T>(), false); } | template<typename T> T Get() { return Get(InnerDefault<T>(), false); } | ||||
template<typename T> T Get(T default_value) { return Get(default_value, true); } | template<typename T> T Get(T default_value) { return Get(default_value, true); } | ||||
template<typename E> SafeEnum<E> GetEnum() { return GetEnum(InnerDefaultSafeEnum<E>(), false); } | template<typename E> SafeEnum<E> GetEnum() { return GetEnum(InnerDefaultSafeEnum<E>(), false); } | ||||
@@ -373,7 +373,7 @@ protected: | |||||
//------------------------------------------------------------------------- | //------------------------------------------------------------------------- | ||||
#define INNER_ERROR "Your type is not implemented. For pointers, use LuaPtr<MyType>()" | #define INNER_ERROR "Your type is not implemented. For pointers, use LuaPtr<MyType>()" | ||||
template<typename T> T InnerDefault() { return T(0); } | template<typename T> T InnerDefault() { return T(0); } | ||||
template<typename T> bool InnerIsValid() { ASSERT(false, INNER_ERROR); return false; } | |||||
template<typename T> bool InnerIsValid() { ASSERT(false, INNER_ERROR); return false; } | |||||
template<typename T> T InnerGet(T value) { UNUSED(value); ASSERT(false, INNER_ERROR); return InnerDefault<T>(); } | template<typename T> T InnerGet(T value) { UNUSED(value); ASSERT(false, INNER_ERROR); return InnerDefault<T>(); } | ||||
template<typename T> int InnerPush(T value) { UNUSED(value); ASSERT(false, INNER_ERROR); return 0; } | template<typename T> int InnerPush(T value) { UNUSED(value); ASSERT(false, INNER_ERROR); return 0; } | ||||
@@ -398,6 +398,7 @@ protected: | |||||
{ | { | ||||
P** data = (P**)lua_newuserdata(m_state, sizeof(P*)); | P** data = (P**)lua_newuserdata(m_state, sizeof(P*)); | ||||
*data = value.m_value; | *data = value.m_value; | ||||
return 1; | |||||
} | } | ||||
#endif //STACK_STRING | #endif //STACK_STRING | ||||
@@ -440,7 +441,7 @@ private: | |||||
#define LOLUA_DECLARE_BEGIN(LUA_FUNC_NAME, INSTANCE_GET) \ | #define LOLUA_DECLARE_BEGIN(LUA_FUNC_NAME, INSTANCE_GET) \ | ||||
static int LUA_FUNC_NAME(lua_State* l) \ | static int LUA_FUNC_NAME(lua_State* l) \ | ||||
{ \ | { \ | ||||
auto s = LuaStack::Begin(l); \ | |||||
auto s = Lolua::Stack::Begin(l); \ | |||||
auto o = s.INSTANCE_GET; | auto o = s.INSTANCE_GET; | ||||
#define LOLUA_DECLARE_VARS(...) \ | #define LOLUA_DECLARE_VARS(...) \ | ||||
@@ -472,7 +473,7 @@ private: | |||||
#define LOLUA_DECLARE_RETURN_METHOD_ARGS(LUA_FUNC_NAME, INSTANCE_GET, INSTANCE_CALL, ...) \ | #define LOLUA_DECLARE_RETURN_METHOD_ARGS(LUA_FUNC_NAME, INSTANCE_GET, INSTANCE_CALL, ...) \ | ||||
static int LUA_FUNC_NAME(lua_State* l) \ | static int LUA_FUNC_NAME(lua_State* l) \ | ||||
{ \ | { \ | ||||
auto s = LuaStack::Begin(l); \ | |||||
auto s = Lolua::Stack::Begin(l); \ | |||||
auto o = s.INSTANCE_GET; \ | auto o = s.INSTANCE_GET; \ | ||||
LOL_CALL(LOL_CAT(LOLUA_VAR_, LOL_CALL(LOL_COUNT_TO_12, (__VA_ARGS__))), (__VA_ARGS__)) \ | LOL_CALL(LOL_CAT(LOLUA_VAR_, LOL_CALL(LOL_COUNT_TO_12, (__VA_ARGS__))), (__VA_ARGS__)) \ | ||||
s << o->INSTANCE_CALL(LOL_CALL(LOL_CAT(LOLUA_ARG_, LOL_CALL(LOL_COUNT_TO_12, (__VA_ARGS__))), (__VA_ARGS__))); \ | s << o->INSTANCE_CALL(LOL_CALL(LOL_CAT(LOLUA_ARG_, LOL_CALL(LOL_COUNT_TO_12, (__VA_ARGS__))), (__VA_ARGS__))); \ | ||||
@@ -536,7 +537,7 @@ template<> inline int Stack::InnerPush<uint64_t>(uint64_t value) { lua_pushi | |||||
template<> inline bool Stack::InnerIsValid<int32_t>() { return !!lua_isnumber(m_state, m_index); } | template<> inline bool Stack::InnerIsValid<int32_t>() { return !!lua_isnumber(m_state, m_index); } | ||||
template<> inline int32_t Stack::InnerGet<int32_t>(int32_t value) { UNUSED(value); return (int32_t)lua_tointeger(m_state, m_index++); } | template<> inline int32_t Stack::InnerGet<int32_t>(int32_t value) { UNUSED(value); return (int32_t)lua_tointeger(m_state, m_index++); } | ||||
template<> inline int Stack::InnerPush<int32_t>(int32_t value) { lua_pushinteger(m_state, (lua_Integer)value); return 1; } | template<> inline int Stack::InnerPush<int32_t>(int32_t value) { lua_pushinteger(m_state, (lua_Integer)value); return 1; } | ||||
#endif STACK_INT32 | |||||
#endif // STACK_INT32 | |||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
#ifndef STACK_UINT32 | #ifndef STACK_UINT32 | ||||
@@ -564,7 +565,7 @@ template<> inline int Stack::InnerPush<vec3>(vec3 value) { return (InnerPush<flo | |||||
template<> inline bool Stack::InnerIsValid<vec4>() { return InnerIsValid<float>(); } | template<> inline bool Stack::InnerIsValid<vec4>() { return InnerIsValid<float>(); } | ||||
template<> inline vec4 Stack::InnerGet<vec4>(vec4 value) { return vec4(InnerGet<float>(value.x), Get<float>(value.y, true), Get<float>(value.z, true), Get<float>(value.w, true)); } | template<> inline vec4 Stack::InnerGet<vec4>(vec4 value) { return vec4(InnerGet<float>(value.x), Get<float>(value.y, true), Get<float>(value.z, true), Get<float>(value.w, true)); } | ||||
template<> inline int Stack::InnerPush<vec4>(vec4 value) { return (InnerPush<float>(value.x) + InnerPush<float>(value.y) + InnerPush<float>(value.z) + InnerPush<float>(value.w)); } | template<> inline int Stack::InnerPush<vec4>(vec4 value) { return (InnerPush<float>(value.x) + InnerPush<float>(value.y) + InnerPush<float>(value.z) + InnerPush<float>(value.w)); } | ||||
#endif STACK_VEC4 | |||||
#endif // STACK_VEC4 | |||||
#endif //REGION_STACK_VAR | #endif //REGION_STACK_VAR | ||||
@@ -585,7 +586,7 @@ public: | |||||
T1 GET_NAME(String const &name) \ | T1 GET_NAME(String const &name) \ | ||||
{ \ | { \ | ||||
lua_getglobal(m_lua_state, name.C()); \ | lua_getglobal(m_lua_state, name.C()); \ | ||||
auto stack = LuaStack::Begin(m_lua_state, -1); \ | |||||
auto stack = Lolua::Stack::Begin(m_lua_state, -1); \ | |||||
auto result = stack.GET_NAME<T0>(); \ | auto result = stack.GET_NAME<T0>(); \ | ||||
lua_pop(m_lua_state, 1); \ | lua_pop(m_lua_state, 1); \ | ||||
return result; \ | return result; \ | ||||
@@ -615,7 +616,7 @@ private: | |||||
template <typename TLuaClass> | template <typename TLuaClass> | ||||
int ObjectHelper::Store(lua_State * l) | int ObjectHelper::Store(lua_State * l) | ||||
{ | { | ||||
auto stack = LuaStack::Begin(l); | |||||
auto stack = Lolua::Stack::Begin(l); | |||||
TLuaClass* obj = stack.GetPtr<TLuaClass>(); | TLuaClass* obj = stack.GetPtr<TLuaClass>(); | ||||
ASSERT(obj); | ASSERT(obj); | ||||
Loader::StoreObject(l, obj); | Loader::StoreObject(l, obj); | ||||
@@ -625,7 +626,7 @@ int ObjectHelper::Store(lua_State * l) | |||||
template <typename TLuaClass> | template <typename TLuaClass> | ||||
int ObjectHelper::Del(lua_State * l) | int ObjectHelper::Del(lua_State * l) | ||||
{ | { | ||||
auto stack = LuaStack::Begin(l); | |||||
auto stack = Lolua::Stack::Begin(l); | |||||
TLuaClass* obj = stack.GetPtr<TLuaClass>(); | TLuaClass* obj = stack.GetPtr<TLuaClass>(); | ||||
ASSERT(obj); | ASSERT(obj); | ||||
delete obj; | delete obj; | ||||
@@ -278,10 +278,10 @@ void SdlInputData::Tick(float seconds) | |||||
# endif | # endif | ||||
{ | { | ||||
//Lock management | //Lock management | ||||
# if defined SDLOL_CapsLock && defined SDLOL_ScrollLock && defined SDLOL_NumLockClear | |||||
case SDLOL_CapsLock: | case SDLOL_CapsLock: | ||||
case SDLOL_ScrollLock: | case SDLOL_ScrollLock: | ||||
case SDLOL_NumLockClear: | case SDLOL_NumLockClear: | ||||
# if defined SDLOL_CapsLock && defined SDLOL_ScrollLock && defined SDLOL_NumLockClear | |||||
//Update status on key down only | //Update status on key down only | ||||
if (event.type == SDL_KEYDOWN) | if (event.type == SDL_KEYDOWN) | ||||
{ | { | ||||
@@ -104,6 +104,13 @@ void init(int argc, char *argv[], | |||||
rootdir += "../src/"; /* FIXME: use SEPARATOR? */ | rootdir += "../src/"; /* FIXME: use SEPARATOR? */ | ||||
add_data_dir(rootdir); | add_data_dir(rootdir); | ||||
/* This data dir is for submodule support stuff */ | |||||
rootdir = solutiondir; | |||||
if (rootdir.count() && rootdir.last() != SEPARATOR) | |||||
rootdir += SEPARATOR; | |||||
rootdir += "./lol/src/"; /* FIXME: use SEPARATOR? */ | |||||
add_data_dir(rootdir); | |||||
/* This data dir is for project-specific stuff */ | /* This data dir is for project-specific stuff */ | ||||
rootdir = projectdir; | rootdir = projectdir; | ||||
if (rootdir.count() && rootdir.last() != SEPARATOR) | if (rootdir.count() && rootdir.last() != SEPARATOR) | ||||
@@ -57,7 +57,19 @@ TextureImage::~TextureImage() | |||||
void TextureImage::Init(char const *path) | void TextureImage::Init(char const *path) | ||||
{ | { | ||||
Init(path, new Image(path)); | |||||
Init(path, ResourceLoader::Load(path)); | |||||
} | |||||
void TextureImage::Init(char const *path, ResourceCodecData* loaded_data) | |||||
{ | |||||
//Load image if available | |||||
auto image_data = dynamic_cast<ResourceImageData*>(loaded_data); | |||||
if (image_data != nullptr) | |||||
{ | |||||
Init(path, new Image(*image_data->m_image)); | |||||
} | |||||
delete image_data; | |||||
} | } | ||||
void TextureImage::Init(char const *path, Image* image) | void TextureImage::Init(char const *path, Image* image) | ||||
@@ -18,6 +18,7 @@ | |||||
// zero, the texture is freed. | // zero, the texture is freed. | ||||
// | // | ||||
#include <lol/image/resource.h> | |||||
#include <lol/image/image.h> | #include <lol/image/image.h> | ||||
#include <lol/gpu/texture.h> | #include <lol/gpu/texture.h> | ||||
@@ -43,6 +44,7 @@ public: | |||||
protected: | protected: | ||||
void Init(char const *path); | void Init(char const *path); | ||||
virtual void Init(char const *path, ResourceCodecData* loaded_data); | |||||
virtual void Init(char const *path, Image* image); | virtual void Init(char const *path, Image* image); | ||||
protected: | protected: | ||||
@@ -46,25 +46,25 @@ protected: | |||||
*/ | */ | ||||
TileSet::TileSet(char const *path) | TileSet::TileSet(char const *path) | ||||
: TextureImage(path), | |||||
: m_tileset_data(new TileSetData()), | |||||
m_palette(nullptr), | |||||
TextureImage(path) | |||||
{ | |||||
} | |||||
TileSet::TileSet(char const *path, Image* image) | |||||
: TextureImage(path, image), | |||||
m_tileset_data(new TileSetData()), | m_tileset_data(new TileSetData()), | ||||
m_palette(nullptr) | m_palette(nullptr) | ||||
{ | { | ||||
array<ivec2, ivec2> tiles; | |||||
if (m_data->m_image->RetrieveTiles(tiles)) | |||||
for (int i = 0; i < tiles.count(); i++) | |||||
define_tile(ibox2(tiles[0].m1, tiles[0].m1 + tiles[0].m2)); | |||||
} | } | ||||
TileSet::TileSet(char const *path, Image* image) | |||||
: TextureImage(path, image), | |||||
TileSet::TileSet(char const *path, Image* image, array<ivec2, ivec2>& tiles) | |||||
: TextureImage(path, image), | |||||
m_tileset_data(new TileSetData()), | m_tileset_data(new TileSetData()), | ||||
m_palette(nullptr) | m_palette(nullptr) | ||||
{ | { | ||||
array<ivec2, ivec2> tiles; | |||||
if (m_data->m_image->RetrieveTiles(tiles)) | |||||
for (int i = 0; i < tiles.count(); i++) | |||||
define_tile(ibox2(tiles[0].m1, tiles[0].m1 + tiles[0].m2)); | |||||
define_tile(tiles); | |||||
} | } | ||||
TileSet::TileSet(char const *path, ivec2 size, ivec2 count) | TileSet::TileSet(char const *path, ivec2 size, ivec2 count) | ||||
@@ -118,6 +118,20 @@ TileSet::~TileSet() | |||||
delete m_tileset_data; | delete m_tileset_data; | ||||
} | } | ||||
void TileSet::Init(char const *path, ResourceCodecData* loaded_data) | |||||
{ | |||||
//Load tileset if available | |||||
auto tileset_data = dynamic_cast<ResourceTilesetData*>(loaded_data); | |||||
if (tileset_data != nullptr) | |||||
{ | |||||
define_tile(tileset_data->m_tiles); | |||||
} | |||||
m_data->m_name = String("<tileset> ") + path; | |||||
super::Init(path, loaded_data); | |||||
} | |||||
void TileSet::Init(char const *path, Image* image) | void TileSet::Init(char const *path, Image* image) | ||||
{ | { | ||||
super::Init(path, image); | super::Init(path, image); | ||||
@@ -132,6 +146,11 @@ char const *TileSet::GetName() | |||||
} | } | ||||
//New methods ----------------------------------------------------------------- | //New methods ----------------------------------------------------------------- | ||||
void TileSet::clear_all() | |||||
{ | |||||
m_tileset_data->m_tiles.empty(); | |||||
} | |||||
int TileSet::define_tile(ibox2 rect) | int TileSet::define_tile(ibox2 rect) | ||||
{ | { | ||||
m_tileset_data->m_tiles.push(rect, | m_tileset_data->m_tiles.push(rect, | ||||
@@ -152,6 +171,18 @@ void TileSet::define_tile(ivec2 count) | |||||
} | } | ||||
} | } | ||||
void TileSet::define_tile(array<ibox2>& tiles) | |||||
{ | |||||
for (int i = 0; i < tiles.count(); i++) | |||||
define_tile(tiles[i]); | |||||
} | |||||
void TileSet::define_tile(array<ivec2, ivec2>& tiles) | |||||
{ | |||||
for (int i = 0; i < tiles.count(); i++) | |||||
define_tile(ibox2(tiles[i].m1, tiles[i].m1 + tiles[i].m2)); | |||||
} | |||||
int TileSet::GetTileCount() const | int TileSet::GetTileCount() const | ||||
{ | { | ||||
return m_tileset_data->m_tiles.count(); | return m_tileset_data->m_tiles.count(); | ||||
@@ -43,6 +43,7 @@ class TileSet : public TextureImage | |||||
public: | public: | ||||
TileSet(char const *path); | TileSet(char const *path); | ||||
TileSet(char const *path, Image* image); | TileSet(char const *path, Image* image); | ||||
TileSet(char const *path, Image* image, array<ivec2, ivec2>& tiles); | |||||
/* Old style: path to PNG file */ | /* Old style: path to PNG file */ | ||||
TileSet(char const *path, ivec2 size, ivec2 count); | TileSet(char const *path, ivec2 size, ivec2 count); | ||||
@@ -51,6 +52,7 @@ public: | |||||
virtual ~TileSet(); | virtual ~TileSet(); | ||||
protected: | protected: | ||||
virtual void Init(char const *path, ResourceCodecData* loaded_data); | |||||
virtual void Init(char const *path, Image* image); | virtual void Init(char const *path, Image* image); | ||||
public: | public: | ||||
@@ -58,8 +60,11 @@ public: | |||||
virtual char const *GetName(); | virtual char const *GetName(); | ||||
/* New methods */ | /* New methods */ | ||||
void clear_all(); | |||||
int define_tile(ibox2 rect); | int define_tile(ibox2 rect); | ||||
void define_tile(ivec2 count); | void define_tile(ivec2 count); | ||||
void define_tile(array<ibox2>& tiles); | |||||
void define_tile(array<ivec2, ivec2>& tiles); | |||||
int GetTileCount() const; | int GetTileCount() const; | ||||
ivec2 GetTileSize(int tileid) const; | ivec2 GetTileSize(int tileid) const; | ||||
ibox2 GetTilePixel(int tileid) const; | ibox2 GetTilePixel(int tileid) const; | ||||