| @@ -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 */ | |||
| @@ -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 */ | |||
| @@ -84,6 +84,7 @@ public: | |||
| virtual bool Close() = 0; | |||
| virtual uint8_t *GetData() const = 0; | |||
| virtual bool RetrieveTiles(Array<ivec2, ivec2>& tiles) { return false; } | |||
| protected: | |||
| ivec2 m_size; | |||
| @@ -48,6 +48,8 @@ static bool RegisterAllLoaders() | |||
| #if defined USE_SDL_IMAGE | |||
| REGISTER_IMAGE_LOADER(SdlImageData) | |||
| #endif | |||
| REGISTER_IMAGE_LOADER(ZedImageData) | |||
| REGISTER_IMAGE_LOADER(ZedPaletteImageData) | |||
| return true; | |||
| } | |||
| @@ -59,7 +61,11 @@ static bool RegisterAllLoaders() | |||
| static class ImageLoader | |||
| { | |||
| public: | |||
| void Init(); | |||
| 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); | |||
| private: | |||
| @@ -67,11 +73,16 @@ private: | |||
| } | |||
| image_loader; | |||
| Image *ImageLoader::Create(char const *path) | |||
| void ImageLoader::Init() | |||
| { | |||
| /* Initialise loaders (see above) */ | |||
| static bool init = RegisterAllLoaders(); | |||
| UNUSED(init); | |||
| } | |||
| Image *ImageLoader::Create(char const *path) | |||
| { | |||
| Init(); | |||
| /* Is our image already in the bank? If so, no need to create it. */ | |||
| Image *img; | |||
| @@ -82,15 +93,42 @@ Image *ImageLoader::Create(char const *path) | |||
| } | |||
| 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; | |||
| 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) | |||
| { | |||
| ASSERT(img->m_data->m_refcount > 0); | |||
| @@ -116,6 +154,16 @@ Image *Image::Create(char const *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) | |||
| { | |||
| return image_loader.Destroy(img); | |||
| @@ -145,6 +193,11 @@ uint8_t *Image::GetData() const | |||
| return m_data->GetData(); | |||
| } | |||
| bool Image::RetrieveTiles(Array<ivec2, ivec2>& tiles) const | |||
| { | |||
| return m_data->RetrieveTiles(tiles); | |||
| } | |||
| Image::~Image() | |||
| { | |||
| m_data->Close(); | |||
| @@ -72,6 +72,8 @@ InputDeviceInternal* InputDeviceInternal::CreateStandardMouse() | |||
| mouse->AddAxis("X"); | |||
| mouse->AddAxis("Y"); | |||
| mouse->AddAxis("XPixel"); | |||
| mouse->AddAxis("YPixel"); | |||
| mouse->AddAxis("Scroll"); | |||
| mouse->AddCursor("Cursor"); | |||
| @@ -27,11 +27,14 @@ class Image | |||
| public: | |||
| 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); | |||
| ivec2 GetSize() const; | |||
| PixelFormat GetFormat() const; | |||
| uint8_t *GetData() const; | |||
| bool RetrieveTiles(Array<ivec2, ivec2>& tiles) const; | |||
| private: | |||
| Image(); | |||
| @@ -41,7 +41,8 @@ struct StreamType | |||
| StdIn = 0, | |||
| StdOut, | |||
| StdErr, | |||
| File | |||
| File, | |||
| FileBinary | |||
| } | |||
| m_value; | |||
| @@ -59,7 +60,7 @@ public: | |||
| ~File(); | |||
| 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; | |||
| void Close(); | |||
| @@ -67,6 +68,9 @@ public: | |||
| String ReadString(); | |||
| int Write(uint8_t const *buf, int count); | |||
| int WriteString(const String &buf); | |||
| long int GetPosFromStart(); | |||
| void SetPosFromStart(long int pos); | |||
| long int GetSize(); | |||
| private: | |||
| class FileData *m_data; | |||
| @@ -44,6 +44,126 @@ public: | |||
| Thread(void *(*fn)(void *), void *data) : ThreadBase(fn, data) {} | |||
| 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 | |||
| } /* namespace lol */ | |||
| @@ -144,6 +144,8 @@ | |||
| <ClCompile Include="image\codec\ios-image.cpp" /> | |||
| <ClCompile Include="image\codec\ps3-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\color.cpp" /> | |||
| <ClCompile Include="image\image.cpp" /> | |||
| @@ -179,7 +179,7 @@ void SdlInputData::Tick(float seconds) | |||
| } | |||
| # endif | |||
| m_mouse->SetAxis(2, 0); | |||
| m_mouse->SetAxis(4, 0); | |||
| /* Handle keyboard and WM events */ | |||
| 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) | |||
| m_mouse->SetKey(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN); | |||
| 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 | |||
| break; | |||
| } | |||
| @@ -242,6 +242,9 @@ void SdlInputData::Tick(float seconds) | |||
| 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) | |||
| 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 | |||
| @@ -27,6 +27,8 @@ | |||
| # include <dirent.h> | |||
| #endif | |||
| #include <sys/stat.h> | |||
| #include "core.h" | |||
| namespace lol | |||
| @@ -45,7 +47,8 @@ class FileData | |||
| void Open(StreamType stream) | |||
| { | |||
| if (m_type == StreamType::File) | |||
| if (m_type == StreamType::File || | |||
| m_type == StreamType::FileBinary) | |||
| return; | |||
| m_type = 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__ | |||
| String realfile = String(SYS_APP_HOME) + '/' + file; | |||
| 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); | |||
| #elif HAVE_STDIO_H | |||
| /* 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 | |||
| } | |||
| @@ -93,6 +97,26 @@ class FileData | |||
| #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) | |||
| { | |||
| #if __CELLOS_LV2__ | |||
| @@ -169,25 +193,46 @@ class FileData | |||
| return Write((uint8_t const *)buf.C(), buf.Count()); | |||
| } | |||
| void Close() | |||
| long int GetPosFromStart() | |||
| { | |||
| if (m_type != StreamType::File) | |||
| return; | |||
| #if __CELLOS_LV2__ | |||
| if (m_fd >= 0) | |||
| cellFsClose(m_fd); | |||
| m_fd = -1; | |||
| return 0; | |||
| #elif __ANDROID__ | |||
| if (m_asset) | |||
| AAsset_close(m_asset); | |||
| m_asset = nullptr; | |||
| return 0; | |||
| #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 | |||
| } | |||
| 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__ | |||
| int m_fd; | |||
| #elif __ANDROID__ | |||
| @@ -195,8 +240,9 @@ class FileData | |||
| #elif HAVE_STDIO_H | |||
| FILE *m_fd; | |||
| #endif | |||
| Atomic<int> m_refcount; | |||
| StreamType m_type; | |||
| Atomic<int> m_refcount; | |||
| StreamType m_type; | |||
| struct stat m_stat; | |||
| }; | |||
| //-- 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(); | |||
| } | |||
| //-- | |||
| void File::Close() | |||
| { | |||
| m_data->Close(); | |||
| } | |||
| //-- | |||
| 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(); | |||
| } | |||
| //--------------- | |||
| @@ -76,6 +76,42 @@ TileSet *Tiler::Register(char const *path) | |||
| 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) | |||
| { | |||
| data->tilesets.RemoveSlot(tileset); | |||
| @@ -31,6 +31,10 @@ public: | |||
| static TileSet *Register(char const *path, ivec2 size, ivec2 count); | |||
| static TileSet *Register(String 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 *); | |||
| private: | |||
| @@ -60,6 +60,22 @@ TileSet::TileSet(char const *path) | |||
| : m_data(new TileSetData()) | |||
| { | |||
| 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) | |||
| @@ -85,14 +101,54 @@ TileSet::TileSet(char const *path, ivec2 size, ivec2 count) | |||
| 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)); | |||
| } | |||
| 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) | |||
| { | |||
| Init(path, Image::Create(path)); | |||
| } | |||
| void TileSet::Init(char const *path, Image* image) | |||
| { | |||
| m_data->m_name = String("<tileset> ") + path; | |||
| 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_texture_size = ivec2(PotUp(m_data->m_image_size.x), | |||
| PotUp(m_data->m_image_size.y)); | |||
| @@ -108,6 +164,18 @@ int TileSet::AddTile(ibox2 rect) | |||
| 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() | |||
| { | |||
| delete m_data; | |||
| @@ -32,10 +32,12 @@ class TileSet : public Entity | |||
| { | |||
| public: | |||
| TileSet(char const *path); | |||
| TileSet(char const *path, Image* image); | |||
| virtual ~TileSet(); | |||
| /* Old style: path to PNG file */ | |||
| TileSet(char const *path, ivec2 size, ivec2 count); | |||
| TileSet(char const *path, Image* image, ivec2 size, ivec2 count); | |||
| protected: | |||
| /* Inherited from Entity */ | |||
| @@ -45,6 +47,7 @@ protected: | |||
| public: | |||
| /* New methods */ | |||
| int AddTile(ibox2 rect); | |||
| void AddTile(ivec2 count); | |||
| int GetTileCount() const; | |||
| ivec2 GetTileSize(int tileid) const; | |||
| @@ -58,6 +61,7 @@ public: | |||
| private: | |||
| void Init(char const *path); | |||
| void Init(char const *path, Image* image); | |||
| TileSetData *m_data; | |||
| }; | |||