Browse Source

Added bunch of stuff on threads and images.

undefined
Benjamin ‘Touky’ Huet Sam Hocevar <sam@hocevar.net> 10 years ago
parent
commit
3d4b3d53c3
15 changed files with 789 additions and 31 deletions
  1. +295
    -0
      src/image/codec/zed-image.cpp
  2. +99
    -0
      src/image/codec/zed-palette-image.cpp
  3. +1
    -0
      src/image/image-private.h
  4. +57
    -4
      src/image/image.cpp
  5. +2
    -0
      src/input/input.cpp
  6. +3
    -0
      src/lol/image/image.h
  7. +6
    -2
      src/lol/sys/file.h
  8. +120
    -0
      src/lol/sys/thread.h
  9. +2
    -0
      src/lolcore.vcxproj
  10. +5
    -2
      src/platform/sdl/sdlinput.cpp
  11. +86
    -22
      src/sys/file.cpp
  12. +36
    -0
      src/tiler.cpp
  13. +4
    -0
      src/tiler.h
  14. +69
    -1
      src/tileset.cpp
  15. +4
    -0
      src/tileset.h

+ 295
- 0
src/image/codec/zed-image.cpp View File

@@ -0,0 +1,295 @@
//
// Lol Engine
//
// Copyright: (c) 2014 Benjamin Huet <huet.benjamin@gmail.com>
// 2014 Sam Hocevar <sam@hocevar.net>
// 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.
//

#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#include "core.h"
#include "../../image/image-private.h"

using namespace std;

namespace lol
{

/*
* Image implementation class
*/

DECLARE_IMAGE_LOADER(ZedImageData, 0)
{
public:
virtual bool Open(char const *);
virtual bool Close();

virtual uint8_t *GetData() const;
virtual bool RetrieveTiles(Array<ivec2, ivec2>& tiles)
{
tiles += m_tiles;
m_tiles.Empty();
return true;
}

private:
uint8_t *m_pixels;
//<Pos, Size>
Array<ivec2, ivec2> m_tiles;
};

/*
* Public Image class
*/

bool ZedImageData::Open(char const *path)
{
if (!lol::String(path).EndsWith(".RSC"))
return false;

File file;
file.Open(path, FileAccess::Read, true);

//Put file in memory
long file_size = file.GetSize();
Array<uint8_t> file_buffer;
file_buffer.Resize(file_size);
file.Read((uint8_t*)&file_buffer[0], file_size);
file.Close();

//Get FileCount
uint32_t file_pos = 0;
uint16_t file_count = 0;
file_count = *((uint16_t*)(&file_buffer[file_pos]));
file_pos += sizeof(uint16_t);

Array<long int> file_offset;
file_offset.Resize(file_count);
//Get all the file offsets
for (int i = 0; i < file_count; i++)
{
file_offset[i] = *((long int*)(&file_buffer[file_pos]));
file_pos += sizeof(long int);
}
file_offset << file_size;

m_tiles.Reserve(file_count);
struct CompactSecondary
{
CompactSecondary(int32_t size) { m_size = size; }
int32_t m_size;
Array<int32_t> m_tiles;
};
struct CompactMain
{
CompactMain(int32_t size) { m_size = size; m_count = 0; }
int32_t m_size;
int32_t m_count;
Array<CompactSecondary> m_secondary;
};
struct Compacter2d
{
void PowSetup(int32_t start, int32_t count)
{
for (int i = 0; i < count; i++)
{
m_primary << CompactMain(start << i);
for (int j = 0; j < count; j++)
m_primary.Last().m_secondary << CompactSecondary(start << j);
}
}
void StepSetup(int32_t start, int32_t interval, int32_t count)
{
for (int i = 0; i < count; i++)
{
m_primary << CompactMain(start + interval * i);
for (int j = 0; j < count; j++)
m_primary.Last().m_secondary << CompactSecondary(start + interval * j);
}
}
void CustomSetup(Array<int32_t> custom_list)
{
for (int i = 0; i < custom_list.Count(); i++)
{
m_primary << CompactMain(custom_list[i]);
for (int j = 0; j < custom_list.Count(); j++)
m_primary.Last().m_secondary << CompactSecondary(custom_list[j]);
}
}
void Store(int32_t tile, ivec2 size)
{
for (int i = 0; i < m_primary.Count(); i++)
{
if (size.y <= m_primary[i].m_size || i == m_primary.Count() - 1)
{
for (int j = 0; j < m_primary[i].m_secondary.Count(); j++)
{
if (size.x <= m_primary[i].m_secondary[j].m_size || j == m_primary[i].m_secondary.Count() - 1)
{
m_primary[i].m_secondary[j].m_tiles << tile;
m_primary[i].m_count++;
break;
}
}
break;
}
}
}
Array<CompactMain> m_primary;
};

Compacter2d compacter;
compacter.StepSetup(8, 8, 10);

uint32_t total_size = 0;
Array<uint8_t> file_convert;
file_convert.Reserve(file_size);
Array<ivec2> available_sizes;
for (int i = 0; i < file_count; i++)
{
file_pos = file_offset[i];

//Get image size
uint8_t size_x = 0;
uint8_t size_y = 0;
size_y = file_buffer[file_pos++];
size_x = file_buffer[file_pos++];

//special tweak
size_x *= 8;
total_size += (size_x * size_y);

//Prepare read
uint32_t header_length = (size_y + 5) & 0xFC;
uint32_t data_length = (file_offset[i+1] - file_offset[i]) - header_length;
uint32_t data_pos = file_offset[i] + header_length;

//Prepare buffer and tiles infos
int32_t convert_pos = file_convert.Count();
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));
file_convert.Resize(convert_pos + data_length);

ivec2 size_16 = size;
int32_t s_16 = 8;
while (1)
{
if (size_16.x <= s_16)
{
size_16.x = s_16;
break;
}
s_16 <<= 1;
}
s_16 = 8;
while (1)
{
if (size_16.y <= s_16)
{
size_16.y = s_16;
break;
}
s_16 <<= 1;
}
int j = 0;
for (; j < available_sizes.Count(); j++)
if (available_sizes[j] == size_16)
break;
if (j >= available_sizes.Count())
available_sizes << size_16;

//Retrieve actual datas
file_pos = data_pos;
memcpy(&file_convert[convert_pos], &file_buffer[file_pos], data_length);
file_pos += data_length;
}

int32_t tex_sqrt = (int32_t)lol::sqrt((float)total_size);
int32_t tex_size = 2;
while (tex_size < tex_sqrt)
tex_size <<= 1;

//Prepare final imqge
m_size = ivec2(tex_size);
m_format = PixelFormat::Y_8;
m_pixels = new uint8_t[tex_size * tex_size * 1 * sizeof(*m_pixels)];
uint8_t *image = m_pixels;

//Data refactor stage
ivec2 pos = ivec2(0);
for (int j = compacter.m_primary.Count() - 1; j >= 0; j--)
{
for (int k = compacter.m_primary[j].m_secondary.Count() - 1; k >= 0; k--)
{
//Try something smaller
if (pos.x + compacter.m_primary[j].m_secondary[k].m_size >= tex_size)
continue;

while (compacter.m_primary[j].m_secondary[k].m_tiles.Count() > 0)
{
//Try something smaller
if (pos.x + compacter.m_primary[j].m_secondary[k].m_size >= tex_size)
break;

compacter.m_primary[j].m_count--;
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;

ASSERT(pos.y + t_size.y < tex_size);

//Move image to texture
int32_t img_off = pos.x + pos.y * tex_size;

//At this stage image data consists of 4 vertical interlaced blocks
for (int pass = 0; pass < 4; pass++)
{
for (int y_cur = 0; y_cur < t_size.y; y_cur++)
{
for (int x_cur = 0; x_cur < t_size.x / 4; x_cur++)
{
int32_t img_pos = img_off + pass + 4 * x_cur + y_cur * (int32_t)tex_size;
image[img_pos] = file_convert[file_off++];
}
}
}

//Register new pos and move to next
m_tiles[i].m1 = pos;
pos.x += t_size.x;
}
}

//Do another loop
if (compacter.m_primary[j].m_count > 0)
{
pos.x = 0;
pos.y += compacter.m_primary[j].m_size;
j++;
}
}
return true;
}

bool ZedImageData::Close()
{
delete[] m_pixels;

return true;
}

uint8_t * ZedImageData::GetData() const
{
return m_pixels;
}

} /* namespace lol */


+ 99
- 0
src/image/codec/zed-palette-image.cpp View File

@@ -0,0 +1,99 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
// 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.
//

#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#include "core.h"
#include "../../image/image-private.h"

using namespace std;

namespace lol
{

/*
* Image implementation class
*/

DECLARE_IMAGE_LOADER(ZedPaletteImageData, 0)
{
public:
virtual bool Open(char const *);
virtual bool Close();

virtual uint8_t *GetData() const;

private:
uint8_t *m_pixels;
};

/*
* Public Image class
*/

bool ZedPaletteImageData::Open(char const *path)
{
if (!lol::String(path).EndsWith(".pal"))
return false;

File file;
file.Open(path, FileAccess::Read, true);

//Put file in memory
long file_size = file.GetSize();
Array<uint8_t> file_buffer;
file_buffer.Resize(file_size);
file.Read((uint8_t*)&file_buffer[0], file_size);
file.Close();

#if 0 //2D PALETTE
int32_t tex_sqrt = (int32_t)lol::sqrt((float)file_size / 3);
int32_t tex_size = 2;
while (tex_size < tex_sqrt)
tex_size <<= 1;
m_size = ivec2(tex_size);
#else
int32_t tex_sqrt = file_size / 3;
int32_t tex_size = 2;
while (tex_size < tex_sqrt)
tex_size <<= 1;
m_size = ivec2(tex_size, 1);
#endif

m_format = PixelFormat::RGBA_8;
m_pixels = new uint8_t[tex_size * tex_size * 4 * sizeof(*m_pixels)];
uint8_t *parser = m_pixels;
for (int i = 0; i < file_buffer.Count();)
{
*parser++ = file_buffer[i++];
*parser++ = file_buffer[i++];
*parser++ = file_buffer[i++];
*parser++ = (i == 0) ? 0 : 255;
}

return true;
}

bool ZedPaletteImageData::Close()
{
delete[] m_pixels;

return true;
}

uint8_t * ZedPaletteImageData::GetData() const
{
return m_pixels;
}

} /* namespace lol */


+ 1
- 0
src/image/image-private.h View File

@@ -84,6 +84,7 @@ public:
virtual bool Close() = 0; virtual bool Close() = 0;


virtual uint8_t *GetData() const = 0; virtual uint8_t *GetData() const = 0;
virtual bool RetrieveTiles(Array<ivec2, ivec2>& tiles) { return false; }


protected: protected:
ivec2 m_size; ivec2 m_size;


+ 57
- 4
src/image/image.cpp View File

@@ -48,6 +48,8 @@ static bool RegisterAllLoaders()
#if defined USE_SDL_IMAGE #if defined USE_SDL_IMAGE
REGISTER_IMAGE_LOADER(SdlImageData) REGISTER_IMAGE_LOADER(SdlImageData)
#endif #endif
REGISTER_IMAGE_LOADER(ZedImageData)
REGISTER_IMAGE_LOADER(ZedPaletteImageData)


return true; return true;
} }
@@ -59,7 +61,11 @@ static bool RegisterAllLoaders()
static class ImageLoader static class ImageLoader
{ {
public: public:
void Init();
Image *Create(char const *path); Image *Create(char const *path);
Image *Get(char const *path);
Image *Load(char const *path);
Image *Store(char const *path, Image *image);
void Destroy(Image *img); void Destroy(Image *img);


private: private:
@@ -67,11 +73,16 @@ private:
} }
image_loader; image_loader;


Image *ImageLoader::Create(char const *path)
void ImageLoader::Init()
{ {
/* Initialise loaders (see above) */ /* Initialise loaders (see above) */
static bool init = RegisterAllLoaders(); static bool init = RegisterAllLoaders();
UNUSED(init); UNUSED(init);
}

Image *ImageLoader::Create(char const *path)
{
Init();


/* Is our image already in the bank? If so, no need to create it. */ /* Is our image already in the bank? If so, no need to create it. */
Image *img; Image *img;
@@ -82,15 +93,42 @@ Image *ImageLoader::Create(char const *path)
} }
else else
{ {
img = new Image();
img->m_data = ImageCodec::Load(path);
m_images[path] = img;
m_images[path] = Load(path);
img = m_images[path];
} }


++img->m_data->m_refcount; ++img->m_data->m_refcount;
return img; return img;
} }


Image *ImageLoader::Get(char const *path)
{
/* Is our image already in the bank? If so, no need to create it. */
Image *img;
if (m_images.HasKey(path))
{
img = m_images[path];
++img->m_data->m_refcount;
return img;
}

return nullptr;
}

Image *ImageLoader::Load(char const *path)
{
Image* img = new Image();
img->m_data = ImageCodec::Load(path);
return img;
}

Image *ImageLoader::Store(char const *path, Image *image)
{
m_images[path] = image;
++image->m_data->m_refcount;
return image;
}

void ImageLoader::Destroy(Image *img) void ImageLoader::Destroy(Image *img)
{ {
ASSERT(img->m_data->m_refcount > 0); ASSERT(img->m_data->m_refcount > 0);
@@ -116,6 +154,16 @@ Image *Image::Create(char const *path)
return image_loader.Create(path); return image_loader.Create(path);
} }


Image *Image::Store(char const *path, Image *img)
{
return image_loader.Store(path, img);
}

Image *Image::Load(char const *path)
{
return image_loader.Load(path);
}

void Image::Destroy(Image *img) void Image::Destroy(Image *img)
{ {
return image_loader.Destroy(img); return image_loader.Destroy(img);
@@ -145,6 +193,11 @@ uint8_t *Image::GetData() const
return m_data->GetData(); return m_data->GetData();
} }


bool Image::RetrieveTiles(Array<ivec2, ivec2>& tiles) const
{
return m_data->RetrieveTiles(tiles);
}

Image::~Image() Image::~Image()
{ {
m_data->Close(); m_data->Close();


+ 2
- 0
src/input/input.cpp View File

@@ -72,6 +72,8 @@ InputDeviceInternal* InputDeviceInternal::CreateStandardMouse()


mouse->AddAxis("X"); mouse->AddAxis("X");
mouse->AddAxis("Y"); mouse->AddAxis("Y");
mouse->AddAxis("XPixel");
mouse->AddAxis("YPixel");
mouse->AddAxis("Scroll"); mouse->AddAxis("Scroll");


mouse->AddCursor("Cursor"); mouse->AddCursor("Cursor");


+ 3
- 0
src/lol/image/image.h View File

@@ -27,11 +27,14 @@ class Image


public: public:
static Image *Create(char const *path); static Image *Create(char const *path);
static Image *Store(char const *path, Image *img);
static Image *Load(char const *path);
static void Destroy(Image *img); static void Destroy(Image *img);


ivec2 GetSize() const; ivec2 GetSize() const;
PixelFormat GetFormat() const; PixelFormat GetFormat() const;
uint8_t *GetData() const; uint8_t *GetData() const;
bool RetrieveTiles(Array<ivec2, ivec2>& tiles) const;


private: private:
Image(); Image();


+ 6
- 2
src/lol/sys/file.h View File

@@ -41,7 +41,8 @@ struct StreamType
StdIn = 0, StdIn = 0,
StdOut, StdOut,
StdErr, StdErr,
File
File,
FileBinary
} }
m_value; m_value;


@@ -59,7 +60,7 @@ public:
~File(); ~File();


void Open(StreamType stream); void Open(StreamType stream);
void Open(String const &file, FileAccess mode);
void Open(String const &file, FileAccess mode, bool force_binary=false);
bool IsValid() const; bool IsValid() const;
void Close(); void Close();


@@ -67,6 +68,9 @@ public:
String ReadString(); String ReadString();
int Write(uint8_t const *buf, int count); int Write(uint8_t const *buf, int count);
int WriteString(const String &buf); int WriteString(const String &buf);
long int GetPosFromStart();
void SetPosFromStart(long int pos);
long int GetSize();


private: private:
class FileData *m_data; class FileData *m_data;


+ 120
- 0
src/lol/sys/thread.h View File

@@ -44,6 +44,126 @@ public:
Thread(void *(*fn)(void *), void *data) : ThreadBase(fn, data) {} Thread(void *(*fn)(void *), void *data) : ThreadBase(fn, data) {}
virtual ~Thread() {} virtual ~Thread() {}
}; };

struct ThreadCommand
{
enum Value
{
THREAD_STARTED,
THREAD_STOPPED,
WORK_TODO,
WORK_DONE,
THREAD_STOP,

MAX
}
m_value;

inline ThreadCommand() : m_value(ThreadCommand::MAX) {}
inline ThreadCommand(Value v) : m_value(v) {}
bool operator==(const ThreadCommand& v) { return m_value == v.m_value; }
};

template<typename T1>
struct JobCommand : public ThreadCommand
{
T1 m_data;

inline JobCommand() : ThreadCommand(ThreadCommand::WORK_TODO) {}
inline JobCommand(Value v) : ThreadCommand(v) {}
inline JobCommand(T1 data) : ThreadCommand(ThreadCommand::WORK_TODO) { m_data = data; }
inline JobCommand(Value v, T1 data) : m_value(v) { m_data = data; }
inline void SetData(T1 data) { m_data = data; }
inline T1 GetData() { return m_data; }
};

template<typename T1, typename T2> class ThreadManager
{
public:
ThreadManager(int thread_count)
{
m_thread_count = thread_count;
}

//Initialize and start the thread
bool Start()
{
if (m_threads.Count() > 0)
return false;

/* Spawn worker threads and wait for their readiness. */
m_threads.Resize(m_thread_count);
for (int i = 0; i < m_thread_count; i++)
m_threads[i] = new Thread(BaseThreadWork, this);
for (int i = 0; i < m_thread_count; i++)
m_spawnqueue.Pop();

return true;
}

bool AddWork(const JobCommand<T1>& job)
{
if (m_jobqueue.TryPush(job))
return true;
return false;
}
bool FetchResult(Array<JobCommand<T2> >& results)
{
JobCommand<T2> result;
while (m_resultqueue.TryPop(result))
results << result;
return results.Count() > 0;
}

static void *BaseThreadWork(void* data)
{
ThreadManager *that = (ThreadManager *)data;
that->m_spawnqueue.Push(ThreadCommand::THREAD_STARTED);
for ( ; ; )
{
JobCommand<T1> job = that->m_jobqueue.Pop();
if (job == ThreadCommand::THREAD_STOP)
break;
else if (job == ThreadCommand::WORK_TODO)
{
JobCommand<T2> result(ThreadCommand::WORK_DONE);
if (that->DoThreadWork(job, result))
that->m_resultqueue.Push(result);
}
}
that->m_donequeue.Push(ThreadCommand::THREAD_STOPPED);
return NULL;
}

virtual bool DoThreadWork(JobCommand<T1>& job, JobCommand<T2>& result)
{
return false;
}

//Stop the thread
bool Stop()
{
if (m_threads.Count() <= 0)
return false;

/* Signal worker threads for completion and wait for
* them to quit. */
for (int i = 0; i < m_thread_count; i++)
m_jobqueue.Push(ThreadCommand::THREAD_STOP);
for (int i = 0; i < m_thread_count; i++)
m_donequeue.Pop();

return true;
}

protected:
/* Worker threads */
int m_thread_count;
Array<Thread*> m_threads;
Queue<ThreadCommand> m_spawnqueue, m_donequeue;
Queue<JobCommand<T1> > m_jobqueue;
Queue<JobCommand<T2> > m_resultqueue;
};
#endif #endif


} /* namespace lol */ } /* namespace lol */


+ 2
- 0
src/lolcore.vcxproj View File

@@ -144,6 +144,8 @@
<ClCompile Include="image\codec\ios-image.cpp" /> <ClCompile Include="image\codec\ios-image.cpp" />
<ClCompile Include="image\codec\ps3-image.cpp" /> <ClCompile Include="image\codec\ps3-image.cpp" />
<ClCompile Include="image\codec\sdl-image.cpp" /> <ClCompile Include="image\codec\sdl-image.cpp" />
<ClCompile Include="image\codec\zed-image.cpp" />
<ClCompile Include="image\codec\zed-palette-image.cpp" />
<ClCompile Include="image\color\cie1931.cpp" /> <ClCompile Include="image\color\cie1931.cpp" />
<ClCompile Include="image\color\color.cpp" /> <ClCompile Include="image\color\color.cpp" />
<ClCompile Include="image\image.cpp" /> <ClCompile Include="image\image.cpp" />


+ 5
- 2
src/platform/sdl/sdlinput.cpp View File

@@ -179,7 +179,7 @@ void SdlInputData::Tick(float seconds)
} }
# endif # endif


m_mouse->SetAxis(2, 0);
m_mouse->SetAxis(4, 0);


/* Handle keyboard and WM events */ /* Handle keyboard and WM events */
SDL_Event event; SDL_Event event;
@@ -202,7 +202,7 @@ void SdlInputData::Tick(float seconds)
if (event.button.button != SDL_BUTTON_WHEELUP && event.button.button != SDL_BUTTON_WHEELDOWN) if (event.button.button != SDL_BUTTON_WHEELUP && event.button.button != SDL_BUTTON_WHEELDOWN)
m_mouse->SetKey(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN); m_mouse->SetKey(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN);
else else
m_mouse->SetAxis(2, (event.button.button != SDL_BUTTON_WHEELUP) ? (1) : (-1));
m_mouse->SetAxis(4, (event.button.button != SDL_BUTTON_WHEELUP) ? (1) : (-1));
// TODO: mouse wheel as axis // TODO: mouse wheel as axis
break; break;
} }
@@ -242,6 +242,9 @@ void SdlInputData::Tick(float seconds)
m_mouse->SetAxis(0, (mouse.x - vprevmouse.x) * MOUSE_SPEED_MOD / max_screen_size); m_mouse->SetAxis(0, (mouse.x - vprevmouse.x) * MOUSE_SPEED_MOD / max_screen_size);
// Y Axis is also negated to match the usual joystick Y axis (negatives values are for the upper direction) // Y Axis is also negated to match the usual joystick Y axis (negatives values are for the upper direction)
m_mouse->SetAxis(1,-(mouse.y - vprevmouse.y) * MOUSE_SPEED_MOD / max_screen_size); m_mouse->SetAxis(1,-(mouse.y - vprevmouse.y) * MOUSE_SPEED_MOD / max_screen_size);
//Pixel movement
m_mouse->SetAxis(2, (mouse.x - vprevmouse.x));
m_mouse->SetAxis(3,-(mouse.y - vprevmouse.y));
} }


//Mouse is focused, Validate the InScreen Key //Mouse is focused, Validate the InScreen Key


+ 86
- 22
src/sys/file.cpp View File

@@ -27,6 +27,8 @@
# include <dirent.h> # include <dirent.h>
#endif #endif


#include <sys/stat.h>

#include "core.h" #include "core.h"


namespace lol namespace lol
@@ -45,7 +47,8 @@ class FileData


void Open(StreamType stream) void Open(StreamType stream)
{ {
if (m_type == StreamType::File)
if (m_type == StreamType::File ||
m_type == StreamType::FileBinary)
return; return;
m_type = stream; m_type = stream;
switch((int)stream) switch((int)stream)
@@ -62,9 +65,9 @@ class FileData
} }
} }


void Open(String const &file, FileAccess mode)
void Open(String const &file, FileAccess mode, bool force_binary)
{ {
m_type = StreamType::File;
m_type = (force_binary) ? (StreamType::FileBinary) : (StreamType::File);
#if __CELLOS_LV2__ #if __CELLOS_LV2__
String realfile = String(SYS_APP_HOME) + '/' + file; String realfile = String(SYS_APP_HOME) + '/' + file;
CellFsErrno err = cellFsOpen(realfile.C(), CELL_FS_O_RDONLY, CellFsErrno err = cellFsOpen(realfile.C(), CELL_FS_O_RDONLY,
@@ -76,7 +79,8 @@ class FileData
m_asset = AAssetManager_open(g_assets, file.C(), AASSET_MODE_UNKNOWN); m_asset = AAssetManager_open(g_assets, file.C(), AASSET_MODE_UNKNOWN);
#elif HAVE_STDIO_H #elif HAVE_STDIO_H
/* FIXME: no modes, no error checking, no nothing */ /* FIXME: no modes, no error checking, no nothing */
m_fd = fopen(file.C(), "r");
stat(file.C(), &m_stat);
m_fd = fopen(file.C(), (!force_binary) ? ("r") : ("rb"));
#endif #endif
} }


@@ -93,6 +97,26 @@ class FileData
#endif #endif
} }


void Close()
{
if (m_type != StreamType::File &&
m_type != StreamType::FileBinary)
return;
#if __CELLOS_LV2__
if (m_fd >= 0)
cellFsClose(m_fd);
m_fd = -1;
#elif __ANDROID__
if (m_asset)
AAsset_close(m_asset);
m_asset = nullptr;
#elif HAVE_STDIO_H
if (m_fd)
fclose(m_fd);
m_fd = nullptr;
#endif
}

int Read(uint8_t *buf, int count) int Read(uint8_t *buf, int count)
{ {
#if __CELLOS_LV2__ #if __CELLOS_LV2__
@@ -169,25 +193,46 @@ class FileData
return Write((uint8_t const *)buf.C(), buf.Count()); return Write((uint8_t const *)buf.C(), buf.Count());
} }


void Close()
long int GetPosFromStart()
{ {
if (m_type != StreamType::File)
return;
#if __CELLOS_LV2__ #if __CELLOS_LV2__
if (m_fd >= 0)
cellFsClose(m_fd);
m_fd = -1;
return 0;
#elif __ANDROID__ #elif __ANDROID__
if (m_asset)
AAsset_close(m_asset);
m_asset = nullptr;
return 0;
#elif HAVE_STDIO_H #elif HAVE_STDIO_H
if (m_fd)
fclose(m_fd);
m_fd = nullptr;
return ftell(m_fd);
#else
return 0;
#endif
}

void SetPosFromStart(long int pos)
{
#if __CELLOS_LV2__
//NOT IMPLEMENTED
#elif __ANDROID__
//NOT IMPLEMENTED
#elif HAVE_STDIO_H
fseek(m_fd, pos, SEEK_SET);
#else
//NOT IMPLEMENTED
#endif #endif
} }


long int GetSize()
{
#if __CELLOS_LV2__
return 0;
#elif __ANDROID__
return 0;
#elif HAVE_STDIO_H
return m_stat.st_size;
#else
return 0;
#endif
}


#if __CELLOS_LV2__ #if __CELLOS_LV2__
int m_fd; int m_fd;
#elif __ANDROID__ #elif __ANDROID__
@@ -195,8 +240,9 @@ class FileData
#elif HAVE_STDIO_H #elif HAVE_STDIO_H
FILE *m_fd; FILE *m_fd;
#endif #endif
Atomic<int> m_refcount;
StreamType m_type;
Atomic<int> m_refcount;
StreamType m_type;
struct stat m_stat;
}; };


//-- FILE -- //-- FILE --
@@ -251,9 +297,9 @@ void File::Open(StreamType stream)
} }


//-- //--
void File::Open(String const &file, FileAccess mode)
void File::Open(String const &file, FileAccess mode, bool force_binary)
{ {
return m_data->Open(file, mode);
return m_data->Open(file, mode, force_binary);
} }


//-- //--
@@ -262,6 +308,12 @@ bool File::IsValid() const
return m_data->IsValid(); return m_data->IsValid();
} }


//--
void File::Close()
{
m_data->Close();
}

//-- //--
int File::Read(uint8_t *buf, int count) int File::Read(uint8_t *buf, int count)
{ {
@@ -287,9 +339,21 @@ int File::WriteString(const String &buf)
} }


//-- //--
void File::Close()
long int File::GetPosFromStart()
{ {
m_data->Close();
return m_data->GetPosFromStart();
}

//--
void File::SetPosFromStart(long int pos)
{
m_data->SetPosFromStart(pos);
}

//--
long int File::GetSize()
{
return m_data->GetSize();
} }


//--------------- //---------------


+ 36
- 0
src/tiler.cpp View File

@@ -76,6 +76,42 @@ TileSet *Tiler::Register(char const *path)
return tileset; return tileset;
} }


TileSet *Tiler::Register(String const &path, Image* image, ivec2 size, ivec2 count)
{
return Tiler::Register(path.C(), image, size, count);
}
TileSet *Tiler::Register(char const *path, Image* image, ivec2 size, ivec2 count)
{
int id = data->tilesets.MakeSlot(path);
TileSet *tileset = (TileSet *)data->tilesets.GetEntity(id);

if (!tileset)
{
tileset = new TileSet(path, image, size, count);
data->tilesets.SetEntity(id, tileset);
}

return tileset;
}

TileSet *Tiler::Register(String const &path, Image* image)
{
return Tiler::Register(path.C(), image);
}
TileSet *Tiler::Register(char const *path, Image* image)
{
int id = data->tilesets.MakeSlot(path);
TileSet *tileset = (TileSet *)data->tilesets.GetEntity(id);

if (!tileset)
{
tileset = new TileSet(path, image);
data->tilesets.SetEntity(id, tileset);
}

return tileset;
}

void Tiler::Deregister(TileSet *tileset) void Tiler::Deregister(TileSet *tileset)
{ {
data->tilesets.RemoveSlot(tileset); data->tilesets.RemoveSlot(tileset);


+ 4
- 0
src/tiler.h View File

@@ -31,6 +31,10 @@ public:
static TileSet *Register(char const *path, ivec2 size, ivec2 count); static TileSet *Register(char const *path, ivec2 size, ivec2 count);
static TileSet *Register(String const &path); static TileSet *Register(String const &path);
static TileSet *Register(char const *path); static TileSet *Register(char const *path);
static TileSet *Register(String const &path, Image* image, ivec2 size, ivec2 count);
static TileSet *Register(char const *path, Image* image, ivec2 size, ivec2 count);
static TileSet *Register(String const &path, Image* image);
static TileSet *Register(char const *path, Image* image);
static void Deregister(TileSet *); static void Deregister(TileSet *);


private: private:


+ 69
- 1
src/tileset.cpp View File

@@ -60,6 +60,22 @@ TileSet::TileSet(char const *path)
: m_data(new TileSetData()) : m_data(new TileSetData())
{ {
Init(path); Init(path);

Array<ivec2, ivec2> tiles;
if (m_data->m_image->RetrieveTiles(tiles))
for (int i = 0; i < tiles.Count(); i++)
AddTile(ibox2(tiles[0].m1, tiles[0].m1 + tiles[0].m2));
}

TileSet::TileSet(char const *path, Image* image)
: m_data(new TileSetData())
{
Init(path, image);

Array<ivec2, ivec2> tiles;
if (m_data->m_image->RetrieveTiles(tiles))
for (int i = 0; i < tiles.Count(); i++)
AddTile(ibox2(tiles[0].m1, tiles[0].m1 + tiles[0].m2));
} }


TileSet::TileSet(char const *path, ivec2 size, ivec2 count) TileSet::TileSet(char const *path, ivec2 size, ivec2 count)
@@ -85,14 +101,54 @@ TileSet::TileSet(char const *path, ivec2 size, ivec2 count)
AddTile(ibox2(size * ivec2(i, j), AddTile(ibox2(size * ivec2(i, j),
size * ivec2(i + 1, j + 1))); size * ivec2(i + 1, j + 1)));
} }

Array<ivec2, ivec2> tiles;
if (m_data->m_image->RetrieveTiles(tiles))
for (int i = 0; i < tiles.Count(); i++)
AddTile(ibox2(tiles[i].m1, tiles[i].m1 + tiles[i].m2));
}

TileSet::TileSet(char const *path, Image* image, ivec2 size, ivec2 count)
: m_data(new TileSetData())
{
Init(path, image);

/* If count is valid, fix size; otherwise, fix count. */
if (count.x > 0 && count.y > 0)
{
size = m_data->m_image_size / count;
}
else
{
if (size.x <= 0 || size.y <= 0)
size = ivec2(32, 32);
count = max(ivec2(1, 1), m_data->m_image_size / size);
}

for (int j = 0; j < count.y; ++j)
for (int i = 0; i < count.x; ++i)
{
AddTile(ibox2(size * ivec2(i, j),
size * ivec2(i + 1, j + 1)));
}

Array<ivec2, ivec2> tiles;
if (m_data->m_image->RetrieveTiles(tiles))
for (int i = 0; i < tiles.Count(); i++)
AddTile(ibox2(tiles[i].m1, tiles[i].m1 + tiles[i].m2));
} }


void TileSet::Init(char const *path) void TileSet::Init(char const *path)
{
Init(path, Image::Create(path));
}

void TileSet::Init(char const *path, Image* image)
{ {
m_data->m_name = String("<tileset> ") + path; m_data->m_name = String("<tileset> ") + path;


m_data->m_texture = 0; m_data->m_texture = 0;
m_data->m_image = Image::Create(path);
m_data->m_image = image;
m_data->m_image_size = m_data->m_image->GetSize(); m_data->m_image_size = m_data->m_image->GetSize();
m_data->m_texture_size = ivec2(PotUp(m_data->m_image_size.x), m_data->m_texture_size = ivec2(PotUp(m_data->m_image_size.x),
PotUp(m_data->m_image_size.y)); PotUp(m_data->m_image_size.y));
@@ -108,6 +164,18 @@ int TileSet::AddTile(ibox2 rect)
return m_data->m_tiles.Count() - 1; return m_data->m_tiles.Count() - 1;
} }


void TileSet::AddTile(ivec2 count)
{
ivec2 size = m_data->m_image_size / count;

for (int j = 0; j < count.y; ++j)
for (int i = 0; i < count.x; ++i)
{
AddTile(ibox2(size * ivec2(i, j),
size * ivec2(i + 1, j + 1)));
}
}

TileSet::~TileSet() TileSet::~TileSet()
{ {
delete m_data; delete m_data;


+ 4
- 0
src/tileset.h View File

@@ -32,10 +32,12 @@ class TileSet : public Entity
{ {
public: public:
TileSet(char const *path); TileSet(char const *path);
TileSet(char const *path, Image* image);
virtual ~TileSet(); virtual ~TileSet();


/* 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);
TileSet(char const *path, Image* image, ivec2 size, ivec2 count);


protected: protected:
/* Inherited from Entity */ /* Inherited from Entity */
@@ -45,6 +47,7 @@ protected:
public: public:
/* New methods */ /* New methods */
int AddTile(ibox2 rect); int AddTile(ibox2 rect);
void AddTile(ivec2 count);
int GetTileCount() const; int GetTileCount() const;
ivec2 GetTileSize(int tileid) const; ivec2 GetTileSize(int tileid) const;


@@ -58,6 +61,7 @@ public:


private: private:
void Init(char const *path); void Init(char const *path);
void Init(char const *path, Image* image);


TileSetData *m_data; TileSetData *m_data;
}; };


Loading…
Cancel
Save