aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/buildvm/buildvm.exebin62976 -> 62976 bytes
-rw-r--r--src/3rdparty/minilua/minilua.exebin112640 -> 112640 bytes
-rw-r--r--src/libjin/Audio/SDL/je_sdl_audio.cpp252
-rw-r--r--src/libjin/Audio/SDL/je_sdl_audio.h231
-rw-r--r--src/libjin/Audio/SDL/je_sdl_source.cpp727
-rw-r--r--src/libjin/Audio/SDL/je_sdl_source.h481
-rw-r--r--src/libjin/Core/je_configuration.h2
-rw-r--r--src/libjin/Graphics/Font/je_decoder.cpp93
-rw-r--r--src/libjin/Graphics/Font/je_decoder.h94
-rw-r--r--src/libjin/Graphics/Font/je_font.h106
-rw-r--r--src/libjin/Graphics/Font/je_page.h51
-rw-r--r--src/libjin/Graphics/Font/je_text.cpp154
-rw-r--r--src/libjin/Graphics/Font/je_text.h169
-rw-r--r--src/libjin/Graphics/Font/je_texture_font.cpp318
-rw-r--r--src/libjin/Graphics/Font/je_texture_font.h139
-rw-r--r--src/libjin/Graphics/Font/je_ttf.cpp463
-rw-r--r--src/libjin/Graphics/Font/je_ttf.h289
-rw-r--r--src/libjin/Graphics/Shader/je_jsl_compiler.cpp54
-rw-r--r--src/libjin/Graphics/Shader/je_jsl_compiler.h42
-rw-r--r--src/libjin/Graphics/Shader/je_shader.cpp278
-rw-r--r--src/libjin/Graphics/Shader/je_shader.h197
-rw-r--r--src/libjin/Graphics/animation/je_animation.h56
-rw-r--r--src/libjin/Graphics/animation/je_animator.h48
-rw-r--r--src/libjin/Graphics/animations/je_animation.cpp (renamed from src/libjin/Graphics/animation/je_animation.cpp)0
-rw-r--r--src/libjin/Graphics/animations/je_animation.h59
-rw-r--r--src/libjin/Graphics/animations/je_animator.cpp (renamed from src/libjin/Graphics/animation/je_animator.cpp)0
-rw-r--r--src/libjin/Graphics/animations/je_animator.h51
-rw-r--r--src/libjin/Graphics/fonts/je_decoder.cpp96
-rw-r--r--src/libjin/Graphics/fonts/je_decoder.h97
-rw-r--r--src/libjin/Graphics/fonts/je_font.h109
-rw-r--r--src/libjin/Graphics/fonts/je_page.h54
-rw-r--r--src/libjin/Graphics/fonts/je_text.cpp157
-rw-r--r--src/libjin/Graphics/fonts/je_text.h172
-rw-r--r--src/libjin/Graphics/fonts/je_texture_font.cpp322
-rw-r--r--src/libjin/Graphics/fonts/je_texture_font.h142
-rw-r--r--src/libjin/Graphics/fonts/je_ttf.cpp468
-rw-r--r--src/libjin/Graphics/fonts/je_ttf.h292
-rw-r--r--src/libjin/Graphics/je_graphic.cpp4
-rw-r--r--src/libjin/Graphics/je_graphics.h10
-rw-r--r--src/libjin/Graphics/je_shapes.cpp4
-rw-r--r--src/libjin/Graphics/je_sprite.h6
-rw-r--r--src/libjin/Graphics/je_window.cpp9
-rw-r--r--src/libjin/Graphics/particle/je_particle.h154
-rw-r--r--src/libjin/Graphics/particle/je_particle_emitter.h96
-rw-r--r--src/libjin/Graphics/particle/je_particle_pool.h53
-rw-r--r--src/libjin/Graphics/particle/je_particle_system.h91
-rw-r--r--src/libjin/Graphics/particles/je_particle.cpp (renamed from src/libjin/Graphics/particle/je_particle.cpp)0
-rw-r--r--src/libjin/Graphics/particles/je_particle.h157
-rw-r--r--src/libjin/Graphics/particles/je_particle_emitter.cpp (renamed from src/libjin/Graphics/particle/je_particle_emitter.cpp)0
-rw-r--r--src/libjin/Graphics/particles/je_particle_emitter.h99
-rw-r--r--src/libjin/Graphics/particles/je_particle_pool.cpp (renamed from src/libjin/Graphics/particle/je_particle_pool.cpp)0
-rw-r--r--src/libjin/Graphics/particles/je_particle_pool.h56
-rw-r--r--src/libjin/Graphics/particles/je_particle_system.cpp (renamed from src/libjin/Graphics/particle/je_particle_system.cpp)0
-rw-r--r--src/libjin/Graphics/particles/je_particle_system.h94
-rw-r--r--src/libjin/Graphics/shaders/built-in/je_default.shader.h (renamed from src/libjin/Graphics/Shader/shaders/je_default.shader.h)0
-rw-r--r--src/libjin/Graphics/shaders/built-in/je_font.shader.h (renamed from src/libjin/Graphics/Shader/shaders/je_font.shader.h)0
-rw-r--r--src/libjin/Graphics/shaders/built-in/je_texture.shader.h (renamed from src/libjin/Graphics/Shader/shaders/je_texture.shader.h)0
-rw-r--r--src/libjin/Graphics/shaders/je_base.shader.h (renamed from src/libjin/Graphics/Shader/je_base.shader.h)0
-rw-r--r--src/libjin/Graphics/shaders/je_jsl_compiler.cpp57
-rw-r--r--src/libjin/Graphics/shaders/je_jsl_compiler.h45
-rw-r--r--src/libjin/Graphics/shaders/je_shader.cpp281
-rw-r--r--src/libjin/Graphics/shaders/je_shader.h200
-rw-r--r--src/libjin/Utils/je_log.cpp81
-rw-r--r--src/libjin/Utils/je_log.h103
-rw-r--r--src/libjin/ai/je_ai.h7
-rw-r--r--src/libjin/ai/je_behavior_tree.h4
-rw-r--r--src/libjin/ai/je_state_machine.cpp407
-rw-r--r--src/libjin/ai/je_state_machine.h128
-rw-r--r--src/libjin/jin.h2
-rw-r--r--src/lua/modules/ai/je_lua_behavior_tree.cpp0
-rw-r--r--src/lua/modules/ai/je_lua_statemachine.cpp0
-rw-r--r--src/lua/modules/audio/je_lua_audio.cpp1
-rw-r--r--src/lua/modules/graphics/je_lua_graphics.cpp2
-rw-r--r--src/lua/modules/graphics/je_lua_page.cpp2
-rw-r--r--src/lua/modules/graphics/je_lua_shader.cpp1
-rw-r--r--src/lua/modules/graphics/je_lua_texture_font.cpp1
-rw-r--r--src/lua/modules/graphics/je_lua_ttf.cpp1
-rw-r--r--src/lua/modules/graphics/je_lua_ttf_data.cpp1
78 files changed, 4473 insertions, 3947 deletions
diff --git a/src/3rdparty/buildvm/buildvm.exe b/src/3rdparty/buildvm/buildvm.exe
index 731fbfb..ed23035 100644
--- a/src/3rdparty/buildvm/buildvm.exe
+++ b/src/3rdparty/buildvm/buildvm.exe
Binary files differ
diff --git a/src/3rdparty/minilua/minilua.exe b/src/3rdparty/minilua/minilua.exe
index 1567a0c..8e7c938 100644
--- a/src/3rdparty/minilua/minilua.exe
+++ b/src/3rdparty/minilua/minilua.exe
Binary files differ
diff --git a/src/libjin/Audio/SDL/je_sdl_audio.cpp b/src/libjin/Audio/SDL/je_sdl_audio.cpp
index 4ce02f7..c21d077 100644
--- a/src/libjin/Audio/SDL/je_sdl_audio.cpp
+++ b/src/libjin/Audio/SDL/je_sdl_audio.cpp
@@ -9,135 +9,137 @@
#include "je_sdl_audio.h"
#include "je_sdl_source.h"
+using namespace JinEngine::Math;
+
namespace JinEngine
{
namespace Audio
{
-
- using namespace JinEngine::Math;
-
- /* עcallbackƵ̵߳ */
- static void defaultCallback(void *userdata, Uint8 *stream, int size)
- {
- static SDLAudio* audio = static_cast<SDLAudio*>(userdata);
- if (!audio->goOnProcess())
- return;
- audio->lock();
- audio->processCommands();
- audio->processSources(stream, size);
- audio->processBuffer(stream, size);
- audio->unlock();
- }
-
- /*call only once*/ bool SDLAudio::initSystem(const SettingBase* s)
- {
- #if defined(jin_debug)
- Loghelper::log(Loglevel::LV_INFO, "Init AudioManager System");
- #endif
-
- if (SDL_Init(SDL_INIT_AUDIO) < 0)
- return false;
-
- SDL_AudioSpec spec;
- Setting* setting = (Setting*)s;
- if (setting == nullptr)
- return false;
-
- unsigned int samplerate = setting->samplerate;
- unsigned int samples = clamp<int>(setting->samples, 1, setting->samplerate);
-
- spec.freq = samplerate; // ÿsample,õ 11025, 22050, 44100 and 48000 Hz.
- spec.format = AUDIO_S16SYS; // signed 16-bit samples in native byte order
- spec.channels = SDLAUDIO_CHANNELS; //
- spec.samples = samples; // ÿβʱһã=setting->samplerateÿֻ1
- spec.userdata = this;
- spec.callback = defaultCallback;
-
- audioDevice = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0);
- if (audioDevice == 0)
- return false;
- /* start audio */
- SDL_PauseAudioDevice(audioDevice, 0);
- return true;
- }
-
- /*call only once*/ void SDLAudio::quitSystem()
- {
- SDL_CloseAudio();
- }
-
- void SDLAudio::lock()
- {
- SDL_LockAudioDevice(audioDevice);
- }
-
- void SDLAudio::unlock()
- {
- SDL_UnlockAudioDevice(audioDevice);
- }
-
- bool SDLAudio::goOnProcess()
- {
- if (state == SDLAudio::State::STOP)
- {
- SDLSourceManager::get()->removeAllSource();
- pause();
- return false;
- }
- else if (state == SDLAudio::State::PAUSE)
- return false;
- else
- return true;
- }
-
- void SDLAudio::processCommands()
- {
- SDLSourceManager::get()->processCommands();
- }
-
- void SDLAudio::processSources(void* buffer, size_t len)
- {
- SDLSourceManager::get()->processSources(buffer, len);
- }
-
- void SDLAudio::processBuffer(void* buff, size_t len)
- {
- short* buffer = (short*)buff;
- int samples = (len / SDLAUDIO_BYTEDEPTH) >> 1; // ˫
- const char L = 0, R = 1;
- for (int i = 0; i < samples; ++i)
- {
- short* clip = buffer + (i << 1);
- clip[L] *= volume;
- clip[R] *= volume;
- }
- }
-
- void SDLAudio::play()
- {
- state = State::PLAY;
- }
-
- void SDLAudio::stop()
- {
- state = State::STOP;
- }
-
- void SDLAudio::pause()
- {
- state = State::PAUSE;
- }
-
- void SDLAudio::resume()
- {
- state = State::PLAY;
- }
-
- void SDLAudio::setVolume(float volume)
- {
- this->volume = clamp(volume, 0.0f, 1.0f);
- }
-
+ namespace SDL
+ {
+
+ /* עcallbackƵ̵߳ */
+ static void defaultCallback(void *userdata, Uint8 *stream, int size)
+ {
+ static SDLAudio* audio = static_cast<SDLAudio*>(userdata);
+ if (!audio->goOnProcess())
+ return;
+ audio->lock();
+ audio->processCommands();
+ audio->processSources(stream, size);
+ audio->processBuffer(stream, size);
+ audio->unlock();
+ }
+
+ /*call only once*/ bool SDLAudio::initSystem(const SettingBase* s)
+ {
+ jin_log_info("Initialize audio system.");
+
+ if (SDL_Init(SDL_INIT_AUDIO) < 0)
+ return false;
+
+ SDL_AudioSpec spec;
+ Setting* setting = (Setting*)s;
+ if (setting == nullptr)
+ return false;
+
+ unsigned int samplerate = setting->samplerate;
+ unsigned int samples = clamp<int>(setting->samples, 1, setting->samplerate);
+
+ spec.freq = samplerate; // ÿsample,õ 11025, 22050, 44100 and 48000 Hz.
+ spec.format = AUDIO_S16SYS; // signed 16-bit samples in native byte order
+ spec.channels = SDLAUDIO_CHANNELS; //
+ spec.samples = samples; // ÿβʱһã=setting->samplerateÿֻ1
+ spec.userdata = this;
+ spec.callback = defaultCallback;
+
+ audioDevice = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0);
+ if (audioDevice == 0)
+ return false;
+ /* start audio */
+ SDL_PauseAudioDevice(audioDevice, 0);
+ return true;
+ }
+
+ /*call only once*/ void SDLAudio::quitSystem()
+ {
+ jin_log_info("Quit audio system.");
+ SDL_CloseAudio();
+ }
+
+ void SDLAudio::lock()
+ {
+ SDL_LockAudioDevice(audioDevice);
+ }
+
+ void SDLAudio::unlock()
+ {
+ SDL_UnlockAudioDevice(audioDevice);
+ }
+
+ bool SDLAudio::goOnProcess()
+ {
+ if (state == SDLAudio::State::STOP)
+ {
+ SDLSourceManager::get()->removeAllSource();
+ pause();
+ return false;
+ }
+ else if (state == SDLAudio::State::PAUSE)
+ return false;
+ else
+ return true;
+ }
+
+ void SDLAudio::processCommands()
+ {
+ SDLSourceManager::get()->processCommands();
+ }
+
+ void SDLAudio::processSources(void* buffer, size_t len)
+ {
+ SDLSourceManager::get()->processSources(buffer, len);
+ }
+
+ void SDLAudio::processBuffer(void* buff, size_t len)
+ {
+ short* buffer = (short*)buff;
+ int samples = (len / SDLAUDIO_BYTEDEPTH) >> 1; // ˫
+ const char L = 0, R = 1;
+ for (int i = 0; i < samples; ++i)
+ {
+ short* clip = buffer + (i << 1);
+ clip[L] *= volume;
+ clip[R] *= volume;
+ }
+ }
+
+ void SDLAudio::play()
+ {
+ state = State::PLAY;
+ }
+
+ void SDLAudio::stop()
+ {
+ state = State::STOP;
+ }
+
+ void SDLAudio::pause()
+ {
+ state = State::PAUSE;
+ }
+
+ void SDLAudio::resume()
+ {
+ state = State::PLAY;
+ }
+
+ void SDLAudio::setVolume(float volume)
+ {
+ this->volume = clamp(volume, 0.0f, 1.0f);
+ }
+
+ } // namespace SDL
} // namespace Audio
} // namespace JinEngine
diff --git a/src/libjin/Audio/SDL/je_sdl_audio.h b/src/libjin/Audio/SDL/je_sdl_audio.h
index 57fee5b..1b12ac1 100644
--- a/src/libjin/Audio/SDL/je_sdl_audio.h
+++ b/src/libjin/Audio/SDL/je_sdl_audio.h
@@ -13,120 +13,123 @@ namespace JinEngine
{
namespace Audio
{
-
- #define SDLAUDIO_BITDEPTH 16
- #define SDLAUDIO_BYTEDEPTH (SDLAUDIO_BITDEPTH >> 3)
- #define SDLAUDIO_CHANNELS 2
-
- ///
- /// Audio system SDL implementation.
- ///
- class SDLAudio : public AudioManager<SDLAudio>
- {
- public:
- ///
- /// SDL audio setting.
- ///
- struct Setting : SettingBase
- {
- public:
- int samplerate; // Ƶ
- int samples; // sample<=samplerate
- };
-
- ///
- /// Play all sources whose state is playing.
- ///
- void play() override;
-
- ///
- /// Stop and remove all sources from the queue.
- ///
- void stop() override;
-
- ///
- /// Pause audio.
- ///
- void pause() override;
-
- ///
- /// Resume audio.
- ///
- void resume() override;
-
- ///
- /// Set global audio volume.
- ///
- void setVolume(float volume) override;
-
- ///
- /// Process all commands in the queue.
- ///
- void processCommands();
-
- ///
- /// Process all sources.
- ///
- /// @param buffer Source buffer.
- /// @param len Source length.
- ///
- void processSources(void* buffer, size_t len);
-
- ///
- /// Process audio buffer.
- ///
- /// @param buffer Audio stream buffer.
- /// @param len Length of stream buffer.
- ///
- void processBuffer(void* buffer, size_t len);
-
- ///
- /// Goon process.
- ///
- /// @return True if sucessful, otherwise return false.
- ///
- bool goOnProcess();
-
- ///
- /// Lock audio device.
- ///
- void lock();
-
- ///
- /// Unlock audio device.
- ///
- void unlock();
-
- private:
- singleton(SDLAudio);
-
- ///
- /// SDL audio constructor.
- ///
- SDLAudio() {};
-
- ///
- /// SDL audio destructor.
- ///
- ~SDLAudio() {};
-
- ///
- /// Initialize audio system.
- ///
- /// @param setting Audio setting.
- ///
- bool initSystem(const SettingBase* setting) override;
-
- ///
- /// Quit audio system.
- ///
- void quitSystem() override;
-
- // Audio device id.
- unsigned int audioDevice;
-
- };
-
+ namespace SDL
+ {
+
+#define SDLAUDIO_BITDEPTH 16
+#define SDLAUDIO_BYTEDEPTH (SDLAUDIO_BITDEPTH >> 3)
+#define SDLAUDIO_CHANNELS 2
+
+ ///
+ /// Audio system SDL implementation.
+ ///
+ class SDLAudio : public AudioManager<SDLAudio>
+ {
+ public:
+ ///
+ /// SDL audio setting.
+ ///
+ struct Setting : SettingBase
+ {
+ public:
+ int samplerate; // Ƶ
+ int samples; // sample<=samplerate
+ };
+
+ ///
+ /// Play all sources whose state is playing.
+ ///
+ void play() override;
+
+ ///
+ /// Stop and remove all sources from the queue.
+ ///
+ void stop() override;
+
+ ///
+ /// Pause audio.
+ ///
+ void pause() override;
+
+ ///
+ /// Resume audio.
+ ///
+ void resume() override;
+
+ ///
+ /// Set global audio volume.
+ ///
+ void setVolume(float volume) override;
+
+ ///
+ /// Process all commands in the queue.
+ ///
+ void processCommands();
+
+ ///
+ /// Process all sources.
+ ///
+ /// @param buffer Source buffer.
+ /// @param len Source length.
+ ///
+ void processSources(void* buffer, size_t len);
+
+ ///
+ /// Process audio buffer.
+ ///
+ /// @param buffer Audio stream buffer.
+ /// @param len Length of stream buffer.
+ ///
+ void processBuffer(void* buffer, size_t len);
+
+ ///
+ /// Goon process.
+ ///
+ /// @return True if sucessful, otherwise return false.
+ ///
+ bool goOnProcess();
+
+ ///
+ /// Lock audio device.
+ ///
+ void lock();
+
+ ///
+ /// Unlock audio device.
+ ///
+ void unlock();
+
+ private:
+ singleton(SDLAudio);
+
+ ///
+ /// SDL audio constructor.
+ ///
+ SDLAudio() {};
+
+ ///
+ /// SDL audio destructor.
+ ///
+ ~SDLAudio() {};
+
+ ///
+ /// Initialize audio system.
+ ///
+ /// @param setting Audio setting.
+ ///
+ bool initSystem(const SettingBase* setting) override;
+
+ ///
+ /// Quit audio system.
+ ///
+ void quitSystem() override;
+
+ // Audio device id.
+ unsigned int audioDevice;
+
+ };
+
+ } // namespace SDL
} // namespace Audio
} // namespace JinEngine
diff --git a/src/libjin/Audio/SDL/je_sdl_source.cpp b/src/libjin/Audio/SDL/je_sdl_source.cpp
index 9e09e61..207aa86 100644
--- a/src/libjin/Audio/SDL/je_sdl_source.cpp
+++ b/src/libjin/Audio/SDL/je_sdl_source.cpp
@@ -15,160 +15,163 @@
#include "je_sdl_audio.h"
#include "je_sdl_source.h"
+using namespace JinEngine::Math;
+
namespace JinEngine
{
namespace Audio
{
-
- using namespace JinEngine::Math;
-
- #define BITS 8
-
- typedef struct SDLSourceCommand
- {
- typedef enum Action
- {
- Nothing = 0,
- Play,
- Stop,
- Pause,
- Resume,
- Rewind,
- SetVolume,
- SetLoop,
- SetRate,
- };
- Action action;
- union {
- int _integer;
- float _float;
- bool _boolean;
- const char* _string;
- } parameter;
-
- SDLSource* source;
- };
-
- typedef enum CHANNEL
- {
- MONO = 1, //
- STEREO = 2, //
- };
-
- typedef /*mask*/ enum STATUS
- {
- PLAYING = 1,
- PAUSED = 2,
- STOPPED = 4
- };
-
- #define Command SDLSourceCommand
- #define Action Command::Action
- #define Manager SDLSourceManager
-
- ///*class member*/ std::queue<Command*> Manager::commands;
- ///*class member*/ std::stack<Command*> Manager::commandsPool;
- ///*class member*/ std::vector<SDLSource*> Manager::sources;
- /*class member*/ Manager* Manager::manager = nullptr;
-
- SDLSource* SDLSource::createSource(const char* file)
- {
- std::ifstream fs;
- fs.open(file, std::ios::binary);
- if (!fs.is_open())
- {
- fs.close();
- return nullptr;
- }
- fs.seekg(0,std::ios::end);
- int size = fs.tellg();
- fs.seekg(0, std::ios::beg);
- char* buffer = (char*)malloc(size);
- memset(buffer, 0, size);
- fs.read(buffer, size);
- fs.close();
- SDLSource* source = createSource(buffer, size);
- free(buffer);
- return source;
- }
-
- SDLSource* SDLSource::createSource(void* mem, size_t size)
- {
- if (mem == nullptr)
- return nullptr;
- SDLSource* source = new SDLSource();
- try
- {
- SourceType format = getType(mem, size);
- switch (format)
- {
- case OGG: source->decode_ogg(mem, size); break;
- case WAV: source->decode_wav(mem, size); break;
- }
- }
- catch (SourceException& exp)
- {
- delete source;
- return nullptr;
- };
- return source;
- }
-
- SDLSource::SDLSource()
- {
- memset(&status, 0, sizeof(status));
- memset(&raw, 0, sizeof(raw));
- status.volume = 1;
- }
-
- SDLSource::~SDLSource()
- {
- delete raw.data;
- raw.end = 0;
- raw.data = 0;
- }
-
- void SDLSource::decode_wav(void* mem, int size)
- {
- wav_t wav;
- if (wav_read(&wav, mem, size) == 0)
- {
- raw.data = wav.data;
- raw.length = wav.length * wav.channels * wav.bitdepth / 8;
- raw.channels = clamp<int>(wav.channels, CHANNEL::MONO, CHANNEL::STEREO);
- raw.end = (char*)raw.data + raw.length;
- raw.samplerate = wav.samplerate;
- raw.bitdepth = wav.bitdepth;
- raw.samples = wav.length;
- }
- else
- throw SourceException();
- }
-
- void SDLSource::decode_ogg(void* _mem, int size)
- {
- unsigned char* mem = (unsigned char*)_mem;
- int channels;
- int samplerate;
- short* data = (short*)raw.data;
- int samples = stb_vorbis_decode_memory(
- mem,
- size,
- &channels,
- &samplerate,
- &data
- );
- const int bitdepth = sizeof(short) * BITS;
- raw.channels = channels;
- raw.samplerate = samplerate;
- raw.data = data;
- raw.samples = samples; // һsample
- raw.length = samples * channels * sizeof(short); // һsample
- raw.bitdepth = bitdepth;
- raw.end = (char*)data + raw.length;
- }
-
- #define ActionNone(T)\
+ namespace SDL
+ {
+
+
+#define BITS 8
+
+ typedef struct SDLSourceCommand
+ {
+ typedef enum Action
+ {
+ Nothing = 0,
+ Play,
+ Stop,
+ Pause,
+ Resume,
+ Rewind,
+ SetVolume,
+ SetLoop,
+ SetRate,
+ };
+ Action action;
+ union {
+ int _integer;
+ float _float;
+ bool _boolean;
+ const char* _string;
+ } parameter;
+
+ SDLSource* source;
+ };
+
+ typedef enum CHANNEL
+ {
+ MONO = 1, //
+ STEREO = 2, //
+ };
+
+ typedef /*mask*/ enum STATUS
+ {
+ PLAYING = 1,
+ PAUSED = 2,
+ STOPPED = 4
+ };
+
+#define Command SDLSourceCommand
+#define Action Command::Action
+#define Manager SDLSourceManager
+
+ ///*class member*/ std::queue<Command*> Manager::commands;
+ ///*class member*/ std::stack<Command*> Manager::commandsPool;
+ ///*class member*/ std::vector<SDLSource*> Manager::sources;
+ /*class member*/ Manager* Manager::manager = nullptr;
+
+ SDLSource* SDLSource::createSource(const char* file)
+ {
+ std::ifstream fs;
+ fs.open(file, std::ios::binary);
+ if (!fs.is_open())
+ {
+ fs.close();
+ return nullptr;
+ }
+ fs.seekg(0, std::ios::end);
+ int size = fs.tellg();
+ fs.seekg(0, std::ios::beg);
+ char* buffer = (char*)malloc(size);
+ memset(buffer, 0, size);
+ fs.read(buffer, size);
+ fs.close();
+ SDLSource* source = createSource(buffer, size);
+ free(buffer);
+ return source;
+ }
+
+ SDLSource* SDLSource::createSource(void* mem, size_t size)
+ {
+ if (mem == nullptr)
+ return nullptr;
+ SDLSource* source = new SDLSource();
+ try
+ {
+ SourceType format = getType(mem, size);
+ switch (format)
+ {
+ case OGG: source->decode_ogg(mem, size); break;
+ case WAV: source->decode_wav(mem, size); break;
+ }
+ }
+ catch (SourceException& exp)
+ {
+ delete source;
+ return nullptr;
+ };
+ return source;
+ }
+
+ SDLSource::SDLSource()
+ {
+ memset(&status, 0, sizeof(status));
+ memset(&raw, 0, sizeof(raw));
+ status.volume = 1;
+ }
+
+ SDLSource::~SDLSource()
+ {
+ delete raw.data;
+ raw.end = 0;
+ raw.data = 0;
+ }
+
+ void SDLSource::decode_wav(void* mem, int size)
+ {
+ wav_t wav;
+ if (wav_read(&wav, mem, size) == 0)
+ {
+ raw.data = wav.data;
+ raw.length = wav.length * wav.channels * wav.bitdepth / 8;
+ raw.channels = clamp<int>(wav.channels, CHANNEL::MONO, CHANNEL::STEREO);
+ raw.end = (char*)raw.data + raw.length;
+ raw.samplerate = wav.samplerate;
+ raw.bitdepth = wav.bitdepth;
+ raw.samples = wav.length;
+ }
+ else
+ throw SourceException();
+ }
+
+ void SDLSource::decode_ogg(void* _mem, int size)
+ {
+ unsigned char* mem = (unsigned char*)_mem;
+ int channels;
+ int samplerate;
+ short* data = (short*)raw.data;
+ int samples = stb_vorbis_decode_memory(
+ mem,
+ size,
+ &channels,
+ &samplerate,
+ &data
+ );
+ const int bitdepth = sizeof(short) * BITS;
+ raw.channels = channels;
+ raw.samplerate = samplerate;
+ raw.data = data;
+ raw.samples = samples; // һsample
+ raw.length = samples * channels * sizeof(short); // һsample
+ raw.bitdepth = bitdepth;
+ raw.end = (char*)data + raw.length;
+ }
+
+#define ActionNone(T)\
do{\
Command* cmd = Manager::get()->getCommand();\
cmd->action = Action::T; \
@@ -176,7 +179,7 @@ namespace JinEngine
Manager::get()->pushCommand(cmd); \
} while (0)
- #define ActionArg(T, ARGT, ARG)\
+#define ActionArg(T, ARGT, ARG)\
do{\
Command* cmd = Manager::get()->getCommand();\
cmd->action = Action::T; \
@@ -185,217 +188,217 @@ namespace JinEngine
Manager::get()->pushCommand(cmd); \
}while(0)
- #define ActionInt(T, INT) ActionArg(T, _integer, INT)
- #define ActionFloat(T, FLT) ActionArg(T, _float, FLT)
- #define ActionString(T, STR) ActionArg(T, _string, STR)
- #define ActionBool(T, BOL) ActionArg(T, _boolean, BOL)
-
- void SDLSource::play()
- {
- ActionNone(Play);
- }
-
- void SDLSource::stop()
- {
- ActionNone(Stop);
- }
-
- void SDLSource::pause()
- {
- ActionNone(Pause);
- }
-
- void SDLSource::resume()
- {
- ActionNone(Resume);
- }
-
- void SDLSource::rewind()
- {
- ActionNone(Rewind);
- }
-
- inline bool SDLSource::isStopped() const
- {
- return is(STOPPED);
- }
-
- bool SDLSource::isPaused() const
- {
- return is(PAUSED);
- }
-
- void SDLSource::setPitch(float pitch)
- {
- }
-
- void SDLSource::setVolume(float volume)
- {
- ActionFloat(SetVolume, clamp(volume, 0.0f, 1.0f));
- }
-
- void SDLSource::setLoop(bool loop)
- {
- ActionBool(SetLoop, loop);
- }
-
- void SDLSource::setRate(float rate)
- {
- ActionFloat(SetRate, rate);
- }
-
- inline void SDLSource::handle(
- SDLSourceManager* manager,
- SDLSourceCommand* cmd
- )
- {
- switch (cmd->action)
- {
- case Command::Action::Play:
- manager->removeSource(this);
- manager->pushSource(this);
- status.state = PLAYING;
- status.pos = 0; // rewind
- break;
- case Command::Action::Stop:
- manager->removeSource(this);
- status.state = STOPPED;
- status.pos = 0; // rewind
- break;
- case Command::Action::Pause:
- manager->removeSource(this);
- status.state = PAUSED;
- break;
- case Command::Action::Resume:
- manager->removeSource(this);
- manager->pushSource(this);
- status.state = PLAYING;
- break;
- case Command::Action::Rewind:
- status.state = PLAYING;
- status.pos = 0;
- break;
- case Command::Action::SetVolume:
- status.volume = cmd->parameter._float;
- break;
- case Command::Action::SetLoop:
- status.loop = cmd->parameter._boolean;
- break;
- }
- }
-
- inline void SDLSource::process(void* buf, size_t size)
- {
- short* buffer = (short*)buf; // AUDIO_S16SYS
- int samples = (size / SDLAUDIO_BYTEDEPTH) >> 1; // ˫
- const char L = 0, R = 1;
- for (int i = 0; i < samples; ++i)
- {
- char* source = (char*)raw.data + status.pos * (raw.bitdepth / 8) * raw.channels;
- short l = 0;
- short r = 0;
- if (raw.bitdepth == 16)
- {
- l = ((short*)source)[L] * status.volume;
- r = ((short*)source)[L + raw.channels - 1] * status.volume;
- }
- else if (raw.bitdepth == 8)
- {
- l = source[L] << 8; // << 8 Ŵ16bits
- r = source[L + raw.channels - 1] << 8;
- }
- short* sample = buffer + (i << 1);
- sample[L] = clamp(sample[L] + l, SHRT_MIN, SHRT_MAX); //
- sample[R] = clamp(sample[R] + r, SHRT_MIN, SHRT_MAX); //
- ++status.pos;
- if (status.pos > raw.samples && status.loop)
- status.pos = 0; // rewind
- else if (status.pos > raw.samples && !status.loop)
- break;
- }
- }
-
- Manager* Manager::get()
- {
- return (manager == nullptr ? manager = new Manager() : manager);
- }
-
- void Manager::processCommands()
- {
- Command* cmd = nullptr;
- SDLSource* source = nullptr;
- while (!commands.empty())
- {
- cmd = commands.front();
- if (cmd != nullptr)
- {
- source = cmd->source;
- if (source != nullptr)
- source->handle(manager, cmd);
- }
- commands.pop();
- }
- }
-
- /* AUDIO_S16SYS[size>>1] buffer */
- void Manager::processSources(void* buf, size_t size)
- {
- /* clear render buffer */
- memset(buf, 0, size);
- SDLSource* src = nullptr;
- std::vector<SDLSource*>::iterator it = sources.begin();
- for (; it != sources.end();)
- {
- src = *it;
- if (src != nullptr)
- src->process(buf, size);
- ++it;
- }
- }
-
- void Manager::removeSource(SDLSource* source)
- {
- std::vector<SDLSource*>::iterator it = sources.begin();
- for (it = sources.begin(); it != sources.end(); )
- {
- if (*it == source)
- {
- it = sources.erase(it);
- return;
- }
- ++it;
- }
- }
-
- void Manager::removeAllSource()
- {
- sources.clear();
- }
-
- void Manager::pushSource(SDLSource* source)
- {
- if(source != nullptr)
- sources.push_back(source);
- }
-
- void Manager::pushCommand(SDLSourceCommand* cmd)
- {
- commands.push(cmd);
- }
-
- Command* Manager::getCommand()
- {
- if (!commandsPool.empty())
- {
- Command* cmd = commandsPool.top();
- commandsPool.pop();
- return cmd;
- }
- return new Command();
- }
-
-
+#define ActionInt(T, INT) ActionArg(T, _integer, INT)
+#define ActionFloat(T, FLT) ActionArg(T, _float, FLT)
+#define ActionString(T, STR) ActionArg(T, _string, STR)
+#define ActionBool(T, BOL) ActionArg(T, _boolean, BOL)
+
+ void SDLSource::play()
+ {
+ ActionNone(Play);
+ }
+
+ void SDLSource::stop()
+ {
+ ActionNone(Stop);
+ }
+
+ void SDLSource::pause()
+ {
+ ActionNone(Pause);
+ }
+
+ void SDLSource::resume()
+ {
+ ActionNone(Resume);
+ }
+
+ void SDLSource::rewind()
+ {
+ ActionNone(Rewind);
+ }
+
+ inline bool SDLSource::isStopped() const
+ {
+ return is(STOPPED);
+ }
+
+ bool SDLSource::isPaused() const
+ {
+ return is(PAUSED);
+ }
+
+ void SDLSource::setPitch(float pitch)
+ {
+ }
+
+ void SDLSource::setVolume(float volume)
+ {
+ ActionFloat(SetVolume, clamp(volume, 0.0f, 1.0f));
+ }
+
+ void SDLSource::setLoop(bool loop)
+ {
+ ActionBool(SetLoop, loop);
+ }
+
+ void SDLSource::setRate(float rate)
+ {
+ ActionFloat(SetRate, rate);
+ }
+
+ inline void SDLSource::handle(
+ SDLSourceManager* manager,
+ SDLSourceCommand* cmd
+ )
+ {
+ switch (cmd->action)
+ {
+ case Command::Action::Play:
+ manager->removeSource(this);
+ manager->pushSource(this);
+ status.state = PLAYING;
+ status.pos = 0; // rewind
+ break;
+ case Command::Action::Stop:
+ manager->removeSource(this);
+ status.state = STOPPED;
+ status.pos = 0; // rewind
+ break;
+ case Command::Action::Pause:
+ manager->removeSource(this);
+ status.state = PAUSED;
+ break;
+ case Command::Action::Resume:
+ manager->removeSource(this);
+ manager->pushSource(this);
+ status.state = PLAYING;
+ break;
+ case Command::Action::Rewind:
+ status.state = PLAYING;
+ status.pos = 0;
+ break;
+ case Command::Action::SetVolume:
+ status.volume = cmd->parameter._float;
+ break;
+ case Command::Action::SetLoop:
+ status.loop = cmd->parameter._boolean;
+ break;
+ }
+ }
+
+ inline void SDLSource::process(void* buf, size_t size)
+ {
+ short* buffer = (short*)buf; // AUDIO_S16SYS
+ int samples = (size / SDLAUDIO_BYTEDEPTH) >> 1; // ˫
+ const char L = 0, R = 1;
+ for (int i = 0; i < samples; ++i)
+ {
+ char* source = (char*)raw.data + status.pos * (raw.bitdepth / 8) * raw.channels;
+ short l = 0;
+ short r = 0;
+ if (raw.bitdepth == 16)
+ {
+ l = ((short*)source)[L] * status.volume;
+ r = ((short*)source)[L + raw.channels - 1] * status.volume;
+ }
+ else if (raw.bitdepth == 8)
+ {
+ l = source[L] << 8; // << 8 Ŵ16bits
+ r = source[L + raw.channels - 1] << 8;
+ }
+ short* sample = buffer + (i << 1);
+ sample[L] = clamp(sample[L] + l, SHRT_MIN, SHRT_MAX); //
+ sample[R] = clamp(sample[R] + r, SHRT_MIN, SHRT_MAX); //
+ ++status.pos;
+ if (status.pos > raw.samples && status.loop)
+ status.pos = 0; // rewind
+ else if (status.pos > raw.samples && !status.loop)
+ break;
+ }
+ }
+
+ Manager* Manager::get()
+ {
+ return (manager == nullptr ? manager = new Manager() : manager);
+ }
+
+ void Manager::processCommands()
+ {
+ Command* cmd = nullptr;
+ SDLSource* source = nullptr;
+ while (!commands.empty())
+ {
+ cmd = commands.front();
+ if (cmd != nullptr)
+ {
+ source = cmd->source;
+ if (source != nullptr)
+ source->handle(manager, cmd);
+ }
+ commands.pop();
+ }
+ }
+
+ /* AUDIO_S16SYS[size>>1] buffer */
+ void Manager::processSources(void* buf, size_t size)
+ {
+ /* clear render buffer */
+ memset(buf, 0, size);
+ SDLSource* src = nullptr;
+ std::vector<SDLSource*>::iterator it = sources.begin();
+ for (; it != sources.end();)
+ {
+ src = *it;
+ if (src != nullptr)
+ src->process(buf, size);
+ ++it;
+ }
+ }
+
+ void Manager::removeSource(SDLSource* source)
+ {
+ std::vector<SDLSource*>::iterator it = sources.begin();
+ for (it = sources.begin(); it != sources.end(); )
+ {
+ if (*it == source)
+ {
+ it = sources.erase(it);
+ return;
+ }
+ ++it;
+ }
+ }
+
+ void Manager::removeAllSource()
+ {
+ sources.clear();
+ }
+
+ void Manager::pushSource(SDLSource* source)
+ {
+ if (source != nullptr)
+ sources.push_back(source);
+ }
+
+ void Manager::pushCommand(SDLSourceCommand* cmd)
+ {
+ commands.push(cmd);
+ }
+
+ Command* Manager::getCommand()
+ {
+ if (!commandsPool.empty())
+ {
+ Command* cmd = commandsPool.top();
+ commandsPool.pop();
+ return cmd;
+ }
+ return new Command();
+ }
+
+ } // namespace SDL
} // namespace Audio
} // namespace JinEngine
-#endif // (jin_audio) && (jin_audio == jin_audio_sdl)
+#endif // (jin_audio) && (jin_audio == jin_audio_sdl) \ No newline at end of file
diff --git a/src/libjin/Audio/SDL/je_sdl_source.h b/src/libjin/Audio/SDL/je_sdl_source.h
index 78cae80..42ac255 100644
--- a/src/libjin/Audio/SDL/je_sdl_source.h
+++ b/src/libjin/Audio/SDL/je_sdl_source.h
@@ -14,253 +14,256 @@ namespace JinEngine
{
namespace Audio
{
+ namespace SDL
+ {
- typedef struct SDLSourceCommand;
+ typedef struct SDLSourceCommand;
- class SDLSourceManager;
+ class SDLSourceManager;
- ///
- /// Audio source SDL implementation.
- ///
- class SDLSource : public Source
- {
- public:
///
- /// Create source from raw source data file.
+ /// Audio source SDL implementation.
///
- /// @param file Audio source file.
- /// @return Return source if create successful, otherwise return null.
- ///
- static SDLSource* createSource(const char* file);
-
- ///
- /// Create source from raw source data.
- ///
- /// @param mem Source data.
- /// @param size Source data size.
- /// @return Return source if create successful, otherwise return null.
- ///
- static SDLSource* createSource(void* mem, size_t size);
-
- ///
- /// Source destructor.
- ///
- ~SDLSource();
-
- ///
- /// Play source.
- ///
- void play() override;
-
- ///
- /// Stop source.
- ///
- void stop() override;
-
- ///
- /// Pause source.
- ///
- void pause() override;
-
- ///
- /// Resume source.
- ///
- void resume() override;
-
- ///
- /// Rewind source.
- ///
- void rewind() override;
-
- ///
- /// Return if the source is stopped.
- ///
- /// @return True if the source is stopped, otherwise return false.
- ///
- bool isStopped() const override;
-
- ///
- /// Return if the source is paused.
- ///
- /// @return True if the source is paused(, otherwise return false.
- ///
- bool isPaused() const override;
-
- ///
- /// Set pitch.
- ///
- /// @param pitch Pitch of source.
- ///
- void setPitch(float pitch) override;
-
- ///
- /// Set volume.
- ///
- /// @param volume Volume of source.
- ///
- void setVolume(float volume) override;
-
- ///
- /// Set source loop.
- ///
- /// @param loop Looping or not.
- ///
- void setLoop(bool loop) override;
-
- ///
- /// Set source rate.
- ///
- /// @param rate Rate of source.
- ///
- void setRate(float rate) override;
-
- ///
- /// Handle a specific command.
- ///
- /// @param manager Audio manager.
- /// @param cmd Source commad.
- ///
- inline void handle(SDLSourceManager* manager, SDLSourceCommand* cmd);
-
- ///
- /// Process decoded source data.
- ///
- /// @param buffer Source data.
- /// @param size Data size.
- ///
- inline void process(void* buffer, size_t size);
-
- protected:
- ///
- /// Source constructor.
- ///
- SDLSource();
-
- ///
- /// Decode wav file.
- ///
- /// @param mem Wav file data.
- /// @param size Wav data size.
- ///
- void decode_wav(void* mem, int size);
+ class SDLSource : public Source
+ {
+ public:
+ ///
+ /// Create source from raw source data file.
+ ///
+ /// @param file Audio source file.
+ /// @return Return source if create successful, otherwise return null.
+ ///
+ static SDLSource* createSource(const char* file);
+
+ ///
+ /// Create source from raw source data.
+ ///
+ /// @param mem Source data.
+ /// @param size Source data size.
+ /// @return Return source if create successful, otherwise return null.
+ ///
+ static SDLSource* createSource(void* mem, size_t size);
+
+ ///
+ /// Source destructor.
+ ///
+ ~SDLSource();
+
+ ///
+ /// Play source.
+ ///
+ void play() override;
+
+ ///
+ /// Stop source.
+ ///
+ void stop() override;
+
+ ///
+ /// Pause source.
+ ///
+ void pause() override;
+
+ ///
+ /// Resume source.
+ ///
+ void resume() override;
+
+ ///
+ /// Rewind source.
+ ///
+ void rewind() override;
+
+ ///
+ /// Return if the source is stopped.
+ ///
+ /// @return True if the source is stopped, otherwise return false.
+ ///
+ bool isStopped() const override;
+
+ ///
+ /// Return if the source is paused.
+ ///
+ /// @return True if the source is paused(, otherwise return false.
+ ///
+ bool isPaused() const override;
+
+ ///
+ /// Set pitch.
+ ///
+ /// @param pitch Pitch of source.
+ ///
+ void setPitch(float pitch) override;
+
+ ///
+ /// Set volume.
+ ///
+ /// @param volume Volume of source.
+ ///
+ void setVolume(float volume) override;
+
+ ///
+ /// Set source loop.
+ ///
+ /// @param loop Looping or not.
+ ///
+ void setLoop(bool loop) override;
+
+ ///
+ /// Set source rate.
+ ///
+ /// @param rate Rate of source.
+ ///
+ void setRate(float rate) override;
+
+ ///
+ /// Handle a specific command.
+ ///
+ /// @param manager Audio manager.
+ /// @param cmd Source commad.
+ ///
+ inline void handle(SDLSourceManager* manager, SDLSourceCommand* cmd);
+
+ ///
+ /// Process decoded source data.
+ ///
+ /// @param buffer Source data.
+ /// @param size Data size.
+ ///
+ inline void process(void* buffer, size_t size);
+
+ protected:
+ ///
+ /// Source constructor.
+ ///
+ SDLSource();
+
+ ///
+ /// Decode wav file.
+ ///
+ /// @param mem Wav file data.
+ /// @param size Wav data size.
+ ///
+ void decode_wav(void* mem, int size);
+
+ ///
+ /// Decode ogg file.
+ ///
+ /// @param mem ogg file data.
+ /// @param size ogg data size.
+ ///
+ void decode_ogg(void* mem, int size);
+
+ ///
+ /// Check source state.
+ ///
+ /// @param state State to be checked.
+ /// @return True if state is given state, otherwise return false.
+ ///
+ inline bool is(int state) const
+ {
+ return (status.state & state) == state;
+ }
+
+ // Source data.
+ struct {
+ const void* data; // Ƶ
+ int length; // dataֽڳ
+ const void* end; // dataβ = (unsigned char*)data + size
+ int samplerate; // Ƶ
+ unsigned char bitdepth; // ÿsampleıس
+ int samples; // sample = size / (bitdepth / 8)
+ unsigned char channels; // channel1(mono)2(stereo)
+ } raw;
+ // Procedure controller variable.
+ struct {
+ int pos; // ǰŵsample
+ int pitch; // pitch
+ int state; // ǰ״̬
+ bool loop; // loop or not
+ float volume; //
+ } status;
+
+ };
///
- /// Decode ogg file.
- ///
- /// @param mem ogg file data.
- /// @param size ogg data size.
+ /// Source manager.
///
- void decode_ogg(void* mem, int size);
-
- ///
- /// Check source state.
- ///
- /// @param state State to be checked.
- /// @return True if state is given state, otherwise return false.
- ///
- inline bool is(int state) const
- {
- return (status.state & state) == state;
- }
-
- // Source data.
- struct{
- const void* data; // Ƶ
- int length; // dataֽڳ
- const void* end; // dataβ = (unsigned char*)data + size
- int samplerate; // Ƶ
- unsigned char bitdepth; // ÿsampleıس
- int samples; // sample = size / (bitdepth / 8)
- unsigned char channels; // channel1(mono)2(stereo)
- } raw;
- // Procedure controller variable.
- struct{
- int pos; // ǰŵsample
- int pitch; // pitch
- int state; // ǰ״̬
- bool loop; // loop or not
- float volume; //
- } status;
-
- };
-
- ///
- /// Source manager.
- ///
- class SDLSourceManager
- {
- public:
- ///
- /// Get manager singleton.
- ///
- /// @return Singleton of SDL source manager.
- ///
- static SDLSourceManager* get();
-
- ///
- /// Process commands.
- ///
- void processCommands();
-
- ///
- /// Process sources.
- ///
- /// @param buffer Source data.
- /// @param size Size of source data.
- ///
- void processSources(void* buffer, size_t size);
-
- ///
- /// Clear source queue.
- ///
- /// This function will stop all sources.
- ///
- void removeAllSource();
-
- ///
- /// Remove specific source.
- ///
- /// @param source SDL audio source.
- ///
- void removeSource(SDLSource* source);
-
- ///
- /// Push specific source into queue.
- ///
- /// @param source SDL audio source.
- ///
- void pushSource(SDLSource* source);
-
- ///
- /// Get command from queue.
- ///
- /// @return Command at first place.
- ///
- SDLSourceCommand* getCommand();
-
- ///
- /// Push command.
- ///
- /// @param cmd Spcific command.
- ///
- void pushCommand(SDLSourceCommand* cmd);
-
- private:
- std::queue<SDLSourceCommand*> commands;
- std::stack<SDLSourceCommand*> commandsPool;
- std::vector<SDLSource*> sources; // processing sources
- static SDLSourceManager* manager;
-
- };
-
- class SourceException : public std::exception
- {
- const char* what() const throw ()
- {
- return "Load Source Exception";
- }
- };
-
+ class SDLSourceManager
+ {
+ public:
+ ///
+ /// Get manager singleton.
+ ///
+ /// @return Singleton of SDL source manager.
+ ///
+ static SDLSourceManager* get();
+
+ ///
+ /// Process commands.
+ ///
+ void processCommands();
+
+ ///
+ /// Process sources.
+ ///
+ /// @param buffer Source data.
+ /// @param size Size of source data.
+ ///
+ void processSources(void* buffer, size_t size);
+
+ ///
+ /// Clear source queue.
+ ///
+ /// This function will stop all sources.
+ ///
+ void removeAllSource();
+
+ ///
+ /// Remove specific source.
+ ///
+ /// @param source SDL audio source.
+ ///
+ void removeSource(SDLSource* source);
+
+ ///
+ /// Push specific source into queue.
+ ///
+ /// @param source SDL audio source.
+ ///
+ void pushSource(SDLSource* source);
+
+ ///
+ /// Get command from queue.
+ ///
+ /// @return Command at first place.
+ ///
+ SDLSourceCommand* getCommand();
+
+ ///
+ /// Push command.
+ ///
+ /// @param cmd Spcific command.
+ ///
+ void pushCommand(SDLSourceCommand* cmd);
+
+ private:
+ std::queue<SDLSourceCommand*> commands;
+ std::stack<SDLSourceCommand*> commandsPool;
+ std::vector<SDLSource*> sources; // processing sources
+ static SDLSourceManager* manager;
+
+ };
+
+ class SourceException : public std::exception
+ {
+ const char* what() const throw ()
+ {
+ return "Load Source Exception";
+ }
+ };
+
+ } // namespace SDL
} // namespace Audio
} // namespace JinEngine
diff --git a/src/libjin/Core/je_configuration.h b/src/libjin/Core/je_configuration.h
index d96d5b9..065fbae 100644
--- a/src/libjin/Core/je_configuration.h
+++ b/src/libjin/Core/je_configuration.h
@@ -6,7 +6,7 @@
///
/// Debug output
///
-//#define jin_debug
+#define jin_debug
#define jin_os_windows 0x01
#define jin_os_mac 0x02
diff --git a/src/libjin/Graphics/Font/je_decoder.cpp b/src/libjin/Graphics/Font/je_decoder.cpp
deleted file mode 100644
index 01e1990..0000000
--- a/src/libjin/Graphics/Font/je_decoder.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include "je_decoder.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- /* utf8 byte string to unicode codepoint */
- static const char *utf8toCodepoint(const char *p, unsigned *res) {
- return nullptr;
-
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // decoders
- /////////////////////////////////////////////////////////////////////////////
-
- const void* Utf8::decode(const void* data, Codepoint* res) const
- {
- const char* p = (char*)data;
- unsigned x, mask, shift;
- switch (*p & 0xf0) {
- case 0xf0: mask = 0x07; shift = 18; break;
- case 0xe0: mask = 0x0f; shift = 12; break;
- case 0xc0:
- case 0xd0: mask = 0x1f; shift = 6; break;
- default:
- *res = *p;
- return p + 1;
- }
- x = (*p & mask) << shift;
- do {
- if (*(++p) == '\0') {
- *res = x;
- return p;
- }
- shift -= 6;
- x |= (*p & 0x3f) << shift;
- } while (shift);
- *res = x;
- return p + 1;
- }
-
- const void* Utf8::next(const void* data) const
- {
- const char* p = (char*)data;
- unsigned x, mask, shift;
- switch (*p & 0xf0) {
- case 0xf0: mask = 0x07; shift = 18; break;
- case 0xe0: mask = 0x0f; shift = 12; break;
- case 0xc0:
- case 0xd0: mask = 0x1f; shift = 6; break;
- default:
- return p + 1;
- }
- x = (*p & mask) << shift;
- do {
- if (*(++p) == '\0') {
- return p;
- }
- shift -= 6;
- x |= (*p & 0x3f) << shift;
- } while (shift);
- return p + 1;
- }
- /*
- const void* Utf16::decode(const void* data, Codepoint* res) const
- {
- return nullptr;
- }
-
- const void* Utf16::next(const void* data) const
- {
- return nullptr;
- }
- */
- const void* Ascii::decode(const void* data, Codepoint* res) const
- {
- const char* p = (char*)data;
- *res = *p;
- return p + 1;
- }
-
- const void* Ascii::next(const void* data) const
- {
- const char* p = (char*)data;
- return p + 1;
- }
-
- } // namespace Graphics
-} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/je_decoder.h b/src/libjin/Graphics/Font/je_decoder.h
deleted file mode 100644
index 36cbda7..0000000
--- a/src/libjin/Graphics/Font/je_decoder.h
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef __JE_UTF8_H
-#define __JE_UTF8_H
-
-#include <vector>
-
-#include "je_text.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- ///
- /// Text decoder.
- ///
- class Decoder
- {
- public:
-
- ///
- /// Decode a code unit.
- ///
- /// @param data Code units.
- /// @param codepoint Value of code point.
- /// @return Next code unit location.
- ///
- virtual const void* decode(const void* data, Codepoint* codepoint) const = 0 ;
-
- ///
- /// Get next code unit location.
- ///
- /// @param data Code units.
- /// @return Next code unit location.
- ///
- virtual const void* next(const void* data) const = 0;
-
- };
-
- ///
- /// Utf-8 decoder.
- ///
- class Utf8 : public Decoder
- {
- public:
-
- ///
- /// Decode a code unit.
- ///
- /// @param data Code units.
- /// @param codepoint Value of code point.
- /// @return Next code unit location.
- ///
- const void* decode(const void* data, Codepoint* codepoint) const override;
-
- ///
- /// Get next code unit location.
- ///
- /// @param data Code units.
- /// @return Next code unit location.
- ///
- const void* next(const void* data) const override;
-
- };
-
- ///
- /// Ascii decoder.
- ///
- class Ascii : public Decoder
- {
- public:
-
- ///
- /// Decode a code unit.
- ///
- /// @param data Code units.
- /// @param codepoint Value of code point.
- /// @return Next code unit location.
- ///
- const void* decode(const void* data, Codepoint* codepoint) const override;
-
- ///
- /// Get next code unit location.
- ///
- /// @param data Code units.
- /// @return Next code unit location.
- ///
- const void* next(const void* data) const override;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/je_font.h b/src/libjin/Graphics/Font/je_font.h
deleted file mode 100644
index 42f83b6..0000000
--- a/src/libjin/Graphics/Font/je_font.h
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef __JE_FONT_H
-#define __JE_FONT_H
-
-#include <vector>
-#include "je_text.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- struct Page;
-
- //
- // Font
- // |- TTF
- // |- TextureFont
- //
-
- ///
- /// Base Font class.
- ///
- class Font
- {
- public:
- ///
- /// Font constructor.
- ///
- Font(unsigned fontsize)
- : mFontSize(fontsize)
- {
- }
-
- ///
- /// Font destructor.
- ///
- virtual ~Font() {};
-
- ///
- /// Create page with given text.
- ///
- /// @param text Text to be typesetted.
- /// @param lineheight Line height of text.
- /// @param spacing Spacing between characters. 0 by default.
- /// @return Page if created successfully, otherwise return null.
- ///
- virtual Page* typeset(const Text& text, int lineheight, int spacing = 0) = 0;
-
- ///
- /// Create page with given unicode codepoints.
- ///
- /// @param content Unicode codepoints to be typesetted.
- /// @param lineheight Line height of text.
- /// @param spacing Spacing between characters. 0 by default.
- /// @return Page if created successfully, otherwise return null.
- ///
- virtual Page* typeset(const Content& content, int lineheight, int spacing = 0) = 0;
-
- ///
- /// Render page to given position.
- ///
- /// @param page Page to be rendered.
- /// @param x X value of the position.
- /// @param y Y value of the position.
- ///
- virtual void render(const Page* page, int x, int y) = 0;
-
- ///
- /// Render unicode codepoints to given position.
- ///
- /// @param content Unicode codepoints to be typesetted.
- /// @param x X value of the position.
- /// @param y Y value of the position.
- /// @param lineheight Line height of the content.
- /// @param spacing Spacing between characters.
- ///
- virtual void render(const Content& content, int x, int y, int lineheight, int spacing = 0) = 0;
-
- ///
- /// Render text to given position.
- ///
- /// @param text Text to be rendered.
- /// @param x X value of the position.
- /// @param y Y value of the position.
- /// @param lineheight Line height of the text.
- /// @param spacing Spacing between characters.
- ///
- virtual void render(const Text& text, int x, int y, int lineheight, int spacing = 0) = 0;
-
- ///
- /// Get font size.
- ///
- /// @return Font size.
- ///
- inline unsigned getFontSize() { return mFontSize; };
-
- protected:
-
- unsigned mFontSize;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif // __JE_FONT_H \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/je_page.h b/src/libjin/Graphics/Font/je_page.h
deleted file mode 100644
index fbc297e..0000000
--- a/src/libjin/Graphics/Font/je_page.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef __JE_PAGE_H
-#define __JE_PAGE_H
-
-#include "../../math/je_vector2.hpp"
-
-#include "je_font.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- class Font;
-
- ///
- /// Glyphs data to be rendered.
- ///
- struct GlyphVertex
- {
- int x, y; ///< screen coordinates
- float u, v; ///< normalized texture uv
- };
-
- ///
- /// Glyphs info for reducing draw call.
- ///
- struct GlyphArrayDrawInfo
- {
- GLuint texture; ///< atlas
- unsigned int start; ///< glyph vertex indecies
- unsigned int count; ///< glyph vertex count
- };
-
- ///
- /// Page to be rendered.
- ///
- /// A page is a pre-rendered text struct for reducing draw call. Each page
- /// keeps a font pointer which should not be changed.
- ///
- struct Page
- {
- Font* font;
- std::vector<GlyphArrayDrawInfo> glyphinfolist;
- std::vector<GlyphVertex> glyphvertices;
- Math::Vector2<int> size;
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif // __JE_PAGE_H \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/je_text.cpp b/src/libjin/Graphics/Font/je_text.cpp
deleted file mode 100644
index 75dfc7b..0000000
--- a/src/libjin/Graphics/Font/je_text.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-#include <cstring>
-
-#include "je_text.h"
-#include "je_decoder.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- /////////////////////////////////////////////////////////////////////////////
- // iterator
- /////////////////////////////////////////////////////////////////////////////
-
- Text::Iterator::Iterator(const Iterator& itor)
- : data(itor.data)
- , p(itor.p)
- , encode(itor.encode)
- , length(itor.length)
- {
- switch (encode)
- {
- case Encode::UTF8: decoder = new Utf8(); break;
- case Encode::ASCII: decoder = new Ascii(); break;
- }
- }
-
- Text::Iterator::Iterator(const Encode& _encode, const void* _data, unsigned int _length)
- : data(_data)
- , p(_data)
- , encode(_encode)
- , length(_length)
- {
- switch (encode)
- {
- case Encode::UTF8: decoder = new Utf8(); break;
- case Encode::ASCII: decoder = new Ascii(); break;
- }
- }
-
- Text::Iterator::~Iterator()
- {
- delete decoder;
- }
-
- Codepoint Text::Iterator::get()
- {
- Codepoint codepoint;
- decoder->decode(p, &codepoint);
- return codepoint;
- }
-
- Codepoint Text::Iterator::operator*()
- {
- return get();
- }
- /*
- Text::Iterator Text::Iterator::begin()
- {
- Iterator itor(encode, data, length);
- itor.toBegin();
- return itor;
- }
-
- Text::Iterator Text::Iterator::end()
- {
- Iterator itor(encode, data, length);
- itor.toEnd();
- return itor;
- }
- */
- void Text::Iterator::toBegin()
- {
- p = (const unsigned char*)data;
- }
-
- void Text::Iterator::toEnd()
- {
- p = (const unsigned char*)data + length;
- }
-
- Text::Iterator& Text::Iterator::operator ++()
- {
- p = decoder->next(p);
- return *this;
- }
-
- Text::Iterator Text::Iterator::operator ++(int)
- {
- p = decoder->next(p);
- Iterator itor(encode, data, length);
- itor.p = p;
- return itor;
- }
-
- bool Text::Iterator::operator !=(const Iterator& itor)
- {
- return !(data == itor.data
- && p == itor.p
- && length == itor.length
- && encode == itor.encode);
- }
-
- bool Text::Iterator::operator ==(const Iterator& itor)
- {
- return data == itor.data
- && p == itor.p
- && length == itor.length
- && encode == itor.encode;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // text
- /////////////////////////////////////////////////////////////////////////////
-
- Text::Text(Encode encode, const void* data)
- {
- unsigned length = strlen((const char*)data);
- Iterator end = Iterator(encode, data, length);
- end.toEnd();
- Iterator it = Iterator(encode, data, length);
- for (; it != end; ++it)
- {
- content.push_back(*it);
- }
- }
-
- Text::Text(Encode encode, const void* data, unsigned length)
- {
- Iterator end = Iterator(encode, data, length);
- end.toEnd();
- Iterator it = Iterator(encode, data, length);
- for (; it != end; ++it)
- {
- content.push_back(*it);
- }
- }
-
- Text::~Text()
- {
- }
-
- const Content& Text::getContent() const
- {
- return content;
- }
-
- const Content& Text::operator*() const
- {
- return content;
- }
-
- } // namespace Graphics
-} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/je_text.h b/src/libjin/Graphics/Font/je_text.h
deleted file mode 100644
index 7436875..0000000
--- a/src/libjin/Graphics/Font/je_text.h
+++ /dev/null
@@ -1,169 +0,0 @@
-#ifndef __JE_TEXT_H
-#define __JE_TEXT_H
-
-#include <vector>
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- typedef unsigned int Codepoint;
-
- typedef std::vector<Codepoint> Content;
-
- class Text;
-
- class Decoder;
-
- ///
- /// Supported text encoding.
- ///
- enum Encode
- {
- UTF8, ///< utf-8
- ASCII, ///< ASCII
- };
-
- ///
- /// Decoded text. Saved as unicode codepoints.
- ///
- class Text
- {
- public:
- ///
- ///
- ///
- Text(Encode encode, const void* data);
-
- ///
- ///
- ///
- Text(Encode encode, const void* data, unsigned int length);
-
- ///
- ///
- ///
- ~Text();
-
- ///
- ///
- ///
- const Content& getContent() const;
-
- ///
- ///
- ///
- const Content& operator*() const;
-
- private:
- ///
- ///
- ///
- class Iterator
- {
- public:
-
- ///
- ///
- ///
- Iterator(const Iterator& itor);
-
- ///
- ///
- ///
- Iterator(const Encode& encode, const void* data, unsigned int length);
-
- ///
- ///
- ///
- ~Iterator();
-
- ///
- ///
- ///
- Codepoint get();
-
- //Iterator begin();
- //Iterator end();
-
- ///
- ///
- ///
- void toBegin();
-
- ///
- ///
- ///
- void toEnd();
-
- ///
- ///
- ///
- Codepoint operator *();
-
- ///
- ///
- ///
- Iterator& operator ++();
-
- ///
- ///
- ///
- Iterator operator ++(int);
-
- ///
- ///
- ///
- bool operator !=(const Iterator& itor);
-
- ///
- ///
- ///
- bool operator ==(const Iterator& itor);
-
- private:
-
- ///
- ///
- ///
- void operator = (const Iterator&);
-
- ///
- ///
- ///
- const Encode encode;
-
- ///
- ///
- ///
- const Decoder* decoder;
-
- ///
- ///
- ///
- const void* p;
-
- ///
- ///
- ///
- const void* const data;
-
- ///
- ///
- ///
- unsigned int length;
-
- };
-
- ///
- ///
- ///
- Content content;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/je_texture_font.cpp b/src/libjin/Graphics/Font/je_texture_font.cpp
deleted file mode 100644
index dcebdb2..0000000
--- a/src/libjin/Graphics/Font/je_texture_font.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
-#include <vector>
-
-#include "../../math/je_vector2.hpp"
-
-#include "../shader/je_shader.h"
-
-#include "je_texture_font.h"
-
-using namespace std;
-using namespace JinEngine::Math;
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- TextureFont * TextureFont::createTextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh)
- {
- TextureFont* tf = new TextureFont(bitmap, codepoints, cellw, cellh);
- return tf;
- }
-
- TextureFont * TextureFont::createTextureFont(const Bitmap* bitmap, const Text& codepoints, int cellw, int cellh)
- {
- TextureFont* tf = new TextureFont(bitmap, *codepoints, cellw, cellh);
- return tf;
- }
-
- TextureFont* TextureFont::createTextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh)
- {
- TextureFont* tf = new TextureFont(bitmap, codepoints, mask, cellh);
- return tf;
- }
-
- TextureFont* TextureFont::createTextureFont(const Bitmap* bitmap, const Text& codepoints, Color mask, int cellh)
- {
- TextureFont* tf = new TextureFont(bitmap, *codepoints, mask, cellh);
- return tf;
- }
-
- TextureFont::~TextureFont()
- {
- }
-
- const TextureFont::TextureGlyph* TextureFont::findGlyph(Codepoint codepoint) const
- {
- auto it = glyphs.find(codepoint);
- if (it != glyphs.end())
- {
- return &it->second;
- }
- else
- return nullptr;
- }
-
- Page* TextureFont::typeset(const Content& text, int lineheight, int spacing)
- {
- Page* page = new Page();
- page->font = this;
- vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist;
- vector<GlyphVertex>& glyphvertices = page->glyphvertices;
- int texture = -1;
- const TextureGlyph* glyph = nullptr;
- GlyphVertex vertex;
- Vector2<int> p(0, 0);
- int i = 0;
-
- #define glyphvertices_push(_x, _y, _u, _v) \
- vertex.x = _x; vertex.y = _y;\
- vertex.u = _u; vertex.v = _v;\
- glyphvertices.push_back(vertex);\
-
- for (Codepoint c : text)
- {
- // return
- if (c == 0x0D) continue;
- // newline
- if (c == 0x0A)
- {
- p.y += lineheight;
- p.x = 0;
- continue;
- }
- if (c == 0x09)
- {
- // tab = 4*space
- unsigned cw = getCharWidth(0x20);
- p.x += cw * 4;
- continue;
- }
- glyph = findGlyph(c);
- if (glyph == nullptr) continue;
- if (texture != getGLTexture())
- {
- texture = getGLTexture();
- GlyphArrayDrawInfo info;
- info.start = i;
- info.count = 0;
- info.texture = texture;
- glyphinfolist.push_back(info);
- }
- glyphinfolist[glyphinfolist.size() - 1].count += 4;
- // normalized
- float w = getWidth(), h = getHeight();
- float nx = glyph->x / w, ny = glyph->y / h;
- float nw = glyph->w / w, nh = glyph->h / h;
- glyphvertices_push(p.x, p.y, nx, ny);
- glyphvertices_push(p.x, p.y + glyph->h, nx, ny + nh);
- glyphvertices_push(p.x + glyph->w, p.y + glyph->h, nx + nw, ny + nh);
- glyphvertices_push(p.x + glyph->w, p.y, nx + nw, ny);
- p.x += glyph->w + spacing;
- i += 4;
- }
- getTextBox(text, &page->size.w, &page->size.h, lineheight, spacing);
- return page;
- }
-
- int TextureFont::getCharWidth(int c)
- {
- auto it = glyphs.find(c);
- if (it != glyphs.end())
- {
- return it->second.w;
- }
- return 0;
- }
-
- int TextureFont::getCharHeight(int c)
- {
- auto it = glyphs.find(c);
- if (it != glyphs.end())
- {
- return it->second.h;
- }
- return 0;
- }
-
- int TextureFont::getTextWidth(const Content& t, int spacing)
- {
- int res = 0;
- int tmp = 0;
- for (Codepoint c : t)
- {
- if (c == 0x0D)
- continue;
- if (c == 0x0A)
- {
- tmp = 0;
- continue;
- }
- if (c == 0x09)
- {
- // tab = 4*space
- unsigned cw = getCharWidth(0x20);
- tmp += cw * 4;
- if (tmp > res) res = tmp;
- continue;
- }
- tmp += getCharWidth(c) + spacing;
- if (tmp > res) res = tmp;
- }
- return res;
- }
-
- int TextureFont::getTextHeight(const Content& t, int lineheight)
- {
- int res = 0;
- bool newline = true;
- for (Codepoint c : t)
- {
- if (c == 0x0A)
- newline = true;
- else if (c == 0x0D);
- else if (newline)
- {
- newline = false;
- res += lineheight;
- }
- }
- return res;
- }
-
- void TextureFont::getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing)
- {
- *w = 0;
- *h = 0;
- int tmp = 0;
- bool newline = true;
- for (Codepoint c : text)
- {
- if (c == 0x0D)
- continue;
- if (c == 0x0A)
- {
- tmp = 0;
- newline = true;
- continue;
- }
- else if (newline)
- {
- newline = false;
- *h += lineheight;
- }
- tmp += getCharWidth(c) + spacing;
- if (tmp > *w)
- *w = tmp;
- }
- }
-
- Page* TextureFont::typeset(const Text& text, int lineheight, int spacing)
- {
- return typeset(*text, lineheight, spacing);
- }
-
- void TextureFont::render(const Page* page, int x, int y)
- {
- Shader* shader = Shader::getCurrentShader();
- const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist;
- const vector<GlyphVertex>& glyphvertices = page->glyphvertices;
- gl.ModelMatrix.setTransformation(x, y, 0, 1, 1, 0, 0);
- shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
- shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
- for (int i = 0; i < glyphinfolist.size(); ++i)
- {
- const GlyphArrayDrawInfo& info = glyphinfolist[i];
- shader->bindVertexPointer(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x);
- shader->bindUVPointer(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u);
- gl.bindTexture(info.texture);
- gl.drawArrays(GL_QUADS, 0, info.count);
- gl.bindTexture(0);
- }
- }
-
- void TextureFont::render(const Content& text, int x, int y, int lineheight, int spacing)
- {
- Page* page = typeset(text, lineheight, spacing);
- render(page, x, y);
- delete page;
- }
-
- void TextureFont::render(const Text& text, int x, int y, int lineheight, int spacing)
- {
- Page* page = typeset(text, lineheight, spacing);
- render(page, x, y);
- delete page;
- }
-
- TextureFont::TextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh)
- : Graphic(bitmap)
- , Font(cellh)
- {
- TextureGlyph glyph;
- Vector2<int> count(bitmap->getWidth() / cellw, bitmap->getHeight() / cellh);
- glyph.w = cellw;
- glyph.h = cellh;
- for (int y = 0; y < count.row; ++y)
- {
- glyph.y = y * cellh;
- for (int x = 0; x < count.colum; ++x)
- {
- glyph.x = x * cellw;
- if (x + y * count.colum >= codepoints.size())
- return;
- glyphs.insert(std::pair<Codepoint, TextureGlyph>(codepoints[x + y * count.colum], glyph));
- }
- }
- }
-
- TextureFont::TextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh)
- : Graphic(bitmap)
- , Font(cellh)
- {
- TextureGlyph glyph;
- glyph.h = cellh;
- int w = bitmap->getWidth();
- int h = bitmap->getHeight();
- int i = 0;
- for (int y = 0; y < h; y += cellh)
- {
- glyph.y = y;
- bool newc = false;
- for (int x = 0; x <= w; ++x)
- {
- if (x == w && newc)
- {
- glyph.w = x - glyph.x;
- if (i >= codepoints.size())
- return;
- glyphs.insert(std::pair<Codepoint, TextureGlyph>(codepoints[i], glyph));
- ++i;
- newc = false;
- break;
- }
- Color c = bitmap->getPixels()[x + y * w];
- if (!newc && c != mask)
- {
- glyph.x = x;
- newc = true;
- }
- else if (newc && c == mask)
- {
- glyph.w = x - glyph.x;
- if (i >= codepoints.size())
- return;
- glyphs.insert(std::pair<Codepoint, TextureGlyph>(codepoints[i], glyph));
- if (codepoints[i] == 't')
- {
- int a = 10;
- }
- ++i;
- newc = false;
- }
- }
- }
- }
-
- }
-} \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/je_texture_font.h b/src/libjin/Graphics/Font/je_texture_font.h
deleted file mode 100644
index fb74eca..0000000
--- a/src/libjin/Graphics/Font/je_texture_font.h
+++ /dev/null
@@ -1,139 +0,0 @@
-#ifndef __JE_TEXTURE_FONT_H
-#define __JE_TEXTURE_FONT_H
-
-#include <map>
-#include <vector>
-
-#include "../../math/je_vector4.hpp"
-
-#include "../je_graphic.h"
-#include "../je_bitmap.h"
-
-#include "je_page.h"
-#include "je_font.h"
-#include "je_text.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- ///
- ///
- ///
- class TextureFont : public Font , public Graphic
- {
- public:
-
- ///
- ///
- ///
- static TextureFont* createTextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh);
-
- ///
- ///
- ///
- static TextureFont* createTextureFont(const Bitmap* bitmap, const Text& text, int cellw, int cellh);
-
- ///
- ///
- ///
- static TextureFont* createTextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh);
-
- ///
- ///
- ///
- static TextureFont* createTextureFont(const Bitmap* bitmap, const Text& text, Color mask, int cellh);
-
- ///
- ///
- ///
- ~TextureFont();
-
- ///
- ///
- ///
- Page* typeset(const Text& text, int lineheight, int spacing = 0) override;
-
- ///
- ///
- ///
- Page* typeset(const Content& text, int lineheight, int spacing = 0) override ;
-
- ///
- ///
- ///
- void render(const Page* page, int x, int y) override;
-
- ///
- ///
- ///
- void render(const Content& text, int x, int y, int linehgiht, int spacing = 0) override;
-
- ///
- ///
- ///
- void render(const Text& text, int x, int y, int lineheight, int spacing = 0)override;
-
- private:
-
- ///
- ///
- ///
- struct TextureGlyph
- {
- float x, y, w, h;
- };
-
- ///
- ///
- ///
- TextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh);
-
- ///
- ///
- ///
- TextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh);
-
- ///
- ///
- ///
- int getCharWidth(int c);
-
- ///
- ///
- ///
- int getCharHeight(int c);
-
- ///
- ///
- ///
- int getTextWidth(const Content& text, int spacing = 0);
-
- ///
- ///
- ///
- int getTextHeight(const Content& text, int lineheight);
-
- ///
- ///
- ///
- void getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing = 0);
-
- ///
- ///
- ///
- const TextureGlyph* findGlyph(Codepoint codepoint) const;
-
-
- ///
- ///
- ///
- std::map<Codepoint, TextureGlyph> glyphs;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/je_ttf.cpp b/src/libjin/Graphics/Font/je_ttf.cpp
deleted file mode 100644
index 52547c9..0000000
--- a/src/libjin/Graphics/Font/je_ttf.cpp
+++ /dev/null
@@ -1,463 +0,0 @@
-#include "../../core/je_configuration.h"
-#if defined(jin_graphics)
-
-#include <stdio.h>
-
-#include "../../common/je_array.hpp"
-
-#include "../je_gl.h"
-#include "../je_color.h"
-#include "../shader/je_shader.h"
-
-#include "je_ttf.h"
-#include "je_page.h"
-
-#define STB_TRUETYPE_IMPLEMENTATION
-#include "stb/stb_truetype.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- /////////////////////////////////////////////////////////////////////////////
- // TTFData
- /////////////////////////////////////////////////////////////////////////////
-
- TTFData* TTFData::createTTFData(const unsigned char* data, unsigned int size)
- {
- TTFData* ttf = nullptr;
- try
- {
- ttf = new TTFData(data, size);
- return ttf;
- }
- catch (...)
- {
- return nullptr;
- }
- }
-
- TTFData::TTFData(const unsigned char* d, unsigned int s)
- {
- raw.size = s;
- raw.data = (unsigned char*)malloc(s);
- memcpy(raw.data, d, s);
- if (!stbtt_InitFont(&info, (const unsigned char*)raw.data, 0))
- {
- delete raw.data;
- throw 0;
- }
- /* push default fontsize */
- pushTTFsize(FONT_SIZE);
- }
-
- TTFData::~TTFData()
- {
- free(raw.data);
- }
-
- TTF* TTFData::createTTF(unsigned fontSize)
- {
- TTF* ttf;
- try
- {
- ttf = new TTF(this, fontSize);
- }
- catch (...)
- {
- return nullptr;
- }
- return ttf;
- }
-
- /*
- * (0, 0)
- * +--------------+ ascent
- * | +--------+ |
- * | | | |
- * | | bitmap | |
- * +--|--------|--+ baseline
- * | +--------+ |
- * +--|-----------+ decent
- * | |
- * leftSideBearing |
- * advanceWidth
- */
- void TTFData::getVMetrics(int* baseline, int* descent)
- {
- float scale = scales.back();
- int ascent;
- stbtt_GetFontVMetrics(&info, &ascent, descent, 0);
- *baseline = (int)(ascent*scale) + 1; // slight adjustment
- *descent = *baseline - (int)(*descent*scale) + 1;
- }
-
- void TTFData::getHMetrics(unsigned int codepoint, int* advanceWidth, int* leftSideBearing)
- {
- float scale = scales.back();
- int adw, lsb;
- stbtt_GetCodepointHMetrics(&info, codepoint, &adw, &lsb);
- *advanceWidth = (int)(adw*scale);
- *leftSideBearing = (int)(lsb*scale);
- }
-
- void TTFData::pushTTFsize(unsigned int fs)
- {
- float sc = stbtt_ScaleForPixelHeight(&info, fs);
- scales.push_back(sc);
- }
-
- void TTFData::popTTFsize()
- {
- /* always keep default ttf size on the bottom of stack */
- if (scales.size() > 1)
- scales.pop_back();
- }
-
- Channel* TTFData::getCodepointBitmapAlpha(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const
- {
- float scale = scales.back();
- Channel* bitmap = stbtt_GetCodepointBitmap(&info, scale, scale, codepoint, width, height, xoff, yoff);
- return bitmap;
- }
-
- Color* TTFData::getCodepointBitmap(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const
- {
- float scale = scales.back();
- Channel* bitmap = stbtt_GetCodepointBitmap(&info, scale, scale, codepoint, width, height, xoff, yoff);
- int w = *width, h = *height;
- //int xo = *xoff, yo = *yoff;
- Color* bitmap32 = new Color[w*h];
- for (int y = 0; y < h; ++y)
- {
- for (int x = 0; x < w; ++x)
- {
- bitmap32[x + y * w].set(0xff, 0xff, 0xff, bitmap[x + y * w]);
- }
- }
- free(bitmap);
- return bitmap32;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // TTF
- /////////////////////////////////////////////////////////////////////////////
-
- #include "../shader/shaders/je_font.shader.h"
-
- using namespace std;
- using namespace JinEngine::Math;
-
- const int TTF::TEXTURE_WIDTHS[] = { 128, 256, 256, 512, 512, 1024, 1024 };
- const int TTF::TEXTURE_HEIGHTS[] = { 128, 128, 256, 256, 512, 512, 1024 };
-
- /* little endian unicode */
- static const char* unicodeLittleEndian(const char* p, unsigned* res)
- {
- }
-
- ///*static*/ TTF* TTF::createTTF(TTFData* fontData, unsigned int fontSzie)
- //{
- // TTF* ttf;
- // try
- // {
- // ttf = new TTF(fontData, fontSzie);
- // }
- // catch (...)
- // {
- // return nullptr;
- // }
- // return ttf;
- //}
-
- TTF::TTF(TTFData* f, unsigned int fontSize)
- : Font(fontSize)
- , cursor(0, 0)
- , ttf(f)
- {
- ttf->pushTTFsize(fontSize);
- ttf->getVMetrics(&baseline, &descent);
- estimateSize();
- ttf->popTTFsize();
- /* create a default texture */
- createAtlas();
- }
-
- /* estimate the size of atlas texture */
- void TTF::estimateSize()
- {
- for (int level = 0; level <= TEXTURE_SIZE_LEVEL_MAX; ++level)
- {
- if (descent * (descent*0.8) * 96 <= TEXTURE_WIDTHS[level] * TEXTURE_HEIGHTS[level])
- {
- textureWidth = TEXTURE_WIDTHS[level];
- textureHeight = TEXTURE_HEIGHTS[level];
- break;
- }
- }
- }
-
- TTF::~TTF()
- {
- }
-
- GLuint TTF::createAtlas()
- {
- GLuint t;
- gl.flushError();
- t = gl.genTexture();
- gl.bindTexture(t);
- gl.setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl.setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl.setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl.setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl.texImage(GL_RGBA8, textureWidth, textureHeight, GL_RGBA, GL_UNSIGNED_BYTE);
- if (glGetError() != GL_NO_ERROR)
- {
- glDeleteTextures(1, &t);
- gl.bindTexture(0);
- return 0;
- }
- atlases.push_back(t);
- gl.bindTexture(0);
- return t;
- }
-
- void TTF::render(const Content& t, int x, int y, int lineheight, int spacing)
- {
- Page* page = typeset(t, lineheight, spacing);
- render(page, x, y);
- delete page;
- }
-
- Page* TTF::typeset(const Content& text, int lineheight, int spacing)
- {
- Page* page = new Page();
- page->font = this;
- vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist;
- vector<GlyphVertex>& glyphvertices = page->glyphvertices;
- int texture = -1;
- TTFGlyph* glyph = nullptr;
- GlyphVertex vertex;
- Vector2<int> p(0, 0);
- int i = 0;
-
- #define glyphvertices_push(_x, _y, _u, _v) \
- vertex.x = _x; vertex.y = _y;\
- vertex.u = _u; vertex.v = _v;\
- glyphvertices.push_back(vertex);
-
- #define glyphlize(c)\
- do{\
- glyph = &findGlyph(c); \
- if (texture != glyph->atlas) \
- { \
- GlyphArrayDrawInfo info; \
- info.start = i; \
- info.count = 0; \
- info.texture = glyph->atlas; \
- texture = glyph->atlas; \
- glyphinfolist.push_back(info); \
- } \
- glyphinfolist[glyphinfolist.size() - 1].count += 4; \
- TTFGlyph::Bbox& bbox = glyph->bbox; \
- glyphvertices_push(p.x, p.y, bbox.x, bbox.y); \
- glyphvertices_push(p.x, p.y + glyph->height, bbox.x, bbox.y + bbox.h); \
- glyphvertices_push(p.x + glyph->width, p.y + glyph->height, bbox.x + bbox.w, bbox.y + bbox.h); \
- glyphvertices_push(p.x + glyph->width, p.y, bbox.x + bbox.w, bbox.y); \
- }while(0)
-
- for (Codepoint c : text)
- {
- if (c == 0x0D)
- continue;
- if (c == 0x0A)
- {
- /* new line */
- p.y += lineheight;
- p.x = 0;
- continue;
- }
- if (c == 0x09)
- {
- // tab = 4*space
- unsigned cw = getCharWidth(0x20);
- p.x += cw * 4;
- continue;
- }
- glyphlize(c);
- p.x += glyph->width + spacing;
- i += 4;
- }
- getTextBox(text, &page->size.w, &page->size.h, lineheight, spacing);
- return page;
- }
-
- Page* TTF::typeset(const Text& text, int lineheight, int spacing)
- {
- return typeset(*text, lineheight, spacing);
- }
-
- void TTF::render(const Page* page, int x, int y)
- {
- Shader* shader = Shader::getCurrentShader();
- const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist;
- const vector<GlyphVertex>& glyphvertices = page->glyphvertices;
- gl.ModelMatrix.setTransformation(x, y, 0, 1, 1, 0, 0);
- shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
- shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
- for (int i = 0; i < glyphinfolist.size(); ++i)
- {
- const GlyphArrayDrawInfo& info = glyphinfolist[i];
- shader->bindVertexPointer(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x);
- shader->bindUVPointer(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u);
- gl.bindTexture(info.texture);
- gl.drawArrays(GL_QUADS, 0, info.count);
- gl.bindTexture(0);
- }
- }
-
- void TTF::render(const Text& text, int x, int y, int lineheight, int spacing /* = 0 */)
- {
- render(*text, x, y, lineheight, spacing);
- }
-
- int TTF::getCharWidth(int c)
- {
- int adw, lsb;
- ttf->pushTTFsize(mFontSize);
- ttf->getHMetrics(c, &adw, &lsb);
- ttf->popTTFsize();
- return adw;
- }
-
- int TTF::getCharHeight(int c)
- {
- return descent;
- }
-
- int TTF::getTextWidth(const Content& t, int spacing)
- {
- ttf->pushTTFsize(mFontSize);
- int res = 0;
- int tmp = 0;
- for (Codepoint c : t)
- {
- if (c == 0x0D)
- continue;
- if (c == 0x0A)
- {
- tmp = 0;
- continue;
- }
- tmp += getCharWidth(c) + spacing;
- if (tmp > res)
- res = tmp;
- }
- ttf->popTTFsize();
- return res;
- }
-
- int TTF::getTextHeight(const Content& t, int lineheight)
- {
- ttf->pushTTFsize(mFontSize);
- int res = 0;
- bool newline = true;
- for (Codepoint c : t)
- {
- if (c == 0x0A)
- newline = true;
- else if (c == 0x0D);
- else if (newline)
- {
- newline = false;
- res += lineheight;
- }
- }
- ttf->popTTFsize();
- return res;
- }
-
- void TTF::getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing)
- {
- ttf->pushTTFsize(mFontSize);
- *w = 0;
- *h = 0;
- int tmp = 0;
- bool newline = true;
- for (Codepoint c : text)
- {
- if (c == 0x0D)
- continue;
- if (c == 0x0A)
- {
- tmp = 0;
- newline = true;
- continue;
- }
- else if (newline)
- {
- newline = false;
- *h += lineheight;
- }
- tmp += getCharWidth(c) + spacing;
- if (tmp > *w)
- *w = tmp;
- }
- ttf->popTTFsize();
- }
-
- TTF::TTFGlyph& TTF::bakeGlyph(unsigned int character)
- {
- int w, h, xoff, yoff;
- ttf->pushTTFsize(mFontSize);
- GLuint atlas = atlases.back();
- const Color* bitmap = ttf->getCodepointBitmap(character, &w, &h, &xoff, &yoff);
- int adw, lsb;
- {
- /* bake glyph */
- ttf->getHMetrics(character, &adw, &lsb);
- ttf->popTTFsize();
- if (cursor.x + adw > textureWidth )
- {
- cursor.x = 0;
- cursor.y += descent;
- if (cursor.y + descent * 2 > textureHeight)
- {
- /* create new atlas */
- atlas = createAtlas();
- cursor.y = 0;
- }
- }
- gl.bindTexture(atlas);
- gl.texSubImage(cursor.x + xoff, cursor.y + yoff + baseline, w, h, GL_RGBA, GL_UNSIGNED_BYTE, bitmap);
- gl.bindTexture();
- delete[] bitmap;
- }
- TTFGlyph glyph;
- glyph.atlas = atlas;
- glyph.bbox.x = cursor.x / (float)textureWidth;
- glyph.bbox.y = cursor.y / (float)textureHeight;
- glyph.bbox.w = adw / (float)textureWidth;
- glyph.bbox.h = descent / (float)textureHeight;
- glyph.width = adw;
- glyph.height = descent;
- glyphs.insert(std::pair<unsigned int, TTFGlyph>(character, glyph));
- cursor.x += adw;
- return glyphs[character];
- }
-
- TTF::TTFGlyph& TTF::findGlyph(unsigned int character)
- {
- map<unsigned int, TTFGlyph>::iterator it = glyphs.find(character);
- if (it != glyphs.end())
- return it->second;
- else
- return bakeGlyph(character);
- }
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif // defined(jin_graphics) \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/je_ttf.h b/src/libjin/Graphics/Font/je_ttf.h
deleted file mode 100644
index b2c1802..0000000
--- a/src/libjin/Graphics/Font/je_ttf.h
+++ /dev/null
@@ -1,289 +0,0 @@
-#ifndef __JETTF_H
-#define __JE_TTF_H
-#include "../../core/je_configuration.h"
-#if defined(jin_graphics)
-
-#include <vector>
-#include <map>
-
-#include "stb/stb_truetype.h"
-
-#include "../../math/je_quad.h"
-
-#include "../je_color.h"
-#include "../je_graphic.h"
-
-#include "je_page.h"
-#include "je_font.h"
-#include "je_text.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- class TTF;
-
- //
- // TTFData
- // |- TTF(14px)
- // |- TTF(15px)
- // .
- // .
- // .
- //
- class TTFData
- {
- public:
-
- ///
- ///
- ///
- static TTFData* createTTFData(const unsigned char* data, unsigned int size);
-
- ///
- ///
- ///
- ~TTFData();
-
- ///
- ///
- ///
- TTF* createTTF(unsigned ttfsize);
-
- ///
- ///
- ///
- void pushTTFsize(unsigned ttfsize);
-
- ///
- ///
- ///
- void popTTFsize();
-
- ///
- ///
- ///
- Channel* getCodepointBitmapAlpha(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const;
-
- ///
- ///
- ///
- Color* getCodepointBitmap(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const;
-
- ///
- ///
- ///
- void getVMetrics(int* baseline, int* descent);
-
- ///
- ///
- ///
- void getHMetrics(unsigned int codepoint, int* advanceWidth, int* leftSideBearing);
-
- private:
-
- ///
- ///
- ///
- static const unsigned int FONT_SIZE = 12;
-
- ///
- ///
- ///
- TTFData(const unsigned char* data, unsigned int size);
-
- ///
- ///
- ///
- stbtt_fontinfo info;
-
- ///
- ///
- ///
- struct
- {
- unsigned char* data;
- unsigned int size;
- } raw;
-
- ///
- ///
- ///
- std::vector<float> scales;
-
- };
-
- class TTF : public Font
- {
- public:
- //static TTF* createTTF(TTFData* ttfData, unsigned ttfSzie);
-
- ///
- ///
- ///
- Page* typeset(const Text& text, int lineheight, int spacing = 0) override;
-
- ///
- ///
- ///
- Page* typeset(const Content& text, int lineheight, int spacing = 0) override;
-
- ///
- ///
- ///
- void render(const Text& text, int x, int y, int lineheight, int spacing = 0) override;
-
- ///
- ///
- ///
- void render(const Content& text, int x, int y, int lineheight, int spacing = 0) override;
-
- ///
- ///
- ///
- void render(const Page* page, int x, int y) override;
-
- ///
- ///
- ///
- ~TTF();
-
- private:
-
- friend class TTFData;
-
- ///
- ///
- ///
- struct TTFGlyph
- {
- GLuint atlas;
- // normalized coordinates
- struct Bbox
- {
- float x, y;
- float w, h;
- } bbox;
- // glyph size in pixel
- unsigned int width, height;
- };
-
- ///
- ///
- ///
- static const int TEXTURE_SIZE_LEVELS_COUNT = 7;
-
- ///
- ///
- ///
- static const int TEXTURE_SIZE_LEVEL_MAX = TEXTURE_SIZE_LEVELS_COUNT - 1;
-
- ///
- ///
- ///
- static const int TEXTURE_WIDTHS[TEXTURE_SIZE_LEVELS_COUNT];
-
- ///
- ///
- ///
- static const int TEXTURE_HEIGHTS[TEXTURE_SIZE_LEVELS_COUNT];
-
- ///
- ///
- ///
- TTF(TTFData* ttf, Codepoint ttfSize);
-
- ///
- ///
- ///
- void estimateSize();
-
- ///
- ///
- ///
- GLuint createAtlas();
-
- ///
- ///
- ///
- TTFGlyph& bakeGlyph(Codepoint character);
-
- ///
- ///
- ///
- TTFGlyph& findGlyph(Codepoint character);
-
- ///
- ///
- ///
- int getCharWidth(int c);
-
- ///
- ///
- ///
- int getCharHeight(int c);
-
- ///
- ///
- ///
- int getTextWidth(const Content& text, int spacing = 0);
-
- ///
- ///
- ///
- int getTextHeight(const Content& text, int lineheight);
-
- ///
- ///
- ///
- void getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing = 0);
-
- ///
- ///
- ///
- int textureWidth;
-
- ///
- ///
- ///
- int textureHeight;
-
- ///
- ///
- ///
- std::vector<GLuint> atlases;
-
- ///
- ///
- ///
- std::map<Codepoint, TTFGlyph> glyphs;
-
- ///
- ///
- ///
- TTFData* ttf;
-
- ///
- ///
- ///
- int baseline;
-
- ///
- ///
- ///
- int descent;
-
- ///
- ///
- ///
- Math::Vector2<float> cursor;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif // defined(jin_graphics)
-
-#endif // __JE_FONT_H \ No newline at end of file
diff --git a/src/libjin/Graphics/Shader/je_jsl_compiler.cpp b/src/libjin/Graphics/Shader/je_jsl_compiler.cpp
deleted file mode 100644
index 81b14e8..0000000
--- a/src/libjin/Graphics/Shader/je_jsl_compiler.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "../../core/je_configuration.h"
-#if defined(jin_graphics) && (jin_graphics & jin_graphics_shader)
-
-#include "../../Filesystem/je_buffer.h"
-
-#include "je_jsl_compiler.h"
-
-using namespace std;
-using namespace JinEngine::Filesystem;
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
-#include "je_base.shader.h"
-
- bool JSLCompiler::compile(const string& jsl, string* vertex_shader, string* fragment_shader)
- {
- // parse shader source, need some optimizations
- int loc_VERTEX_SHADER = jsl.find("#VERTEX_SHADER");
- int loc_END_VERTEX_SHADER = jsl.find("#END_VERTEX_SHADER");
- int loc_FRAGMENT_SHADER = jsl.find("#FRAGMENT_SHADER");
- int loc_END_FRAGMENT_SHADER = jsl.find("#END_FRAGMENT_SHADER");
- if (loc_VERTEX_SHADER == string::npos
- || loc_END_VERTEX_SHADER == string::npos
- || loc_FRAGMENT_SHADER == string::npos
- || loc_END_FRAGMENT_SHADER == string::npos
- )
- return false;
- // Load vertex and fragment shader source into buffers.
- {
- // Compile JSL vertex program.
- int start = loc_VERTEX_SHADER + strlen("#VERTEX_SHADER");
- *vertex_shader = jsl.substr(start, loc_END_VERTEX_SHADER - start);
- Buffer vbuffer = Buffer(vertex_shader->length() + BASE_VERTEX_SHADER_SIZE);
- formatVertexShader((char*)&vbuffer, vertex_shader->c_str());
- vertex_shader->assign((char*)&vbuffer);
- }
- {
- // Compile JSL fragment program.
- int start = loc_FRAGMENT_SHADER + strlen("#FRAGMENT_SHADER");
- *fragment_shader = jsl.substr(start, loc_END_FRAGMENT_SHADER - start);
- Buffer fbuffer = Buffer(fragment_shader->length() + BASE_FRAGMENT_SHADER_SIZE);
- formatFragmentShader((char*)&fbuffer, fragment_shader->c_str());
- fragment_shader->assign((char*)&fbuffer);
- }
- return true;
- }
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif // (jin_graphics) && (jin_graphics & jin_graphics_shader) \ No newline at end of file
diff --git a/src/libjin/Graphics/Shader/je_jsl_compiler.h b/src/libjin/Graphics/Shader/je_jsl_compiler.h
deleted file mode 100644
index 29129e1..0000000
--- a/src/libjin/Graphics/Shader/je_jsl_compiler.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __JE_JSL_COMPILER_H
-#define __JE_JSL_COMPILER_H
-
-#include "../../core/je_configuration.h"
-#if defined(jin_graphics) && (jin_graphics & jin_graphics_shader)
-
-#include <string>
-
-#include "../../common/je_singleton.hpp"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- ///
- /// Compile JSL into GLSL.
- ///
- class JSLCompiler : public Singleton<JSLCompiler>
- {
- public:
- ///
- /// Compile JSL shader source into GLSL.
- ///
- /// @param jsl JSL shader source.
- /// @param glsl_vertex Output of vertex glsl shader source.
- /// @param glsl_fragment Output of fragment glsl shader source.
- /// @return True if compile successful, otherwise return false.
- ///
- bool compile(const std::string& jsl, std::string* glsl_vertex, std::string* glsl_fragment);
-
- private:
- singleton(JSLCompiler);
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif // (jin_graphics) && (jin_graphics & jin_graphics_shader)
-
-#endif // __JE_JSL_COMPILER_H \ No newline at end of file
diff --git a/src/libjin/Graphics/Shader/je_shader.cpp b/src/libjin/Graphics/Shader/je_shader.cpp
deleted file mode 100644
index 8e909d8..0000000
--- a/src/libjin/Graphics/Shader/je_shader.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-#include "../../core/je_configuration.h"
-#if defined(jin_graphics) && (jin_graphics & jin_graphics_shader)
-
-#include <iostream>
-
-#include "../../filesystem/je_buffer.h"
-#include "../../utils/je_macros.h"
-
-#include "je_jsl_compiler.h"
-#include "je_shader.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- using namespace std;
- using namespace JinEngine::Filesystem;
-
- //
- // default_texture
- // base_shader
- // SHADER_FORMAT_SIZE
- // formatShader
- //
- #include "shaders/je_default.shader.h"
-
- //
- // https://stackoverflow.com/questions/27941496/use-sampler-without-passing-through-value
- // The default value of a sampler variable is 0. From the GLSL 3.30 spec,
- // section "4.3.5 Uniforms":
- //
- // The link time initial value is either the value of the variable's
- // initializer, if present, or 0 if no initializer is present.Sampler
- // types cannot have initializers.
- //
- // Since a value of 0 means that it's sampling from texture unit 0, it will
- // work without ever setting the value as long as you bind your textures to
- // unit 0. This is well defined behavior.
- //
- // Since texture unit 0 is also the default until you call glActiveTexture()
- // with a value other than GL_TEXTURE0, it's very common to always use unit
- // 0 as long as shaders do not need more than one texture.Which means that
- // often times, setting the sampler uniforms is redundant for simple
- // applications.
- //
- // I would still prefer to always set the values.If nothing else, it makes
- // it clear to anybody reading your code that you really mean to sample from
- // texture unit 0, and did not just forget to set the value.
- //
- const int DEFAULT_TEXTURE_UNIT = 0;
-
- /*static*/ Shader* Shader::CurrentShader = nullptr;
-
- Shader* Shader::createShader(const string& program)
- {
- Shader* shader = nullptr;
- try
- {
- shader = new Shader(program);
- }
- catch(...)
- {
- return nullptr;
- }
- return shader;
- }
-
- Shader::Shader(const string& program)
- : mCurrentTextureUnit(DEFAULT_TEXTURE_UNIT)
- {
- if (!compile(program))
- throw 0;
- }
-
- Shader::~Shader()
- {
- if (CurrentShader == this)
- unuse();
- // delete shader program
- glDeleteShader(mPID);
- }
-
- bool Shader::compile(const string& program)
- {
- string vertex_shader, fragment_shader;
- // Compile JSL shader source into GLSL shader source.
- JSLCompiler* compiler = JSLCompiler::get();
- if (!compiler->compile(program, &vertex_shader, &fragment_shader))
- {
- return false;
- }
-#define glsl(SHADER_MODE, SHADER, SRC) \
-do{ \
-const GLchar* src = SRC.c_str(); \
-glShaderSource(SHADER, 1, &src, NULL); \
-glCompileShader(SHADER); \
-GLint success; \
-glGetShaderiv(SHADER, GL_COMPILE_STATUS, &success); \
-if (success == GL_FALSE) \
- return false; \
-}while(0)
- // Compile vertex shader.
- GLuint vid = glCreateShader(GL_VERTEX_SHADER);
- glsl(GL_VERTEX_SHADER, vid, vertex_shader);
- // Compile fragment shader.
- GLuint fid = glCreateShader(GL_FRAGMENT_SHADER);
- glsl(GL_FRAGMENT_SHADER, fid, fragment_shader);
-#undef glsl
- // Create OpenGL shader program.
- mPID = glCreateProgram();
- glAttachShader(mPID, vid);
- glAttachShader(mPID, fid);
- glLinkProgram(mPID);
- GLint success;
- glGetProgramiv(mPID, GL_LINK_STATUS, &success);
- if (success == GL_FALSE)
- return false;
- }
-
- static inline GLint getMaxTextureUnits()
- {
- GLint maxTextureUnits = 0;
- glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
- return maxTextureUnits;
- }
-
- void Shader::use()
- {
- glUseProgram(mPID);
- CurrentShader = this;
- sendInt(SHADER_MAIN_TEXTURE, DEFAULT_TEXTURE_UNIT);
- }
-
- /*static*/ void Shader::unuse()
- {
- glUseProgram(0);
- CurrentShader = nullptr;
- }
-
- GLint Shader::claimTextureUnit(const std::string& name)
- {
- std::map<std::string, GLint>::iterator unit = mTextureUnits.find(name);
- if (unit != mTextureUnits.end())
- return unit->second;
- static GLint MAX_TEXTURE_UNITS = getMaxTextureUnits();
- if (++mCurrentTextureUnit >= MAX_TEXTURE_UNITS)
- return 0;
- mTextureUnits[name] = mCurrentTextureUnit;
- return mCurrentTextureUnit;
- }
-
- #define checkJSL() \
- if (CurrentShader != this) \
- return
-
- void Shader::sendInt(const char* name, int value)
- {
- checkJSL();
- int loc = glGetUniformLocation(mPID, name);
- glUniform1i(loc, value);
- }
-
- void Shader::sendFloat(const char* variable, float number)
- {
- checkJSL();
- int loc = glGetUniformLocation(mPID, variable);
- glUniform1f(loc, number);
- }
-
- //
- // https://www.douban.com/note/627332677/
- // struct TextureUnit
- // {
- // GLuint targetTexture1D;
- // GLuint targetTexture2D;
- // GLuint targetTexture3D;
- // GLuint targetTextureCube;
- // ...
- // };
- //
- // TextureUnit mTextureUnits[GL_MAX_TEXTURE_IMAGE_UNITS]
- // GLuint mCurrentTextureUnit = 0;
- //
- void Shader::sendTexture(const char* variable, const Texture* tex)
- {
- checkJSL();
- GLint location = glGetUniformLocation(mPID, variable);
- if (location == -1)
- return;
- GLint unit = claimTextureUnit(variable);
- if (unit == 0)
- {
- // TODO: 쳣󶨵
- return;
- }
- gl.activeTexUnit(unit);
- glUniform1i(location, unit);
- gl.bindTexture(tex->getGLTexture());
- gl.activeTexUnit(0);
- }
-
- void Shader::sendCanvas(const char* variable, const Canvas* canvas)
- {
- checkJSL();
- GLint location = glGetUniformLocation(mPID, variable);
- if (location == -1)
- return;
- GLint unit = claimTextureUnit(variable);
- if (unit == 0)
- {
- // TODO: 쳣󶨵
- return;
- }
- glUniform1i(location, unit);
- glActiveTexture(GL_TEXTURE0 + unit);
- gl.bindTexture(canvas->getGLTexture());
-
- glActiveTexture(GL_TEXTURE0);
- }
-
- void Shader::sendVec2(const char* name, float x, float y)
- {
- checkJSL();
- int loc = glGetUniformLocation(mPID, name);
- glUniform2f(loc, x, y);
- }
-
- void Shader::sendVec3(const char* name, float x, float y, float z)
- {
- checkJSL();
- int loc = glGetUniformLocation(mPID, name);
- glUniform3f(loc, x, y, z);
- }
-
- void Shader::sendVec4(const char* name, float x, float y, float z, float w)
- {
- checkJSL();
- int loc = glGetUniformLocation(mPID, name);
- glUniform4f(loc, x, y, z, w);
- }
-
- void Shader::sendColor(const char* name, const Color* col)
- {
- checkJSL();
- int loc = glGetUniformLocation(mPID, name);
- glUniform4f(loc,
- col->r / 255.f,
- col->g / 255.f,
- col->b / 255.f,
- col->a / 255.f
- );
- }
-
- void Shader::sendMatrix4(const char* name, const Math::Matrix* mat4)
- {
- int loc = glGetUniformLocation(mPID, name);
- glUniformMatrix4fv(loc, 1, GL_FALSE, mat4->getElements());
- }
-
- void Shader::bindVertexPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers)
- {
- GLint loc = glGetAttribLocation(mPID, SHADER_VERTEX_COORDS);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(loc, n, type, GL_FALSE, stride, pointers);
- }
-
- void Shader::bindUVPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers)
- {
- GLint loc = glGetAttribLocation(mPID, SHADER_TEXTURE_COORDS);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(loc, n, type, GL_FALSE, stride, pointers);
- }
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif // (jin_graphics) && (jin_graphics & jin_graphics_shader) \ No newline at end of file
diff --git a/src/libjin/Graphics/Shader/je_shader.h b/src/libjin/Graphics/Shader/je_shader.h
deleted file mode 100644
index 039efb5..0000000
--- a/src/libjin/Graphics/Shader/je_shader.h
+++ /dev/null
@@ -1,197 +0,0 @@
-#ifndef __JE_SHADER_H
-#define __JE_SHADER_H
-
-#include "../../core/je_configuration.h"
-#if defined(jin_graphics) && (jin_graphics & jin_graphics_shader)
-
-#include <string>
-#include <map>
-
-#include "GLee/GLee.h"
-
-#include "../je_color.h"
-#include "../je_texture.h"
-#include "../je_canvas.h"
-
-#include "je_base.shader.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- ///
- /// Built in shader program.
- ///
- /// Built in shader program written with custom shading language called JSL (jin shading language). A JSL
- /// program is compiled into glsl, so most glsl built in functions and structs are available in JSL.
- ///
- class Shader
- {
- public:
- ///
- /// Create shader program from source code.
- ///
- /// @param source The shader source code.
- ///
- static Shader* createShader(const std::string& source);
-
- ///
- /// Get current shader.
- ///
- /// @return Current used shader program.
- ///
- static inline Shader* getCurrentShader() { return CurrentShader; }
-
- ///
- /// Unuse current shader.
- ///
- static void unuse();
-
- ///
- /// Destructor of shader.
- ///
- virtual ~Shader();
-
- ///
- /// Use specific shader.
- ///
- void use();
-
- ///
- /// Send float value to shader.
- ///
- /// @param name Name of the uniform variable to be assigned.
- /// @param number Value of uniform variable to be sent.
- ///
- void sendFloat(const char* name, float number);
-
- ///
- /// Send texture to shader.
- ///
- /// @param name Name of the uniform variable to be assigned.
- /// @param texture Texture to be sent.
- ///
- void sendTexture(const char* name, const Texture* texture);
-
- ///
- /// Send integer value to shader
- ///
- /// @param name Name of the uniform variable to be assigned.
- /// @param value Value to be sent.
- ///
- void sendInt(const char* name, int value);
-
- ///
- /// Send 2D vector to shader.
- ///
- /// @param name Name of the uniform variable to be assigned.
- /// @param x X value of the vector to be sent.
- /// @param y Y value of the vector to be sent.
- ///
- void sendVec2(const char* name, float x, float y);
-
- ///
- /// Send 3D vector to shader.
- ///
- /// @param name Name of the uniform variable to be assigned.
- /// @param x X value of the vector to be sent.
- /// @param y Y value of the vector to be sent.
- /// @param z Z value of the vector to be sent.
- ///
- void sendVec3(const char* name, float x, float y, float z);
-
- ///
- /// Send 4D vector to shader.
- ///
- /// @param name Name of the uniform variable to be assigned.
- /// @param x X value of the vector to be sent.
- /// @param y Y value of the vector to be sent.
- /// @param z Z value of the vector to be sent.
- /// @param w W value of the vector to be sent.
- ///
- void sendVec4(const char* name, float x, float y, float z, float w);
-
- ///
- /// Send canvas to shader.
- ///
- /// @param name Name of the uniform variable to be assigned.
- /// @param canvas Canvas to be sent.
- ///
- void sendCanvas(const char* name, const Canvas* canvas);
-
- ///
- /// Send color to shader.
- ///
- /// @param name Name of the uniform variable to be assigned.
- /// @param color Color to be sent.
- ///
- void sendColor(const char* name, const Color* color);
-
- ///
- /// Send 4 by 4 matrix to shader.
- ///
- /// @param name Name of the uniform variable to be assigned.
- /// @param mat4 Matrix to be sent.
- ///
- void sendMatrix4(const char* name, const Math::Matrix* mat4);
-
- ///
- /// Set vertices value.
- ///
- /// @param n Number of vertices.
- /// @param type Data type of each component in the array.
- /// @param stride Byte offset between consecutive generic vertex attributes.
- /// @param pointers Pointer to the first component of the first generic vertex attribute in the array.
- ///
- void bindVertexPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers);
-
- ///
- /// Set texture UV coordinates.
- ///
- /// @param n Number of vertices.
- /// @param type Data type of each component in the array.
- /// @param stride Byte offset between consecutive generic vertex attributes.
- /// @param pointers Pointer to the first component of the first generic vertex attribute in the array.
- ///
- void bindUVPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers);
-
- protected:
- ///
- /// Reference of current used shader.
- ///
- static Shader* CurrentShader;
-
- ///
- /// Get texture unit of the uniform texture. If not, assign one.
- ///
- /// @param name Name of the texture uniform variable.
- /// @return Texture unit which texture variable be assigned.
- ///
- GLint claimTextureUnit(const std::string& name);
-
- ///
- /// Shader constructor.
- ///
- Shader(const std::string& program);
-
- ///
- /// Compile JSL program into GLSL source.
- ///
- /// @param program JSL source code.
- /// @return Return true if compile successed, otherwise return false.
- ///
- bool compile(const std::string& program);
-
- GLuint mPID;
- GLint mCurrentTextureUnit;
- std::map<std::string, GLint> mTextureUnits;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif // (jin_graphics) && (jin_graphics & jin_graphics_shader)
-
-#endif // __JE_SHADER_H \ No newline at end of file
diff --git a/src/libjin/Graphics/animation/je_animation.h b/src/libjin/Graphics/animation/je_animation.h
deleted file mode 100644
index aa4c93f..0000000
--- a/src/libjin/Graphics/animation/je_animation.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef __JE_ANIMATION_H
-#define __JE_ANIMATION_H
-
-#include <vector>
-#include <string>
-
-#include "../je_sprite.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- ///
- /// Animation clip with key.
- ///
- class Animation
- {
- public:
- void onUpdate(float dt);
-
- void start();
- void pause();
- void stop();
- void rewind();
- void setSpeed(float speed);
-
- ///
- /// Get current frame index.
- ///
- uint getCurrentFrame();
-
- ///
- /// Set current frame index.
- ///
- /// @param frame Current frame to play.
- ///
- void setCurrentFrame(uint frame);
-
- private:
- ///
- /// Key frames.
- ///
- std::vector<Sprite*> mFrames;
-
- ///
- /// Animation playing speed.
- ///
- float mSpeed;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/animation/je_animator.h b/src/libjin/Graphics/animation/je_animator.h
deleted file mode 100644
index 973ff58..0000000
--- a/src/libjin/Graphics/animation/je_animator.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef __JE_ANIMATOR_H
-#define __JE_ANIMATOR_H
-
-#include <map>
-#include <vector>
-#include <string>
-
-#include "je_animation.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- ///
- ///
- ///
- class Animator
- {
- public:
- void addAnimation(const std::string& key, Animation* clip);
- bool hasKey(const std::string& key);
-
- void play();
- void switchAnimationByKey(const std::string& key);
- void switchAnimation(const Animation* clip);
-
- ///
- /// Control clips.
- ///
- void stopAnimation();
- void pauseAnimation();
- void rewindAnimation();
- void startAnimation();
-
- private:
- ///
- /// Map a key to clips.
- ///
- std::map<std::string, Animation*> mAnimations;
- Animation* mCurrentAnimation;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/animation/je_animation.cpp b/src/libjin/Graphics/animations/je_animation.cpp
index e69de29..e69de29 100644
--- a/src/libjin/Graphics/animation/je_animation.cpp
+++ b/src/libjin/Graphics/animations/je_animation.cpp
diff --git a/src/libjin/Graphics/animations/je_animation.h b/src/libjin/Graphics/animations/je_animation.h
new file mode 100644
index 0000000..f694455
--- /dev/null
+++ b/src/libjin/Graphics/animations/je_animation.h
@@ -0,0 +1,59 @@
+#ifndef __JE_ANIMATION_H
+#define __JE_ANIMATION_H
+
+#include <vector>
+#include <string>
+
+#include "../je_sprite.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Animations
+ {
+
+ ///
+ /// Animation clip with key.
+ ///
+ class Animation
+ {
+ public:
+ void onUpdate(float dt);
+
+ void start();
+ void pause();
+ void stop();
+ void rewind();
+ void setSpeed(float speed);
+
+ ///
+ /// Get current frame index.
+ ///
+ uint getCurrentFrame();
+
+ ///
+ /// Set current frame index.
+ ///
+ /// @param frame Current frame to play.
+ ///
+ void setCurrentFrame(uint frame);
+
+ private:
+ ///
+ /// Key frames.
+ ///
+ std::vector<Sprite*> mFrames;
+
+ ///
+ /// Animation playing speed.
+ ///
+ float mSpeed;
+
+ };
+
+ } // namespace Animations
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/animation/je_animator.cpp b/src/libjin/Graphics/animations/je_animator.cpp
index e69de29..e69de29 100644
--- a/src/libjin/Graphics/animation/je_animator.cpp
+++ b/src/libjin/Graphics/animations/je_animator.cpp
diff --git a/src/libjin/Graphics/animations/je_animator.h b/src/libjin/Graphics/animations/je_animator.h
new file mode 100644
index 0000000..9273ff8
--- /dev/null
+++ b/src/libjin/Graphics/animations/je_animator.h
@@ -0,0 +1,51 @@
+#ifndef __JE_ANIMATOR_H
+#define __JE_ANIMATOR_H
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "je_animation.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Animations
+ {
+
+ ///
+ ///
+ ///
+ class Animator
+ {
+ public:
+ void addAnimation(const std::string& key, Animation* clip);
+ bool hasKey(const std::string& key);
+
+ void play();
+ void switchAnimationByKey(const std::string& key);
+ void switchAnimation(const Animation* clip);
+
+ ///
+ /// Control clips.
+ ///
+ void stopAnimation();
+ void pauseAnimation();
+ void rewindAnimation();
+ void startAnimation();
+
+ private:
+ ///
+ /// Map a key to clips.
+ ///
+ std::map<std::string, Animation*> mAnimations;
+ Animation* mCurrentAnimation;
+
+ };
+
+ }
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_decoder.cpp b/src/libjin/Graphics/fonts/je_decoder.cpp
new file mode 100644
index 0000000..02112a0
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_decoder.cpp
@@ -0,0 +1,96 @@
+#include <stdlib.h>
+#include <string.h>
+#include "je_decoder.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ /* utf8 byte string to unicode codepoint */
+ static const char *utf8toCodepoint(const char *p, unsigned *res) {
+ return nullptr;
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // decoders
+ /////////////////////////////////////////////////////////////////////////////
+
+ const void* Utf8::decode(const void* data, Codepoint* res) const
+ {
+ const char* p = (char*)data;
+ unsigned x, mask, shift;
+ switch (*p & 0xf0) {
+ case 0xf0: mask = 0x07; shift = 18; break;
+ case 0xe0: mask = 0x0f; shift = 12; break;
+ case 0xc0:
+ case 0xd0: mask = 0x1f; shift = 6; break;
+ default:
+ *res = *p;
+ return p + 1;
+ }
+ x = (*p & mask) << shift;
+ do {
+ if (*(++p) == '\0') {
+ *res = x;
+ return p;
+ }
+ shift -= 6;
+ x |= (*p & 0x3f) << shift;
+ } while (shift);
+ *res = x;
+ return p + 1;
+ }
+
+ const void* Utf8::next(const void* data) const
+ {
+ const char* p = (char*)data;
+ unsigned x, mask, shift;
+ switch (*p & 0xf0) {
+ case 0xf0: mask = 0x07; shift = 18; break;
+ case 0xe0: mask = 0x0f; shift = 12; break;
+ case 0xc0:
+ case 0xd0: mask = 0x1f; shift = 6; break;
+ default:
+ return p + 1;
+ }
+ x = (*p & mask) << shift;
+ do {
+ if (*(++p) == '\0') {
+ return p;
+ }
+ shift -= 6;
+ x |= (*p & 0x3f) << shift;
+ } while (shift);
+ return p + 1;
+ }
+ /*
+ const void* Utf16::decode(const void* data, Codepoint* res) const
+ {
+ return nullptr;
+ }
+
+ const void* Utf16::next(const void* data) const
+ {
+ return nullptr;
+ }
+ */
+ const void* Ascii::decode(const void* data, Codepoint* res) const
+ {
+ const char* p = (char*)data;
+ *res = *p;
+ return p + 1;
+ }
+
+ const void* Ascii::next(const void* data) const
+ {
+ const char* p = (char*)data;
+ return p + 1;
+ }
+
+ } // namespace Fonts
+ } // namespace Graphics
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_decoder.h b/src/libjin/Graphics/fonts/je_decoder.h
new file mode 100644
index 0000000..cacbad8
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_decoder.h
@@ -0,0 +1,97 @@
+#ifndef __JE_UTF8_H
+#define __JE_UTF8_H
+
+#include <vector>
+
+#include "je_text.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ ///
+ /// Text decoder.
+ ///
+ class Decoder
+ {
+ public:
+
+ ///
+ /// Decode a code unit.
+ ///
+ /// @param data Code units.
+ /// @param codepoint Value of code point.
+ /// @return Next code unit location.
+ ///
+ virtual const void* decode(const void* data, Codepoint* codepoint) const = 0;
+
+ ///
+ /// Get next code unit location.
+ ///
+ /// @param data Code units.
+ /// @return Next code unit location.
+ ///
+ virtual const void* next(const void* data) const = 0;
+
+ };
+
+ ///
+ /// Utf-8 decoder.
+ ///
+ class Utf8 : public Decoder
+ {
+ public:
+
+ ///
+ /// Decode a code unit.
+ ///
+ /// @param data Code units.
+ /// @param codepoint Value of code point.
+ /// @return Next code unit location.
+ ///
+ const void* decode(const void* data, Codepoint* codepoint) const override;
+
+ ///
+ /// Get next code unit location.
+ ///
+ /// @param data Code units.
+ /// @return Next code unit location.
+ ///
+ const void* next(const void* data) const override;
+
+ };
+
+ ///
+ /// Ascii decoder.
+ ///
+ class Ascii : public Decoder
+ {
+ public:
+
+ ///
+ /// Decode a code unit.
+ ///
+ /// @param data Code units.
+ /// @param codepoint Value of code point.
+ /// @return Next code unit location.
+ ///
+ const void* decode(const void* data, Codepoint* codepoint) const override;
+
+ ///
+ /// Get next code unit location.
+ ///
+ /// @param data Code units.
+ /// @return Next code unit location.
+ ///
+ const void* next(const void* data) const override;
+
+ };
+
+ } // namespace Fonts
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_font.h b/src/libjin/Graphics/fonts/je_font.h
new file mode 100644
index 0000000..ae151dc
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_font.h
@@ -0,0 +1,109 @@
+#ifndef __JE_FONT_H
+#define __JE_FONT_H
+
+#include <vector>
+#include "je_text.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ struct Page;
+
+ //
+ // Font
+ // |- TTF
+ // |- TextureFont
+ //
+
+ ///
+ /// Base Font class.
+ ///
+ class Font
+ {
+ public:
+ ///
+ /// Font constructor.
+ ///
+ Font(unsigned fontsize)
+ : mFontSize(fontsize)
+ {
+ }
+
+ ///
+ /// Font destructor.
+ ///
+ virtual ~Font() {};
+
+ ///
+ /// Create page with given text.
+ ///
+ /// @param text Text to be typesetted.
+ /// @param lineheight Line height of text.
+ /// @param spacing Spacing between characters. 0 by default.
+ /// @return Page if created successfully, otherwise return null.
+ ///
+ virtual Page* typeset(const Text& text, int lineheight, int spacing = 0) = 0;
+
+ ///
+ /// Create page with given unicode codepoints.
+ ///
+ /// @param content Unicode codepoints to be typesetted.
+ /// @param lineheight Line height of text.
+ /// @param spacing Spacing between characters. 0 by default.
+ /// @return Page if created successfully, otherwise return null.
+ ///
+ virtual Page* typeset(const Content& content, int lineheight, int spacing = 0) = 0;
+
+ ///
+ /// Render page to given position.
+ ///
+ /// @param page Page to be rendered.
+ /// @param x X value of the position.
+ /// @param y Y value of the position.
+ ///
+ virtual void render(const Page* page, int x, int y) = 0;
+
+ ///
+ /// Render unicode codepoints to given position.
+ ///
+ /// @param content Unicode codepoints to be typesetted.
+ /// @param x X value of the position.
+ /// @param y Y value of the position.
+ /// @param lineheight Line height of the content.
+ /// @param spacing Spacing between characters.
+ ///
+ virtual void render(const Content& content, int x, int y, int lineheight, int spacing = 0) = 0;
+
+ ///
+ /// Render text to given position.
+ ///
+ /// @param text Text to be rendered.
+ /// @param x X value of the position.
+ /// @param y Y value of the position.
+ /// @param lineheight Line height of the text.
+ /// @param spacing Spacing between characters.
+ ///
+ virtual void render(const Text& text, int x, int y, int lineheight, int spacing = 0) = 0;
+
+ ///
+ /// Get font size.
+ ///
+ /// @return Font size.
+ ///
+ inline unsigned getFontSize() { return mFontSize; };
+
+ protected:
+
+ unsigned mFontSize;
+
+ };
+
+ } // namespace Fonts
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif // __JE_FONT_H \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_page.h b/src/libjin/Graphics/fonts/je_page.h
new file mode 100644
index 0000000..cc61ac2
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_page.h
@@ -0,0 +1,54 @@
+#ifndef __JE_PAGE_H
+#define __JE_PAGE_H
+
+#include "../../math/je_vector2.hpp"
+
+#include "je_font.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ class Font;
+
+ ///
+ /// Glyphs data to be rendered.
+ ///
+ struct GlyphVertex
+ {
+ int x, y; ///< screen coordinates
+ float u, v; ///< normalized texture uv
+ };
+
+ ///
+ /// Glyphs info for reducing draw call.
+ ///
+ struct GlyphArrayDrawInfo
+ {
+ GLuint texture; ///< atlas
+ unsigned int start; ///< glyph vertex indecies
+ unsigned int count; ///< glyph vertex count
+ };
+
+ ///
+ /// Page to be rendered.
+ ///
+ /// A page is a pre-rendered text struct for reducing draw call. Each page
+ /// keeps a font pointer which should not be changed.
+ ///
+ struct Page
+ {
+ Font* font;
+ std::vector<GlyphArrayDrawInfo> glyphinfolist;
+ std::vector<GlyphVertex> glyphvertices;
+ Math::Vector2<int> size;
+ };
+
+ } // namespace Fonts
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif // __JE_PAGE_H \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_text.cpp b/src/libjin/Graphics/fonts/je_text.cpp
new file mode 100644
index 0000000..80aaa6a
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_text.cpp
@@ -0,0 +1,157 @@
+#include <cstring>
+
+#include "je_text.h"
+#include "je_decoder.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ /////////////////////////////////////////////////////////////////////////////
+ // iterator
+ /////////////////////////////////////////////////////////////////////////////
+
+ Text::Iterator::Iterator(const Iterator& itor)
+ : data(itor.data)
+ , p(itor.p)
+ , encode(itor.encode)
+ , length(itor.length)
+ {
+ switch (encode)
+ {
+ case Encode::UTF8: decoder = new Utf8(); break;
+ case Encode::ASCII: decoder = new Ascii(); break;
+ }
+ }
+
+ Text::Iterator::Iterator(const Encode& _encode, const void* _data, unsigned int _length)
+ : data(_data)
+ , p(_data)
+ , encode(_encode)
+ , length(_length)
+ {
+ switch (encode)
+ {
+ case Encode::UTF8: decoder = new Utf8(); break;
+ case Encode::ASCII: decoder = new Ascii(); break;
+ }
+ }
+
+ Text::Iterator::~Iterator()
+ {
+ delete decoder;
+ }
+
+ Codepoint Text::Iterator::get()
+ {
+ Codepoint codepoint;
+ decoder->decode(p, &codepoint);
+ return codepoint;
+ }
+
+ Codepoint Text::Iterator::operator*()
+ {
+ return get();
+ }
+ /*
+ Text::Iterator Text::Iterator::begin()
+ {
+ Iterator itor(encode, data, length);
+ itor.toBegin();
+ return itor;
+ }
+
+ Text::Iterator Text::Iterator::end()
+ {
+ Iterator itor(encode, data, length);
+ itor.toEnd();
+ return itor;
+ }
+ */
+ void Text::Iterator::toBegin()
+ {
+ p = (const unsigned char*)data;
+ }
+
+ void Text::Iterator::toEnd()
+ {
+ p = (const unsigned char*)data + length;
+ }
+
+ Text::Iterator& Text::Iterator::operator ++()
+ {
+ p = decoder->next(p);
+ return *this;
+ }
+
+ Text::Iterator Text::Iterator::operator ++(int)
+ {
+ p = decoder->next(p);
+ Iterator itor(encode, data, length);
+ itor.p = p;
+ return itor;
+ }
+
+ bool Text::Iterator::operator !=(const Iterator& itor)
+ {
+ return !(data == itor.data
+ && p == itor.p
+ && length == itor.length
+ && encode == itor.encode);
+ }
+
+ bool Text::Iterator::operator ==(const Iterator& itor)
+ {
+ return data == itor.data
+ && p == itor.p
+ && length == itor.length
+ && encode == itor.encode;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // text
+ /////////////////////////////////////////////////////////////////////////////
+
+ Text::Text(Encode encode, const void* data)
+ {
+ unsigned length = strlen((const char*)data);
+ Iterator end = Iterator(encode, data, length);
+ end.toEnd();
+ Iterator it = Iterator(encode, data, length);
+ for (; it != end; ++it)
+ {
+ content.push_back(*it);
+ }
+ }
+
+ Text::Text(Encode encode, const void* data, unsigned length)
+ {
+ Iterator end = Iterator(encode, data, length);
+ end.toEnd();
+ Iterator it = Iterator(encode, data, length);
+ for (; it != end; ++it)
+ {
+ content.push_back(*it);
+ }
+ }
+
+ Text::~Text()
+ {
+ }
+
+ const Content& Text::getContent() const
+ {
+ return content;
+ }
+
+ const Content& Text::operator*() const
+ {
+ return content;
+ }
+
+ } // namespace Fonts
+ } // namespace Graphics
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_text.h b/src/libjin/Graphics/fonts/je_text.h
new file mode 100644
index 0000000..261f112
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_text.h
@@ -0,0 +1,172 @@
+#ifndef __JE_TEXT_H
+#define __JE_TEXT_H
+
+#include <vector>
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ typedef unsigned int Codepoint;
+
+ typedef std::vector<Codepoint> Content;
+
+ class Text;
+
+ class Decoder;
+
+ ///
+ /// Supported text encoding.
+ ///
+ enum Encode
+ {
+ UTF8, ///< utf-8
+ ASCII, ///< ASCII
+ };
+
+ ///
+ /// Decoded text. Saved as unicode codepoints.
+ ///
+ class Text
+ {
+ public:
+ ///
+ ///
+ ///
+ Text(Encode encode, const void* data);
+
+ ///
+ ///
+ ///
+ Text(Encode encode, const void* data, unsigned int length);
+
+ ///
+ ///
+ ///
+ ~Text();
+
+ ///
+ ///
+ ///
+ const Content& getContent() const;
+
+ ///
+ ///
+ ///
+ const Content& operator*() const;
+
+ private:
+ ///
+ ///
+ ///
+ class Iterator
+ {
+ public:
+
+ ///
+ ///
+ ///
+ Iterator(const Iterator& itor);
+
+ ///
+ ///
+ ///
+ Iterator(const Encode& encode, const void* data, unsigned int length);
+
+ ///
+ ///
+ ///
+ ~Iterator();
+
+ ///
+ ///
+ ///
+ Codepoint get();
+
+ //Iterator begin();
+ //Iterator end();
+
+ ///
+ ///
+ ///
+ void toBegin();
+
+ ///
+ ///
+ ///
+ void toEnd();
+
+ ///
+ ///
+ ///
+ Codepoint operator *();
+
+ ///
+ ///
+ ///
+ Iterator& operator ++();
+
+ ///
+ ///
+ ///
+ Iterator operator ++(int);
+
+ ///
+ ///
+ ///
+ bool operator !=(const Iterator& itor);
+
+ ///
+ ///
+ ///
+ bool operator ==(const Iterator& itor);
+
+ private:
+
+ ///
+ ///
+ ///
+ void operator = (const Iterator&);
+
+ ///
+ ///
+ ///
+ const Encode encode;
+
+ ///
+ ///
+ ///
+ const Decoder* decoder;
+
+ ///
+ ///
+ ///
+ const void* p;
+
+ ///
+ ///
+ ///
+ const void* const data;
+
+ ///
+ ///
+ ///
+ unsigned int length;
+
+ };
+
+ ///
+ ///
+ ///
+ Content content;
+
+ };
+
+ }
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_texture_font.cpp b/src/libjin/Graphics/fonts/je_texture_font.cpp
new file mode 100644
index 0000000..6404b16
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_texture_font.cpp
@@ -0,0 +1,322 @@
+#include <vector>
+
+#include "../../math/je_vector2.hpp"
+
+#include "../shaders/je_shader.h"
+
+#include "je_texture_font.h"
+
+using namespace std;
+using namespace JinEngine::Math;
+using namespace JinEngine::Graphics::Shaders;
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ TextureFont * TextureFont::createTextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh)
+ {
+ TextureFont* tf = new TextureFont(bitmap, codepoints, cellw, cellh);
+ return tf;
+ }
+
+ TextureFont * TextureFont::createTextureFont(const Bitmap* bitmap, const Text& codepoints, int cellw, int cellh)
+ {
+ TextureFont* tf = new TextureFont(bitmap, *codepoints, cellw, cellh);
+ return tf;
+ }
+
+ TextureFont* TextureFont::createTextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh)
+ {
+ TextureFont* tf = new TextureFont(bitmap, codepoints, mask, cellh);
+ return tf;
+ }
+
+ TextureFont* TextureFont::createTextureFont(const Bitmap* bitmap, const Text& codepoints, Color mask, int cellh)
+ {
+ TextureFont* tf = new TextureFont(bitmap, *codepoints, mask, cellh);
+ return tf;
+ }
+
+ TextureFont::~TextureFont()
+ {
+ }
+
+ const TextureFont::TextureGlyph* TextureFont::findGlyph(Codepoint codepoint) const
+ {
+ auto it = glyphs.find(codepoint);
+ if (it != glyphs.end())
+ {
+ return &it->second;
+ }
+ else
+ return nullptr;
+ }
+
+ Page* TextureFont::typeset(const Content& text, int lineheight, int spacing)
+ {
+ Page* page = new Page();
+ page->font = this;
+ vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist;
+ vector<GlyphVertex>& glyphvertices = page->glyphvertices;
+ int texture = -1;
+ const TextureGlyph* glyph = nullptr;
+ GlyphVertex vertex;
+ Vector2<int> p(0, 0);
+ int i = 0;
+
+#define glyphvertices_push(_x, _y, _u, _v) \
+ vertex.x = _x; vertex.y = _y;\
+ vertex.u = _u; vertex.v = _v;\
+ glyphvertices.push_back(vertex);\
+
+ for (Codepoint c : text)
+ {
+ // return
+ if (c == 0x0D) continue;
+ // newline
+ if (c == 0x0A)
+ {
+ p.y += lineheight;
+ p.x = 0;
+ continue;
+ }
+ if (c == 0x09)
+ {
+ // tab = 4*space
+ unsigned cw = getCharWidth(0x20);
+ p.x += cw * 4;
+ continue;
+ }
+ glyph = findGlyph(c);
+ if (glyph == nullptr) continue;
+ if (texture != getGLTexture())
+ {
+ texture = getGLTexture();
+ GlyphArrayDrawInfo info;
+ info.start = i;
+ info.count = 0;
+ info.texture = texture;
+ glyphinfolist.push_back(info);
+ }
+ glyphinfolist[glyphinfolist.size() - 1].count += 4;
+ // normalized
+ float w = getWidth(), h = getHeight();
+ float nx = glyph->x / w, ny = glyph->y / h;
+ float nw = glyph->w / w, nh = glyph->h / h;
+ glyphvertices_push(p.x, p.y, nx, ny);
+ glyphvertices_push(p.x, p.y + glyph->h, nx, ny + nh);
+ glyphvertices_push(p.x + glyph->w, p.y + glyph->h, nx + nw, ny + nh);
+ glyphvertices_push(p.x + glyph->w, p.y, nx + nw, ny);
+ p.x += glyph->w + spacing;
+ i += 4;
+ }
+ getTextBox(text, &page->size.w, &page->size.h, lineheight, spacing);
+ return page;
+ }
+
+ int TextureFont::getCharWidth(int c)
+ {
+ auto it = glyphs.find(c);
+ if (it != glyphs.end())
+ {
+ return it->second.w;
+ }
+ return 0;
+ }
+
+ int TextureFont::getCharHeight(int c)
+ {
+ auto it = glyphs.find(c);
+ if (it != glyphs.end())
+ {
+ return it->second.h;
+ }
+ return 0;
+ }
+
+ int TextureFont::getTextWidth(const Content& t, int spacing)
+ {
+ int res = 0;
+ int tmp = 0;
+ for (Codepoint c : t)
+ {
+ if (c == 0x0D)
+ continue;
+ if (c == 0x0A)
+ {
+ tmp = 0;
+ continue;
+ }
+ if (c == 0x09)
+ {
+ // tab = 4*space
+ unsigned cw = getCharWidth(0x20);
+ tmp += cw * 4;
+ if (tmp > res) res = tmp;
+ continue;
+ }
+ tmp += getCharWidth(c) + spacing;
+ if (tmp > res) res = tmp;
+ }
+ return res;
+ }
+
+ int TextureFont::getTextHeight(const Content& t, int lineheight)
+ {
+ int res = 0;
+ bool newline = true;
+ for (Codepoint c : t)
+ {
+ if (c == 0x0A)
+ newline = true;
+ else if (c == 0x0D);
+ else if (newline)
+ {
+ newline = false;
+ res += lineheight;
+ }
+ }
+ return res;
+ }
+
+ void TextureFont::getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing)
+ {
+ *w = 0;
+ *h = 0;
+ int tmp = 0;
+ bool newline = true;
+ for (Codepoint c : text)
+ {
+ if (c == 0x0D)
+ continue;
+ if (c == 0x0A)
+ {
+ tmp = 0;
+ newline = true;
+ continue;
+ }
+ else if (newline)
+ {
+ newline = false;
+ *h += lineheight;
+ }
+ tmp += getCharWidth(c) + spacing;
+ if (tmp > *w)
+ *w = tmp;
+ }
+ }
+
+ Page* TextureFont::typeset(const Text& text, int lineheight, int spacing)
+ {
+ return typeset(*text, lineheight, spacing);
+ }
+
+ void TextureFont::render(const Page* page, int x, int y)
+ {
+ Shader* shader = Shader::getCurrentShader();
+ const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist;
+ const vector<GlyphVertex>& glyphvertices = page->glyphvertices;
+ gl.ModelMatrix.setTransformation(x, y, 0, 1, 1, 0, 0);
+ shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
+ for (int i = 0; i < glyphinfolist.size(); ++i)
+ {
+ const GlyphArrayDrawInfo& info = glyphinfolist[i];
+ shader->bindVertexPointer(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x);
+ shader->bindUVPointer(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u);
+ gl.bindTexture(info.texture);
+ gl.drawArrays(GL_QUADS, 0, info.count);
+ gl.bindTexture(0);
+ }
+ }
+
+ void TextureFont::render(const Content& text, int x, int y, int lineheight, int spacing)
+ {
+ Page* page = typeset(text, lineheight, spacing);
+ render(page, x, y);
+ delete page;
+ }
+
+ void TextureFont::render(const Text& text, int x, int y, int lineheight, int spacing)
+ {
+ Page* page = typeset(text, lineheight, spacing);
+ render(page, x, y);
+ delete page;
+ }
+
+ TextureFont::TextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh)
+ : Graphic(bitmap)
+ , Font(cellh)
+ {
+ TextureGlyph glyph;
+ Vector2<int> count(bitmap->getWidth() / cellw, bitmap->getHeight() / cellh);
+ glyph.w = cellw;
+ glyph.h = cellh;
+ for (int y = 0; y < count.row; ++y)
+ {
+ glyph.y = y * cellh;
+ for (int x = 0; x < count.colum; ++x)
+ {
+ glyph.x = x * cellw;
+ if (x + y * count.colum >= codepoints.size())
+ return;
+ glyphs.insert(std::pair<Codepoint, TextureGlyph>(codepoints[x + y * count.colum], glyph));
+ }
+ }
+ }
+
+ TextureFont::TextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh)
+ : Graphic(bitmap)
+ , Font(cellh)
+ {
+ TextureGlyph glyph;
+ glyph.h = cellh;
+ int w = bitmap->getWidth();
+ int h = bitmap->getHeight();
+ int i = 0;
+ for (int y = 0; y < h; y += cellh)
+ {
+ glyph.y = y;
+ bool newc = false;
+ for (int x = 0; x <= w; ++x)
+ {
+ if (x == w && newc)
+ {
+ glyph.w = x - glyph.x;
+ if (i >= codepoints.size())
+ return;
+ glyphs.insert(std::pair<Codepoint, TextureGlyph>(codepoints[i], glyph));
+ ++i;
+ newc = false;
+ break;
+ }
+ Color c = bitmap->getPixels()[x + y * w];
+ if (!newc && c != mask)
+ {
+ glyph.x = x;
+ newc = true;
+ }
+ else if (newc && c == mask)
+ {
+ glyph.w = x - glyph.x;
+ if (i >= codepoints.size())
+ return;
+ glyphs.insert(std::pair<Codepoint, TextureGlyph>(codepoints[i], glyph));
+ if (codepoints[i] == 't')
+ {
+ int a = 10;
+ }
+ ++i;
+ newc = false;
+ }
+ }
+ }
+ }
+
+ }
+ }
+} \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_texture_font.h b/src/libjin/Graphics/fonts/je_texture_font.h
new file mode 100644
index 0000000..13abbae
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_texture_font.h
@@ -0,0 +1,142 @@
+#ifndef __JE_TEXTURE_FONT_H
+#define __JE_TEXTURE_FONT_H
+
+#include <map>
+#include <vector>
+
+#include "../../math/je_vector4.hpp"
+
+#include "../je_graphic.h"
+#include "../je_bitmap.h"
+
+#include "je_page.h"
+#include "je_font.h"
+#include "je_text.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ ///
+ ///
+ ///
+ class TextureFont : public Font, public Graphic
+ {
+ public:
+
+ ///
+ ///
+ ///
+ static TextureFont* createTextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh);
+
+ ///
+ ///
+ ///
+ static TextureFont* createTextureFont(const Bitmap* bitmap, const Text& text, int cellw, int cellh);
+
+ ///
+ ///
+ ///
+ static TextureFont* createTextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh);
+
+ ///
+ ///
+ ///
+ static TextureFont* createTextureFont(const Bitmap* bitmap, const Text& text, Color mask, int cellh);
+
+ ///
+ ///
+ ///
+ ~TextureFont();
+
+ ///
+ ///
+ ///
+ Page* typeset(const Text& text, int lineheight, int spacing = 0) override;
+
+ ///
+ ///
+ ///
+ Page* typeset(const Content& text, int lineheight, int spacing = 0) override;
+
+ ///
+ ///
+ ///
+ void render(const Page* page, int x, int y) override;
+
+ ///
+ ///
+ ///
+ void render(const Content& text, int x, int y, int linehgiht, int spacing = 0) override;
+
+ ///
+ ///
+ ///
+ void render(const Text& text, int x, int y, int lineheight, int spacing = 0)override;
+
+ private:
+
+ ///
+ ///
+ ///
+ struct TextureGlyph
+ {
+ float x, y, w, h;
+ };
+
+ ///
+ ///
+ ///
+ TextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh);
+
+ ///
+ ///
+ ///
+ TextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh);
+
+ ///
+ ///
+ ///
+ int getCharWidth(int c);
+
+ ///
+ ///
+ ///
+ int getCharHeight(int c);
+
+ ///
+ ///
+ ///
+ int getTextWidth(const Content& text, int spacing = 0);
+
+ ///
+ ///
+ ///
+ int getTextHeight(const Content& text, int lineheight);
+
+ ///
+ ///
+ ///
+ void getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing = 0);
+
+ ///
+ ///
+ ///
+ const TextureGlyph* findGlyph(Codepoint codepoint) const;
+
+
+ ///
+ ///
+ ///
+ std::map<Codepoint, TextureGlyph> glyphs;
+
+ };
+
+ } // namespace Fonts
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_ttf.cpp b/src/libjin/Graphics/fonts/je_ttf.cpp
new file mode 100644
index 0000000..3d0a02f
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_ttf.cpp
@@ -0,0 +1,468 @@
+#include "../../core/je_configuration.h"
+#if defined(jin_graphics)
+
+#include <stdio.h>
+
+#include "../../common/je_array.hpp"
+
+#include "../je_gl.h"
+#include "../je_color.h"
+#include "../shaders/je_shader.h"
+
+#include "je_ttf.h"
+#include "je_page.h"
+
+#define STB_TRUETYPE_IMPLEMENTATION
+#include "stb/stb_truetype.h"
+
+using namespace JinEngine::Graphics::Shaders;
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ /////////////////////////////////////////////////////////////////////////////
+ // TTFData
+ /////////////////////////////////////////////////////////////////////////////
+
+ TTFData* TTFData::createTTFData(const unsigned char* data, unsigned int size)
+ {
+ TTFData* ttf = nullptr;
+ try
+ {
+ ttf = new TTFData(data, size);
+ return ttf;
+ }
+ catch (...)
+ {
+ return nullptr;
+ }
+ }
+
+ TTFData::TTFData(const unsigned char* d, unsigned int s)
+ {
+ raw.size = s;
+ raw.data = (unsigned char*)malloc(s);
+ memcpy(raw.data, d, s);
+ if (!stbtt_InitFont(&info, (const unsigned char*)raw.data, 0))
+ {
+ delete raw.data;
+ throw 0;
+ }
+ /* push default fontsize */
+ pushTTFsize(FONT_SIZE);
+ }
+
+ TTFData::~TTFData()
+ {
+ free(raw.data);
+ }
+
+ TTF* TTFData::createTTF(unsigned fontSize)
+ {
+ TTF* ttf;
+ try
+ {
+ ttf = new TTF(this, fontSize);
+ }
+ catch (...)
+ {
+ return nullptr;
+ }
+ return ttf;
+ }
+
+ /*
+ * (0, 0)
+ * +--------------+ ascent
+ * | +--------+ |
+ * | | | |
+ * | | bitmap | |
+ * +--|--------|--+ baseline
+ * | +--------+ |
+ * +--|-----------+ decent
+ * | |
+ * leftSideBearing |
+ * advanceWidth
+ */
+ void TTFData::getVMetrics(int* baseline, int* descent)
+ {
+ float scale = scales.back();
+ int ascent;
+ stbtt_GetFontVMetrics(&info, &ascent, descent, 0);
+ *baseline = (int)(ascent*scale) + 1; // slight adjustment
+ *descent = *baseline - (int)(*descent*scale) + 1;
+ }
+
+ void TTFData::getHMetrics(unsigned int codepoint, int* advanceWidth, int* leftSideBearing)
+ {
+ float scale = scales.back();
+ int adw, lsb;
+ stbtt_GetCodepointHMetrics(&info, codepoint, &adw, &lsb);
+ *advanceWidth = (int)(adw*scale);
+ *leftSideBearing = (int)(lsb*scale);
+ }
+
+ void TTFData::pushTTFsize(unsigned int fs)
+ {
+ float sc = stbtt_ScaleForPixelHeight(&info, fs);
+ scales.push_back(sc);
+ }
+
+ void TTFData::popTTFsize()
+ {
+ /* always keep default ttf size on the bottom of stack */
+ if (scales.size() > 1)
+ scales.pop_back();
+ }
+
+ Channel* TTFData::getCodepointBitmapAlpha(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const
+ {
+ float scale = scales.back();
+ Channel* bitmap = stbtt_GetCodepointBitmap(&info, scale, scale, codepoint, width, height, xoff, yoff);
+ return bitmap;
+ }
+
+ Color* TTFData::getCodepointBitmap(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const
+ {
+ float scale = scales.back();
+ Channel* bitmap = stbtt_GetCodepointBitmap(&info, scale, scale, codepoint, width, height, xoff, yoff);
+ int w = *width, h = *height;
+ //int xo = *xoff, yo = *yoff;
+ Color* bitmap32 = new Color[w*h];
+ for (int y = 0; y < h; ++y)
+ {
+ for (int x = 0; x < w; ++x)
+ {
+ bitmap32[x + y * w].set(0xff, 0xff, 0xff, bitmap[x + y * w]);
+ }
+ }
+ free(bitmap);
+ return bitmap32;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // TTF
+ /////////////////////////////////////////////////////////////////////////////
+
+#include "../shaders/built-in/je_font.shader.h"
+
+ using namespace std;
+ using namespace JinEngine::Math;
+
+ const int TTF::TEXTURE_WIDTHS[] = { 128, 256, 256, 512, 512, 1024, 1024 };
+ const int TTF::TEXTURE_HEIGHTS[] = { 128, 128, 256, 256, 512, 512, 1024 };
+
+ /* little endian unicode */
+ static const char* unicodeLittleEndian(const char* p, unsigned* res)
+ {
+ }
+
+ ///*static*/ TTF* TTF::createTTF(TTFData* fontData, unsigned int fontSzie)
+ //{
+ // TTF* ttf;
+ // try
+ // {
+ // ttf = new TTF(fontData, fontSzie);
+ // }
+ // catch (...)
+ // {
+ // return nullptr;
+ // }
+ // return ttf;
+ //}
+
+ TTF::TTF(TTFData* f, unsigned int fontSize)
+ : Font(fontSize)
+ , cursor(0, 0)
+ , ttf(f)
+ {
+ ttf->pushTTFsize(fontSize);
+ ttf->getVMetrics(&baseline, &descent);
+ estimateSize();
+ ttf->popTTFsize();
+ /* create a default texture */
+ createAtlas();
+ }
+
+ /* estimate the size of atlas texture */
+ void TTF::estimateSize()
+ {
+ for (int level = 0; level <= TEXTURE_SIZE_LEVEL_MAX; ++level)
+ {
+ if (descent * (descent*0.8) * 96 <= TEXTURE_WIDTHS[level] * TEXTURE_HEIGHTS[level])
+ {
+ textureWidth = TEXTURE_WIDTHS[level];
+ textureHeight = TEXTURE_HEIGHTS[level];
+ break;
+ }
+ }
+ }
+
+ TTF::~TTF()
+ {
+ }
+
+ GLuint TTF::createAtlas()
+ {
+ GLuint t;
+ gl.flushError();
+ t = gl.genTexture();
+ gl.bindTexture(t);
+ gl.setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl.setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl.setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl.setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ gl.texImage(GL_RGBA8, textureWidth, textureHeight, GL_RGBA, GL_UNSIGNED_BYTE);
+ if (glGetError() != GL_NO_ERROR)
+ {
+ glDeleteTextures(1, &t);
+ gl.bindTexture(0);
+ return 0;
+ }
+ atlases.push_back(t);
+ gl.bindTexture(0);
+ return t;
+ }
+
+ void TTF::render(const Content& t, int x, int y, int lineheight, int spacing)
+ {
+ Page* page = typeset(t, lineheight, spacing);
+ render(page, x, y);
+ delete page;
+ }
+
+ Page* TTF::typeset(const Content& text, int lineheight, int spacing)
+ {
+ Page* page = new Page();
+ page->font = this;
+ vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist;
+ vector<GlyphVertex>& glyphvertices = page->glyphvertices;
+ int texture = -1;
+ TTFGlyph* glyph = nullptr;
+ GlyphVertex vertex;
+ Vector2<int> p(0, 0);
+ int i = 0;
+
+#define glyphvertices_push(_x, _y, _u, _v) \
+ vertex.x = _x; vertex.y = _y;\
+ vertex.u = _u; vertex.v = _v;\
+ glyphvertices.push_back(vertex);
+
+#define glyphlize(c)\
+ do{\
+ glyph = &findGlyph(c); \
+ if (texture != glyph->atlas) \
+ { \
+ GlyphArrayDrawInfo info; \
+ info.start = i; \
+ info.count = 0; \
+ info.texture = glyph->atlas; \
+ texture = glyph->atlas; \
+ glyphinfolist.push_back(info); \
+ } \
+ glyphinfolist[glyphinfolist.size() - 1].count += 4; \
+ TTFGlyph::Bbox& bbox = glyph->bbox; \
+ glyphvertices_push(p.x, p.y, bbox.x, bbox.y); \
+ glyphvertices_push(p.x, p.y + glyph->height, bbox.x, bbox.y + bbox.h); \
+ glyphvertices_push(p.x + glyph->width, p.y + glyph->height, bbox.x + bbox.w, bbox.y + bbox.h); \
+ glyphvertices_push(p.x + glyph->width, p.y, bbox.x + bbox.w, bbox.y); \
+ }while(0)
+
+ for (Codepoint c : text)
+ {
+ if (c == 0x0D)
+ continue;
+ if (c == 0x0A)
+ {
+ /* new line */
+ p.y += lineheight;
+ p.x = 0;
+ continue;
+ }
+ if (c == 0x09)
+ {
+ // tab = 4*space
+ unsigned cw = getCharWidth(0x20);
+ p.x += cw * 4;
+ continue;
+ }
+ glyphlize(c);
+ p.x += glyph->width + spacing;
+ i += 4;
+ }
+ getTextBox(text, &page->size.w, &page->size.h, lineheight, spacing);
+ return page;
+ }
+
+ Page* TTF::typeset(const Text& text, int lineheight, int spacing)
+ {
+ return typeset(*text, lineheight, spacing);
+ }
+
+ void TTF::render(const Page* page, int x, int y)
+ {
+ Shader* shader = Shader::getCurrentShader();
+ const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist;
+ const vector<GlyphVertex>& glyphvertices = page->glyphvertices;
+ gl.ModelMatrix.setTransformation(x, y, 0, 1, 1, 0, 0);
+ shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
+ for (int i = 0; i < glyphinfolist.size(); ++i)
+ {
+ const GlyphArrayDrawInfo& info = glyphinfolist[i];
+ shader->bindVertexPointer(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x);
+ shader->bindUVPointer(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u);
+ gl.bindTexture(info.texture);
+ gl.drawArrays(GL_QUADS, 0, info.count);
+ gl.bindTexture(0);
+ }
+ }
+
+ void TTF::render(const Text& text, int x, int y, int lineheight, int spacing /* = 0 */)
+ {
+ render(*text, x, y, lineheight, spacing);
+ }
+
+ int TTF::getCharWidth(int c)
+ {
+ int adw, lsb;
+ ttf->pushTTFsize(mFontSize);
+ ttf->getHMetrics(c, &adw, &lsb);
+ ttf->popTTFsize();
+ return adw;
+ }
+
+ int TTF::getCharHeight(int c)
+ {
+ return descent;
+ }
+
+ int TTF::getTextWidth(const Content& t, int spacing)
+ {
+ ttf->pushTTFsize(mFontSize);
+ int res = 0;
+ int tmp = 0;
+ for (Codepoint c : t)
+ {
+ if (c == 0x0D)
+ continue;
+ if (c == 0x0A)
+ {
+ tmp = 0;
+ continue;
+ }
+ tmp += getCharWidth(c) + spacing;
+ if (tmp > res)
+ res = tmp;
+ }
+ ttf->popTTFsize();
+ return res;
+ }
+
+ int TTF::getTextHeight(const Content& t, int lineheight)
+ {
+ ttf->pushTTFsize(mFontSize);
+ int res = 0;
+ bool newline = true;
+ for (Codepoint c : t)
+ {
+ if (c == 0x0A)
+ newline = true;
+ else if (c == 0x0D);
+ else if (newline)
+ {
+ newline = false;
+ res += lineheight;
+ }
+ }
+ ttf->popTTFsize();
+ return res;
+ }
+
+ void TTF::getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing)
+ {
+ ttf->pushTTFsize(mFontSize);
+ *w = 0;
+ *h = 0;
+ int tmp = 0;
+ bool newline = true;
+ for (Codepoint c : text)
+ {
+ if (c == 0x0D)
+ continue;
+ if (c == 0x0A)
+ {
+ tmp = 0;
+ newline = true;
+ continue;
+ }
+ else if (newline)
+ {
+ newline = false;
+ *h += lineheight;
+ }
+ tmp += getCharWidth(c) + spacing;
+ if (tmp > *w)
+ *w = tmp;
+ }
+ ttf->popTTFsize();
+ }
+
+ TTF::TTFGlyph& TTF::bakeGlyph(unsigned int character)
+ {
+ int w, h, xoff, yoff;
+ ttf->pushTTFsize(mFontSize);
+ GLuint atlas = atlases.back();
+ const Color* bitmap = ttf->getCodepointBitmap(character, &w, &h, &xoff, &yoff);
+ int adw, lsb;
+ {
+ /* bake glyph */
+ ttf->getHMetrics(character, &adw, &lsb);
+ ttf->popTTFsize();
+ if (cursor.x + adw > textureWidth)
+ {
+ cursor.x = 0;
+ cursor.y += descent;
+ if (cursor.y + descent * 2 > textureHeight)
+ {
+ /* create new atlas */
+ atlas = createAtlas();
+ cursor.y = 0;
+ }
+ }
+ gl.bindTexture(atlas);
+ gl.texSubImage(cursor.x + xoff, cursor.y + yoff + baseline, w, h, GL_RGBA, GL_UNSIGNED_BYTE, bitmap);
+ gl.bindTexture();
+ delete[] bitmap;
+ }
+ TTFGlyph glyph;
+ glyph.atlas = atlas;
+ glyph.bbox.x = cursor.x / (float)textureWidth;
+ glyph.bbox.y = cursor.y / (float)textureHeight;
+ glyph.bbox.w = adw / (float)textureWidth;
+ glyph.bbox.h = descent / (float)textureHeight;
+ glyph.width = adw;
+ glyph.height = descent;
+ glyphs.insert(std::pair<unsigned int, TTFGlyph>(character, glyph));
+ cursor.x += adw;
+ return glyphs[character];
+ }
+
+ TTF::TTFGlyph& TTF::findGlyph(unsigned int character)
+ {
+ map<unsigned int, TTFGlyph>::iterator it = glyphs.find(character);
+ if (it != glyphs.end())
+ return it->second;
+ else
+ return bakeGlyph(character);
+ }
+
+ } // namespace Fonts
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif // defined(jin_graphics) \ No newline at end of file
diff --git a/src/libjin/Graphics/fonts/je_ttf.h b/src/libjin/Graphics/fonts/je_ttf.h
new file mode 100644
index 0000000..02017ec
--- /dev/null
+++ b/src/libjin/Graphics/fonts/je_ttf.h
@@ -0,0 +1,292 @@
+#ifndef __JETTF_H
+#define __JE_TTF_H
+#include "../../core/je_configuration.h"
+#if defined(jin_graphics)
+
+#include <vector>
+#include <map>
+
+#include "stb/stb_truetype.h"
+
+#include "../../math/je_quad.h"
+
+#include "../je_color.h"
+#include "../je_graphic.h"
+
+#include "je_page.h"
+#include "je_font.h"
+#include "je_text.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Fonts
+ {
+
+ class TTF;
+
+ //
+ // TTFData
+ // |- TTF(14px)
+ // |- TTF(15px)
+ // .
+ // .
+ // .
+ //
+ class TTFData
+ {
+ public:
+
+ ///
+ ///
+ ///
+ static TTFData* createTTFData(const unsigned char* data, unsigned int size);
+
+ ///
+ ///
+ ///
+ ~TTFData();
+
+ ///
+ ///
+ ///
+ TTF* createTTF(unsigned ttfsize);
+
+ ///
+ ///
+ ///
+ void pushTTFsize(unsigned ttfsize);
+
+ ///
+ ///
+ ///
+ void popTTFsize();
+
+ ///
+ ///
+ ///
+ Channel* getCodepointBitmapAlpha(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const;
+
+ ///
+ ///
+ ///
+ Color* getCodepointBitmap(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const;
+
+ ///
+ ///
+ ///
+ void getVMetrics(int* baseline, int* descent);
+
+ ///
+ ///
+ ///
+ void getHMetrics(unsigned int codepoint, int* advanceWidth, int* leftSideBearing);
+
+ private:
+
+ ///
+ ///
+ ///
+ static const unsigned int FONT_SIZE = 12;
+
+ ///
+ ///
+ ///
+ TTFData(const unsigned char* data, unsigned int size);
+
+ ///
+ ///
+ ///
+ stbtt_fontinfo info;
+
+ ///
+ ///
+ ///
+ struct
+ {
+ unsigned char* data;
+ unsigned int size;
+ } raw;
+
+ ///
+ ///
+ ///
+ std::vector<float> scales;
+
+ };
+
+ class TTF : public Font
+ {
+ public:
+ //static TTF* createTTF(TTFData* ttfData, unsigned ttfSzie);
+
+ ///
+ ///
+ ///
+ Page* typeset(const Text& text, int lineheight, int spacing = 0) override;
+
+ ///
+ ///
+ ///
+ Page* typeset(const Content& text, int lineheight, int spacing = 0) override;
+
+ ///
+ ///
+ ///
+ void render(const Text& text, int x, int y, int lineheight, int spacing = 0) override;
+
+ ///
+ ///
+ ///
+ void render(const Content& text, int x, int y, int lineheight, int spacing = 0) override;
+
+ ///
+ ///
+ ///
+ void render(const Page* page, int x, int y) override;
+
+ ///
+ ///
+ ///
+ ~TTF();
+
+ private:
+
+ friend class TTFData;
+
+ ///
+ ///
+ ///
+ struct TTFGlyph
+ {
+ GLuint atlas;
+ // normalized coordinates
+ struct Bbox
+ {
+ float x, y;
+ float w, h;
+ } bbox;
+ // glyph size in pixel
+ unsigned int width, height;
+ };
+
+ ///
+ ///
+ ///
+ static const int TEXTURE_SIZE_LEVELS_COUNT = 7;
+
+ ///
+ ///
+ ///
+ static const int TEXTURE_SIZE_LEVEL_MAX = TEXTURE_SIZE_LEVELS_COUNT - 1;
+
+ ///
+ ///
+ ///
+ static const int TEXTURE_WIDTHS[TEXTURE_SIZE_LEVELS_COUNT];
+
+ ///
+ ///
+ ///
+ static const int TEXTURE_HEIGHTS[TEXTURE_SIZE_LEVELS_COUNT];
+
+ ///
+ ///
+ ///
+ TTF(TTFData* ttf, Codepoint ttfSize);
+
+ ///
+ ///
+ ///
+ void estimateSize();
+
+ ///
+ ///
+ ///
+ GLuint createAtlas();
+
+ ///
+ ///
+ ///
+ TTFGlyph& bakeGlyph(Codepoint character);
+
+ ///
+ ///
+ ///
+ TTFGlyph& findGlyph(Codepoint character);
+
+ ///
+ ///
+ ///
+ int getCharWidth(int c);
+
+ ///
+ ///
+ ///
+ int getCharHeight(int c);
+
+ ///
+ ///
+ ///
+ int getTextWidth(const Content& text, int spacing = 0);
+
+ ///
+ ///
+ ///
+ int getTextHeight(const Content& text, int lineheight);
+
+ ///
+ ///
+ ///
+ void getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing = 0);
+
+ ///
+ ///
+ ///
+ int textureWidth;
+
+ ///
+ ///
+ ///
+ int textureHeight;
+
+ ///
+ ///
+ ///
+ std::vector<GLuint> atlases;
+
+ ///
+ ///
+ ///
+ std::map<Codepoint, TTFGlyph> glyphs;
+
+ ///
+ ///
+ ///
+ TTFData* ttf;
+
+ ///
+ ///
+ ///
+ int baseline;
+
+ ///
+ ///
+ ///
+ int descent;
+
+ ///
+ ///
+ ///
+ Math::Vector2<float> cursor;
+
+ };
+
+ } // namespace Fonts
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif // defined(jin_graphics)
+
+#endif // __JE_FONT_H \ No newline at end of file
diff --git a/src/libjin/Graphics/je_graphic.cpp b/src/libjin/Graphics/je_graphic.cpp
index 66fb494..5df202f 100644
--- a/src/libjin/Graphics/je_graphic.cpp
+++ b/src/libjin/Graphics/je_graphic.cpp
@@ -5,9 +5,11 @@
#include "../math/je_matrix.h"
-#include "shader/je_shader.h"
+#include "shaders/je_shader.h"
#include "je_graphic.h"
+using namespace JinEngine::Graphics::Shaders;
+
namespace JinEngine
{
namespace Graphics
diff --git a/src/libjin/Graphics/je_graphics.h b/src/libjin/Graphics/je_graphics.h
index e2e9a2d..bef72c0 100644
--- a/src/libjin/Graphics/je_graphics.h
+++ b/src/libjin/Graphics/je_graphics.h
@@ -11,13 +11,13 @@
#include "je_bitmap.h"
#include "je_image.h"
-#include "shader/je_shader.h"
+#include "shaders/je_shader.h"
-#include "font/je_ttf.h"
-#include "font/je_text.h"
-#include "font/je_texture_font.h"
+#include "fonts/je_ttf.h"
+#include "fonts/je_text.h"
+#include "fonts/je_texture_font.h"
-#include "particle/je_particle_system.h"
+#include "particles/je_particle_system.h"
#endif // defined(jin_graphics)
#endif // __JE_GRAPHICS_H \ No newline at end of file
diff --git a/src/libjin/Graphics/je_shapes.cpp b/src/libjin/Graphics/je_shapes.cpp
index 3146f31..f15300d 100644
--- a/src/libjin/Graphics/je_shapes.cpp
+++ b/src/libjin/Graphics/je_shapes.cpp
@@ -6,9 +6,11 @@
#include "../math/je_matrix.h"
#include "../math/je_constant.h"
-#include "shader/je_shader.h"
+#include "shaders/je_shader.h"
#include "je_shapes.h"
+using namespace JinEngine::Graphics::Shaders;
+
namespace JinEngine
{
namespace Graphics
diff --git a/src/libjin/Graphics/je_sprite.h b/src/libjin/Graphics/je_sprite.h
index 730e11e..6e6812a 100644
--- a/src/libjin/Graphics/je_sprite.h
+++ b/src/libjin/Graphics/je_sprite.h
@@ -4,7 +4,7 @@
#include "../common/je_types.h"
#include "../math/je_vector2.hpp"
-#include "shader/je_shader.h"
+#include "shaders/je_shader.h"
#include "je_color.h"
namespace JinEngine
@@ -22,7 +22,7 @@ namespace JinEngine
void setPosition(int x, int y);
void setScale(float x, float y);
void setColor(Color color);
- void setShader(const Shader* shader);
+ void setShader(const Shaders::Shader* shader);
void setGraphic(const Graphic* graphic);
///
@@ -38,7 +38,7 @@ namespace JinEngine
Math::Vector2<int> mOrigin;
Math::Vector2<float> mScale;
Color mColor;
- Shader* mShader;
+ Shaders::Shader* mShader;
Graphic* mGraphic;
};
diff --git a/src/libjin/Graphics/je_window.cpp b/src/libjin/Graphics/je_window.cpp
index b36a2a3..7265898 100644
--- a/src/libjin/Graphics/je_window.cpp
+++ b/src/libjin/Graphics/je_window.cpp
@@ -7,11 +7,13 @@
#include "../audio/sdl/je_sdl_audio.h"
#include "../utils/je_log.h"
-#include "shader/je_shader.h"
+#include "shaders/je_shader.h"
#include "je_window.h"
#include "je_gl.h"
#include "je_canvas.h"
+using namespace JinEngine::Graphics::Shaders;
+
namespace JinEngine
{
namespace Graphics
@@ -19,9 +21,7 @@ namespace JinEngine
bool Window::initSystem(const SettingBase* s)
{
- #if defined(jin_debug)
- Loghelper::log(Loglevel::LV_INFO, "Init window system");
- #endif
+ jin_log_info("Initialize window system.");
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return false;
@@ -84,6 +84,7 @@ namespace JinEngine
void Window::quitSystem()
{
+ jin_log_info("Quit window system.");
// disable opengl
gl.disable(GL_BLEND);
gl.disable(GL_TEXTURE_2D);
diff --git a/src/libjin/Graphics/particle/je_particle.h b/src/libjin/Graphics/particle/je_particle.h
deleted file mode 100644
index 089bf35..0000000
--- a/src/libjin/Graphics/particle/je_particle.h
+++ /dev/null
@@ -1,154 +0,0 @@
-#ifndef __JE_PARTICLE_H
-#define __JE_PARTICLE_H
-
-#include "../../math/je_vector2.hpp"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- class ParticleEmitter;
-
- struct LifeTimeDef
- {
- bool enableRandom = false;
- union
- {
- struct
- {
- float min, max;
- } random;
- float life;
- } life;
- };
-
- struct LinearAccelaration
- {
-
- };
-
- struct SpeedOverTimeDef
- {
- bool enable = false;
- bool enableRandom = false;
- union
- {
- struct
- {
- Math::Vector2<float> startFloor;
- Math::Vector2<float> startCeil;
- Math::Vector2<float> endFloor;
- Math::Vector2<float> endCeil;
- } random;
- struct
- {
- Math::Vector2<float> start;
- Math::Vector2<float> end;
- } speed;
- } speed;
- };
-
- struct SizeOverTimeDef
- {
- bool enable = false;
- bool enableRandom = false;
- union {
- struct {
- float startFloor = 1;
- float startCeil = 1;
- float endFloor = 1;
- float endCeil = 1;
- } random;
- struct {
- float start = 1;
- float end = 1;
- } size;
- } size;
- };
-
- struct ColorOverTime
- {
- bool enable = false;
- Color colorStart = Color::WHITE;
- Color colorEnd = Color::WHITE;
- };
-
- ///
- ///
- ///
- struct ParticleDef
- {
- private:
- friend class ParticleEmitter;
-
- public:
- // Basic definitions.
- LifeTimeDef lifeTimeDef; ///<
- // Optional definitions.
-
- SpeedOverTimeDef speedOverTimeDef; ///<
- SizeOverTimeDef sizeOverTimeDef; ///<
- ColorOverTime colorOverTimeDef; ///<
- };
-
- ///
- /// A single particle contains various properties of particle, such as position, accelaration, color and
- /// other attributes changed over time.
- ///
- struct Particle
- {
- Particle(const ParticleDef& particleDef);
- ///
- /// Whole life time.
- ///
- float lifeTime = 0.0f;
-
- ///
- /// Current life time.
- ///
- float life = 0.0f;
-
- ///
- /// Current position.
- ///
- float position[2] = {0,0};
-
- ///
- /// Emitte direction.
- ///
- float direction = 0;
-
- Math::Vector2<float> speed;
- Math::Vector2<float> linearAcceleration;
- float radialAcceleration = 0;
- float tangetialAcceleration = 0;
-
- ///
- /// Size over lifetime.
- ///
- float size = 1;
- float sizeBegin = 1;
- float sizeEnd = 1;
-
- float rotation = 0;
- float angle = 0;
-
- ///
- /// Color over lifetime.
- ///
- Color color = Color::WHITE;
- Color colorStart = Color::WHITE;
- Color colorEnd = Color::WHITE;
-
- ///
- /// Is particle still alive? Alive is equivalent to NOT available in particle pool.
- ///
- bool alive = false;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/particle/je_particle_emitter.h b/src/libjin/Graphics/particle/je_particle_emitter.h
deleted file mode 100644
index 5e4316d..0000000
--- a/src/libjin/Graphics/particle/je_particle_emitter.h
+++ /dev/null
@@ -1,96 +0,0 @@
-#ifndef __JE_PARTICLE_EMITTER_H
-#define __JE_PARTICLE_EMITTER_H
-
-#include "../../common/je_temporary.h"
-#include "../../math/je_vector2.hpp"
-
-#include "je_particle.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- struct PositionDef
- {
- bool enableRandom = false;
- union
- {
- struct
- {
- Math::Vector2<float> min;
- Math::Vector2<float> max;
- } random;
- Math::Vector2<float> position;
- } position;
- };
-
- struct DirectionDef
- {
- bool enableRandom = false;
- union
- {
- struct
- {
- float min = 0;
- float max = 0;
- } random;
- float direction = 0;
- } direction;
- };
-
- struct EmitRateDef
- {
- bool enableRandom = false;
- union
- {
- struct
- {
- float min = 1;
- float max = 1;
- } random;
- float rate = 1;
- } rate;
- };
-
- ///
- /// Definition of particle emitter.
- ///
- struct ParticleEmitterDef : public Temporary
- {
- PositionDef positionDef; ///< Emit position(relativily to the particle system center).
- DirectionDef directionDef; ///< Emit direction.
- EmitRateDef emitRateDef; ///< Emit rate.
- };
-
- ///
- /// Emit a single particle.
- ///
- class ParticleEmitter
- {
- public:
- ///
- /// ParticleEmitter constructor.
- ///
- /// @param emitterDef Definition of particle emitter.
- /// @param particleDef Definition of particle.
- ///
- ParticleEmitter(const ParticleEmitterDef& emitterDef, const ParticleDef& particleDef);
-
- ///
- /// Emit a particle according to emitter definition and particle definition, particle system should
- /// assign particle value to the particle in particle pool, but not use this return particle.
- ///
- Particle emit();
-
- private:
- float mDirection;
- ParticleEmitterDef mEmitterDef;
- ParticleDef mParticleDef;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/particle/je_particle_pool.h b/src/libjin/Graphics/particle/je_particle_pool.h
deleted file mode 100644
index f1f6214..0000000
--- a/src/libjin/Graphics/particle/je_particle_pool.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef __JE_PARTICLE_BATCH_H
-#define __JE_PARTICLE_BATCH_H
-
-#include <list>
-
-#include "je_particle.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- ///
- /// Particle pool for reducing memory fragmentation.
- ///
- class ParticlePool
- {
- public:
-
- ///
- /// Particle pool constructor.
- ///
- /// @param count Max count of particles.
- ///
- ParticlePool(uint count);
-
- ///
- /// Particle pool destructor.
- ///
- ~ParticlePool();
-
- ///
- /// Claim a particle if available.
- ///
- Particle* claim();
-
- ///
- /// Recycle particle if the particle is no more alive.
- ///
- void recycle(Particle* particle);
-
- private:
- ///
- /// All particles include available and inavailable particles.
- ///
- std::list<Particle> particles;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/particle/je_particle_system.h b/src/libjin/Graphics/particle/je_particle_system.h
deleted file mode 100644
index 8526da8..0000000
--- a/src/libjin/Graphics/particle/je_particle_system.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef __JE_PARTICLE_EMMITTER_H
-#define __JE_PARTICLE_EMMITTER_H
-
-#include <vector>
-
-#include "../../common/je_temporary.h"
-#include "../../game/je_gameobject.h"
-
-#include "../je_sprite.h"
-
-#include "je_particle_emitter.h"
-#include "je_particle_pool.h"
-#include "je_particle.h"
-
-namespace JinEngine
-{
- namespace Graphics
- {
-
- ///
- /// Definition of particle system.
- ///
- struct ParticleSystemDef : public Temporary
- {
- uint maxParticleCount = 1; ///< Max count of particles in pool. 1 by default.
-
- ParticleEmitterDef emitterDef; ///< Particle emitter definition.
- ParticleDef particleDef; ///< Particle definition.
- };
-
- ///
- /// Particle emitter, handle all particles it emitts.
- ///
- class ParticleSystem : public Game::GameObject
- {
- public:
- ///
- /// Particle system constructor
- ///
- /// @param def Definition of particle system.
- ///
- ParticleSystem(const ParticleSystemDef& def);
-
- ///
- /// Particle system destructor.
- ///
- ~ParticleSystem();
-
- ///
- /// Render particle system's all particles.
- ///
- void render(int x, int y, float sx = 1, float sy = 1, float r = 0, float ax = 0, float ay = 0);
-
- ///
- /// Set sprite to render.
- ///
- /// @param sprite Sprite to render.
- ///
- void setSprite(Sprite* sprite);
-
- ///
- /// Release particle and make it available in particle pool.
- ///
- void releaseParticle();
-
- private:
- // Disable default constructor.
- ParticleSystem();
-
- ///
- /// Sprite to be drawn.
- ///
- Sprite* mSprite;
-
- ///
- /// Particle emitter.
- ///
- ParticleEmitter mEmitter;
- ParticlePool mParticlePool;
-
- ///
- /// Alive particles, that means these particles could join to the life cycle loop.
- ///
- std::vector<Particle*> mAliveParticles;
-
- };
-
- } // namespace Graphics
-} // namespace JinEngine
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/particle/je_particle.cpp b/src/libjin/Graphics/particles/je_particle.cpp
index e69de29..e69de29 100644
--- a/src/libjin/Graphics/particle/je_particle.cpp
+++ b/src/libjin/Graphics/particles/je_particle.cpp
diff --git a/src/libjin/Graphics/particles/je_particle.h b/src/libjin/Graphics/particles/je_particle.h
new file mode 100644
index 0000000..819b95c
--- /dev/null
+++ b/src/libjin/Graphics/particles/je_particle.h
@@ -0,0 +1,157 @@
+#ifndef __JE_PARTICLE_H
+#define __JE_PARTICLE_H
+
+#include "../../math/je_vector2.hpp"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Particles
+ {
+
+ class ParticleEmitter;
+
+ struct LifeTimeDef
+ {
+ bool enableRandom = false;
+ union
+ {
+ struct
+ {
+ float min, max;
+ } random;
+ float life;
+ } life;
+ };
+
+ struct LinearAccelaration
+ {
+
+ };
+
+ struct SpeedOverTimeDef
+ {
+ bool enable = false;
+ bool enableRandom = false;
+ union
+ {
+ struct
+ {
+ Math::Vector2<float> startFloor;
+ Math::Vector2<float> startCeil;
+ Math::Vector2<float> endFloor;
+ Math::Vector2<float> endCeil;
+ } random;
+ struct
+ {
+ Math::Vector2<float> start;
+ Math::Vector2<float> end;
+ } speed;
+ } speed;
+ };
+
+ struct SizeOverTimeDef
+ {
+ bool enable = false;
+ bool enableRandom = false;
+ union {
+ struct {
+ float startFloor = 1;
+ float startCeil = 1;
+ float endFloor = 1;
+ float endCeil = 1;
+ } random;
+ struct {
+ float start = 1;
+ float end = 1;
+ } size;
+ } size;
+ };
+
+ struct ColorOverTime
+ {
+ bool enable = false;
+ Color colorStart = Color::WHITE;
+ Color colorEnd = Color::WHITE;
+ };
+
+ ///
+ ///
+ ///
+ struct ParticleDef
+ {
+ private:
+ friend class ParticleEmitter;
+
+ public:
+ // Basic definitions.
+ LifeTimeDef lifeTimeDef; ///<
+ // Optional definitions.
+
+ SpeedOverTimeDef speedOverTimeDef; ///<
+ SizeOverTimeDef sizeOverTimeDef; ///<
+ ColorOverTime colorOverTimeDef; ///<
+ };
+
+ ///
+ /// A single particle contains various properties of particle, such as position, accelaration, color and
+ /// other attributes changed over time.
+ ///
+ struct Particle
+ {
+ Particle(const ParticleDef& particleDef);
+ ///
+ /// Whole life time.
+ ///
+ float lifeTime = 0.0f;
+
+ ///
+ /// Current life time.
+ ///
+ float life = 0.0f;
+
+ ///
+ /// Current position.
+ ///
+ float position[2] = { 0,0 };
+
+ ///
+ /// Emitte direction.
+ ///
+ float direction = 0;
+
+ Math::Vector2<float> speed;
+ Math::Vector2<float> linearAcceleration;
+ float radialAcceleration = 0;
+ float tangetialAcceleration = 0;
+
+ ///
+ /// Size over lifetime.
+ ///
+ float size = 1;
+ float sizeBegin = 1;
+ float sizeEnd = 1;
+
+ float rotation = 0;
+ float angle = 0;
+
+ ///
+ /// Color over lifetime.
+ ///
+ Color color = Color::WHITE;
+ Color colorStart = Color::WHITE;
+ Color colorEnd = Color::WHITE;
+
+ ///
+ /// Is particle still alive? Alive is equivalent to NOT available in particle pool.
+ ///
+ bool alive = false;
+
+ };
+
+ } // namespace Particles
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/particle/je_particle_emitter.cpp b/src/libjin/Graphics/particles/je_particle_emitter.cpp
index 0ab9cf1..0ab9cf1 100644
--- a/src/libjin/Graphics/particle/je_particle_emitter.cpp
+++ b/src/libjin/Graphics/particles/je_particle_emitter.cpp
diff --git a/src/libjin/Graphics/particles/je_particle_emitter.h b/src/libjin/Graphics/particles/je_particle_emitter.h
new file mode 100644
index 0000000..c6e4321
--- /dev/null
+++ b/src/libjin/Graphics/particles/je_particle_emitter.h
@@ -0,0 +1,99 @@
+#ifndef __JE_PARTICLE_EMITTER_H
+#define __JE_PARTICLE_EMITTER_H
+
+#include "../../common/je_temporary.h"
+#include "../../math/je_vector2.hpp"
+
+#include "je_particle.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Particles
+ {
+
+ struct PositionDef
+ {
+ bool enableRandom = false;
+ union
+ {
+ struct
+ {
+ Math::Vector2<float> min;
+ Math::Vector2<float> max;
+ } random;
+ Math::Vector2<float> position;
+ } position;
+ };
+
+ struct DirectionDef
+ {
+ bool enableRandom = false;
+ union
+ {
+ struct
+ {
+ float min = 0;
+ float max = 0;
+ } random;
+ float direction = 0;
+ } direction;
+ };
+
+ struct EmitRateDef
+ {
+ bool enableRandom = false;
+ union
+ {
+ struct
+ {
+ float min = 1;
+ float max = 1;
+ } random;
+ float rate = 1;
+ } rate;
+ };
+
+ ///
+ /// Definition of particle emitter.
+ ///
+ struct ParticleEmitterDef : public Temporary
+ {
+ PositionDef positionDef; ///< Emit position(relativily to the particle system center).
+ DirectionDef directionDef; ///< Emit direction.
+ EmitRateDef emitRateDef; ///< Emit rate.
+ };
+
+ ///
+ /// Emit a single particle.
+ ///
+ class ParticleEmitter
+ {
+ public:
+ ///
+ /// ParticleEmitter constructor.
+ ///
+ /// @param emitterDef Definition of particle emitter.
+ /// @param particleDef Definition of particle.
+ ///
+ ParticleEmitter(const ParticleEmitterDef& emitterDef, const ParticleDef& particleDef);
+
+ ///
+ /// Emit a particle according to emitter definition and particle definition, particle system should
+ /// assign particle value to the particle in particle pool, but not use this return particle.
+ ///
+ Particle emit();
+
+ private:
+ float mDirection;
+ ParticleEmitterDef mEmitterDef;
+ ParticleDef mParticleDef;
+
+ };
+
+ } // namespace Particles
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/particle/je_particle_pool.cpp b/src/libjin/Graphics/particles/je_particle_pool.cpp
index e69de29..e69de29 100644
--- a/src/libjin/Graphics/particle/je_particle_pool.cpp
+++ b/src/libjin/Graphics/particles/je_particle_pool.cpp
diff --git a/src/libjin/Graphics/particles/je_particle_pool.h b/src/libjin/Graphics/particles/je_particle_pool.h
new file mode 100644
index 0000000..9bc7d78
--- /dev/null
+++ b/src/libjin/Graphics/particles/je_particle_pool.h
@@ -0,0 +1,56 @@
+#ifndef __JE_PARTICLE_BATCH_H
+#define __JE_PARTICLE_BATCH_H
+
+#include <list>
+
+#include "je_particle.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Particles
+ {
+
+ ///
+ /// Particle pool for reducing memory fragmentation.
+ ///
+ class ParticlePool
+ {
+ public:
+
+ ///
+ /// Particle pool constructor.
+ ///
+ /// @param count Max count of particles.
+ ///
+ ParticlePool(uint count);
+
+ ///
+ /// Particle pool destructor.
+ ///
+ ~ParticlePool();
+
+ ///
+ /// Claim a particle if available.
+ ///
+ Particle* claim();
+
+ ///
+ /// Recycle particle if the particle is no more alive.
+ ///
+ void recycle(Particle* particle);
+
+ private:
+ ///
+ /// All particles include available and inavailable particles.
+ ///
+ std::list<Particle> particles;
+
+ };
+
+ } // namespace Particles
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/particle/je_particle_system.cpp b/src/libjin/Graphics/particles/je_particle_system.cpp
index 68f8f21..68f8f21 100644
--- a/src/libjin/Graphics/particle/je_particle_system.cpp
+++ b/src/libjin/Graphics/particles/je_particle_system.cpp
diff --git a/src/libjin/Graphics/particles/je_particle_system.h b/src/libjin/Graphics/particles/je_particle_system.h
new file mode 100644
index 0000000..aa7ff99
--- /dev/null
+++ b/src/libjin/Graphics/particles/je_particle_system.h
@@ -0,0 +1,94 @@
+#ifndef __JE_PARTICLE_EMMITTER_H
+#define __JE_PARTICLE_EMMITTER_H
+
+#include <vector>
+
+#include "../../common/je_temporary.h"
+#include "../../game/je_gameobject.h"
+
+#include "../je_sprite.h"
+
+#include "je_particle_emitter.h"
+#include "je_particle_pool.h"
+#include "je_particle.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Particles
+ {
+
+ ///
+ /// Definition of particle system.
+ ///
+ struct ParticleSystemDef : public Temporary
+ {
+ uint maxParticleCount = 1; ///< Max count of particles in pool. 1 by default.
+
+ ParticleEmitterDef emitterDef; ///< Particle emitter definition.
+ ParticleDef particleDef; ///< Particle definition.
+ };
+
+ ///
+ /// Particle emitter, handle all particles it emitts.
+ ///
+ class ParticleSystem : public Game::GameObject
+ {
+ public:
+ ///
+ /// Particle system constructor
+ ///
+ /// @param def Definition of particle system.
+ ///
+ ParticleSystem(const ParticleSystemDef& def);
+
+ ///
+ /// Particle system destructor.
+ ///
+ ~ParticleSystem();
+
+ ///
+ /// Render particle system's all particles.
+ ///
+ void render(int x, int y, float sx = 1, float sy = 1, float r = 0, float ax = 0, float ay = 0);
+
+ ///
+ /// Set sprite to render.
+ ///
+ /// @param sprite Sprite to render.
+ ///
+ void setSprite(Sprite* sprite);
+
+ ///
+ /// Release particle and make it available in particle pool.
+ ///
+ void releaseParticle();
+
+ private:
+ // Disable default constructor.
+ ParticleSystem();
+
+ ///
+ /// Sprite to be drawn.
+ ///
+ Sprite* mSprite;
+
+ ///
+ /// Particle emitter.
+ ///
+ ParticleEmitter mEmitter;
+ ParticlePool mParticlePool;
+
+ ///
+ /// Alive particles, that means these particles could join to the life cycle loop.
+ ///
+ std::vector<Particle*> mAliveParticles;
+
+ };
+
+ } // namespace Particles
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Shader/shaders/je_default.shader.h b/src/libjin/Graphics/shaders/built-in/je_default.shader.h
index 3f57c44..3f57c44 100644
--- a/src/libjin/Graphics/Shader/shaders/je_default.shader.h
+++ b/src/libjin/Graphics/shaders/built-in/je_default.shader.h
diff --git a/src/libjin/Graphics/Shader/shaders/je_font.shader.h b/src/libjin/Graphics/shaders/built-in/je_font.shader.h
index e04c225..e04c225 100644
--- a/src/libjin/Graphics/Shader/shaders/je_font.shader.h
+++ b/src/libjin/Graphics/shaders/built-in/je_font.shader.h
diff --git a/src/libjin/Graphics/Shader/shaders/je_texture.shader.h b/src/libjin/Graphics/shaders/built-in/je_texture.shader.h
index d1fc86f..d1fc86f 100644
--- a/src/libjin/Graphics/Shader/shaders/je_texture.shader.h
+++ b/src/libjin/Graphics/shaders/built-in/je_texture.shader.h
diff --git a/src/libjin/Graphics/Shader/je_base.shader.h b/src/libjin/Graphics/shaders/je_base.shader.h
index d6f9d7b..d6f9d7b 100644
--- a/src/libjin/Graphics/Shader/je_base.shader.h
+++ b/src/libjin/Graphics/shaders/je_base.shader.h
diff --git a/src/libjin/Graphics/shaders/je_jsl_compiler.cpp b/src/libjin/Graphics/shaders/je_jsl_compiler.cpp
new file mode 100644
index 0000000..feb88d4
--- /dev/null
+++ b/src/libjin/Graphics/shaders/je_jsl_compiler.cpp
@@ -0,0 +1,57 @@
+#include "../../core/je_configuration.h"
+#if defined(jin_graphics) && (jin_graphics & jin_graphics_shader)
+
+#include "../../Filesystem/je_buffer.h"
+
+#include "je_jsl_compiler.h"
+
+using namespace std;
+using namespace JinEngine::Filesystem;
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Shaders
+ {
+
+ #include "je_base.shader.h"
+
+ bool JSLCompiler::compile(const string& jsl, string* vertex_shader, string* fragment_shader)
+ {
+ // parse shader source, need some optimizations
+ int loc_VERTEX_SHADER = jsl.find("#VERTEX_SHADER");
+ int loc_END_VERTEX_SHADER = jsl.find("#END_VERTEX_SHADER");
+ int loc_FRAGMENT_SHADER = jsl.find("#FRAGMENT_SHADER");
+ int loc_END_FRAGMENT_SHADER = jsl.find("#END_FRAGMENT_SHADER");
+ if (loc_VERTEX_SHADER == string::npos
+ || loc_END_VERTEX_SHADER == string::npos
+ || loc_FRAGMENT_SHADER == string::npos
+ || loc_END_FRAGMENT_SHADER == string::npos
+ )
+ return false;
+ // Load vertex and fragment shader source into buffers.
+ {
+ // Compile JSL vertex program.
+ int start = loc_VERTEX_SHADER + strlen("#VERTEX_SHADER");
+ *vertex_shader = jsl.substr(start, loc_END_VERTEX_SHADER - start);
+ Buffer vbuffer = Buffer(vertex_shader->length() + BASE_VERTEX_SHADER_SIZE);
+ formatVertexShader((char*)&vbuffer, vertex_shader->c_str());
+ vertex_shader->assign((char*)&vbuffer);
+ }
+ {
+ // Compile JSL fragment program.
+ int start = loc_FRAGMENT_SHADER + strlen("#FRAGMENT_SHADER");
+ *fragment_shader = jsl.substr(start, loc_END_FRAGMENT_SHADER - start);
+ Buffer fbuffer = Buffer(fragment_shader->length() + BASE_FRAGMENT_SHADER_SIZE);
+ formatFragmentShader((char*)&fbuffer, fragment_shader->c_str());
+ fragment_shader->assign((char*)&fbuffer);
+ }
+ return true;
+ }
+
+ } // namespace Shaders
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif // (jin_graphics) && (jin_graphics & jin_graphics_shader) \ No newline at end of file
diff --git a/src/libjin/Graphics/shaders/je_jsl_compiler.h b/src/libjin/Graphics/shaders/je_jsl_compiler.h
new file mode 100644
index 0000000..eeb42ae
--- /dev/null
+++ b/src/libjin/Graphics/shaders/je_jsl_compiler.h
@@ -0,0 +1,45 @@
+#ifndef __JE_JSL_COMPILER_H
+#define __JE_JSL_COMPILER_H
+
+#include "../../core/je_configuration.h"
+#if defined(jin_graphics) && (jin_graphics & jin_graphics_shader)
+
+#include <string>
+
+#include "../../common/je_singleton.hpp"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Shaders
+ {
+
+ ///
+ /// Compile JSL into GLSL.
+ ///
+ class JSLCompiler : public Singleton<JSLCompiler>
+ {
+ public:
+ ///
+ /// Compile JSL shader source into GLSL.
+ ///
+ /// @param jsl JSL shader source.
+ /// @param glsl_vertex Output of vertex glsl shader source.
+ /// @param glsl_fragment Output of fragment glsl shader source.
+ /// @return True if compile successful, otherwise return false.
+ ///
+ bool compile(const std::string& jsl, std::string* glsl_vertex, std::string* glsl_fragment);
+
+ private:
+ singleton(JSLCompiler);
+
+ };
+
+ } // namespace Shaders
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif // (jin_graphics) && (jin_graphics & jin_graphics_shader)
+
+#endif // __JE_JSL_COMPILER_H \ No newline at end of file
diff --git a/src/libjin/Graphics/shaders/je_shader.cpp b/src/libjin/Graphics/shaders/je_shader.cpp
new file mode 100644
index 0000000..3eae5c7
--- /dev/null
+++ b/src/libjin/Graphics/shaders/je_shader.cpp
@@ -0,0 +1,281 @@
+#include "../../core/je_configuration.h"
+#if defined(jin_graphics) && (jin_graphics & jin_graphics_shader)
+
+#include <iostream>
+
+#include "../../filesystem/je_buffer.h"
+#include "../../utils/je_macros.h"
+
+#include "je_jsl_compiler.h"
+#include "je_shader.h"
+
+using namespace std;
+using namespace JinEngine::Filesystem;
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Shaders
+ {
+
+ //
+ // default_texture
+ // base_shader
+ // SHADER_FORMAT_SIZE
+ // formatShader
+ //
+#include "built-in/je_default.shader.h"
+
+//
+// https://stackoverflow.com/questions/27941496/use-sampler-without-passing-through-value
+// The default value of a sampler variable is 0. From the GLSL 3.30 spec,
+// section "4.3.5 Uniforms":
+//
+// The link time initial value is either the value of the variable's
+// initializer, if present, or 0 if no initializer is present.Sampler
+// types cannot have initializers.
+//
+// Since a value of 0 means that it's sampling from texture unit 0, it will
+// work without ever setting the value as long as you bind your textures to
+// unit 0. This is well defined behavior.
+//
+// Since texture unit 0 is also the default until you call glActiveTexture()
+// with a value other than GL_TEXTURE0, it's very common to always use unit
+// 0 as long as shaders do not need more than one texture.Which means that
+// often times, setting the sampler uniforms is redundant for simple
+// applications.
+//
+// I would still prefer to always set the values.If nothing else, it makes
+// it clear to anybody reading your code that you really mean to sample from
+// texture unit 0, and did not just forget to set the value.
+//
+ const int DEFAULT_TEXTURE_UNIT = 0;
+
+ /*static*/ Shader* Shader::CurrentShader = nullptr;
+
+ Shader* Shader::createShader(const string& program)
+ {
+ Shader* shader = nullptr;
+ try
+ {
+ shader = new Shader(program);
+ }
+ catch (...)
+ {
+ return nullptr;
+ }
+ return shader;
+ }
+
+ Shader::Shader(const string& program)
+ : mCurrentTextureUnit(DEFAULT_TEXTURE_UNIT)
+ {
+ if (!compile(program))
+ throw 0;
+ }
+
+ Shader::~Shader()
+ {
+ if (CurrentShader == this)
+ unuse();
+ // delete shader program
+ glDeleteShader(mPID);
+ }
+
+ bool Shader::compile(const string& program)
+ {
+ string vertex_shader, fragment_shader;
+ // Compile JSL shader source into GLSL shader source.
+ JSLCompiler* compiler = JSLCompiler::get();
+ if (!compiler->compile(program, &vertex_shader, &fragment_shader))
+ {
+ return false;
+ }
+#define glsl(SHADER_MODE, SHADER, SRC) \
+do{ \
+const GLchar* src = SRC.c_str(); \
+glShaderSource(SHADER, 1, &src, NULL); \
+glCompileShader(SHADER); \
+GLint success; \
+glGetShaderiv(SHADER, GL_COMPILE_STATUS, &success); \
+if (success == GL_FALSE) \
+ return false; \
+}while(0)
+ // Compile vertex shader.
+ GLuint vid = glCreateShader(GL_VERTEX_SHADER);
+ glsl(GL_VERTEX_SHADER, vid, vertex_shader);
+ // Compile fragment shader.
+ GLuint fid = glCreateShader(GL_FRAGMENT_SHADER);
+ glsl(GL_FRAGMENT_SHADER, fid, fragment_shader);
+#undef glsl
+ // Create OpenGL shader program.
+ mPID = glCreateProgram();
+ glAttachShader(mPID, vid);
+ glAttachShader(mPID, fid);
+ glLinkProgram(mPID);
+ GLint success;
+ glGetProgramiv(mPID, GL_LINK_STATUS, &success);
+ if (success == GL_FALSE)
+ return false;
+ }
+
+ static inline GLint getMaxTextureUnits()
+ {
+ GLint maxTextureUnits = 0;
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+ return maxTextureUnits;
+ }
+
+ void Shader::use()
+ {
+ glUseProgram(mPID);
+ CurrentShader = this;
+ sendInt(SHADER_MAIN_TEXTURE, DEFAULT_TEXTURE_UNIT);
+ }
+
+ /*static*/ void Shader::unuse()
+ {
+ glUseProgram(0);
+ CurrentShader = nullptr;
+ }
+
+ GLint Shader::claimTextureUnit(const std::string& name)
+ {
+ std::map<std::string, GLint>::iterator unit = mTextureUnits.find(name);
+ if (unit != mTextureUnits.end())
+ return unit->second;
+ static GLint MAX_TEXTURE_UNITS = getMaxTextureUnits();
+ if (++mCurrentTextureUnit >= MAX_TEXTURE_UNITS)
+ return 0;
+ mTextureUnits[name] = mCurrentTextureUnit;
+ return mCurrentTextureUnit;
+ }
+
+#define checkJSL() \
+ if (CurrentShader != this) \
+ return
+
+ void Shader::sendInt(const char* name, int value)
+ {
+ checkJSL();
+ int loc = glGetUniformLocation(mPID, name);
+ glUniform1i(loc, value);
+ }
+
+ void Shader::sendFloat(const char* variable, float number)
+ {
+ checkJSL();
+ int loc = glGetUniformLocation(mPID, variable);
+ glUniform1f(loc, number);
+ }
+
+ //
+ // https://www.douban.com/note/627332677/
+ // struct TextureUnit
+ // {
+ // GLuint targetTexture1D;
+ // GLuint targetTexture2D;
+ // GLuint targetTexture3D;
+ // GLuint targetTextureCube;
+ // ...
+ // };
+ //
+ // TextureUnit mTextureUnits[GL_MAX_TEXTURE_IMAGE_UNITS]
+ // GLuint mCurrentTextureUnit = 0;
+ //
+ void Shader::sendTexture(const char* variable, const Texture* tex)
+ {
+ checkJSL();
+ GLint location = glGetUniformLocation(mPID, variable);
+ if (location == -1)
+ return;
+ GLint unit = claimTextureUnit(variable);
+ if (unit == 0)
+ {
+ // TODO: 쳣󶨵
+ return;
+ }
+ gl.activeTexUnit(unit);
+ glUniform1i(location, unit);
+ gl.bindTexture(tex->getGLTexture());
+ gl.activeTexUnit(0);
+ }
+
+ void Shader::sendCanvas(const char* variable, const Canvas* canvas)
+ {
+ checkJSL();
+ GLint location = glGetUniformLocation(mPID, variable);
+ if (location == -1)
+ return;
+ GLint unit = claimTextureUnit(variable);
+ if (unit == 0)
+ {
+ // TODO: 쳣󶨵
+ return;
+ }
+ glUniform1i(location, unit);
+ glActiveTexture(GL_TEXTURE0 + unit);
+ gl.bindTexture(canvas->getGLTexture());
+
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ void Shader::sendVec2(const char* name, float x, float y)
+ {
+ checkJSL();
+ int loc = glGetUniformLocation(mPID, name);
+ glUniform2f(loc, x, y);
+ }
+
+ void Shader::sendVec3(const char* name, float x, float y, float z)
+ {
+ checkJSL();
+ int loc = glGetUniformLocation(mPID, name);
+ glUniform3f(loc, x, y, z);
+ }
+
+ void Shader::sendVec4(const char* name, float x, float y, float z, float w)
+ {
+ checkJSL();
+ int loc = glGetUniformLocation(mPID, name);
+ glUniform4f(loc, x, y, z, w);
+ }
+
+ void Shader::sendColor(const char* name, const Color* col)
+ {
+ checkJSL();
+ int loc = glGetUniformLocation(mPID, name);
+ glUniform4f(loc,
+ col->r / 255.f,
+ col->g / 255.f,
+ col->b / 255.f,
+ col->a / 255.f
+ );
+ }
+
+ void Shader::sendMatrix4(const char* name, const Math::Matrix* mat4)
+ {
+ int loc = glGetUniformLocation(mPID, name);
+ glUniformMatrix4fv(loc, 1, GL_FALSE, mat4->getElements());
+ }
+
+ void Shader::bindVertexPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers)
+ {
+ GLint loc = glGetAttribLocation(mPID, SHADER_VERTEX_COORDS);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(loc, n, type, GL_FALSE, stride, pointers);
+ }
+
+ void Shader::bindUVPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers)
+ {
+ GLint loc = glGetAttribLocation(mPID, SHADER_TEXTURE_COORDS);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(loc, n, type, GL_FALSE, stride, pointers);
+ }
+
+ } // namespace Shaders
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif // (jin_graphics) && (jin_graphics & jin_graphics_shader) \ No newline at end of file
diff --git a/src/libjin/Graphics/shaders/je_shader.h b/src/libjin/Graphics/shaders/je_shader.h
new file mode 100644
index 0000000..3a4f65b
--- /dev/null
+++ b/src/libjin/Graphics/shaders/je_shader.h
@@ -0,0 +1,200 @@
+#ifndef __JE_SHADER_H
+#define __JE_SHADER_H
+
+#include "../../core/je_configuration.h"
+#if defined(jin_graphics) && (jin_graphics & jin_graphics_shader)
+
+#include <string>
+#include <map>
+
+#include "GLee/GLee.h"
+
+#include "../je_color.h"
+#include "../je_texture.h"
+#include "../je_canvas.h"
+
+#include "je_base.shader.h"
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Shaders
+ {
+
+ ///
+ /// Built in shader program.
+ ///
+ /// Built in shader program written with custom shading language called JSL (jin shading language). A JSL
+ /// program is compiled into glsl, so most glsl built in functions and structs are available in JSL.
+ ///
+ class Shader
+ {
+ public:
+ ///
+ /// Create shader program from source code.
+ ///
+ /// @param source The shader source code.
+ ///
+ static Shader* createShader(const std::string& source);
+
+ ///
+ /// Get current shader.
+ ///
+ /// @return Current used shader program.
+ ///
+ static inline Shader* getCurrentShader() { return CurrentShader; }
+
+ ///
+ /// Unuse current shader.
+ ///
+ static void unuse();
+
+ ///
+ /// Destructor of shader.
+ ///
+ virtual ~Shader();
+
+ ///
+ /// Use specific shader.
+ ///
+ void use();
+
+ ///
+ /// Send float value to shader.
+ ///
+ /// @param name Name of the uniform variable to be assigned.
+ /// @param number Value of uniform variable to be sent.
+ ///
+ void sendFloat(const char* name, float number);
+
+ ///
+ /// Send texture to shader.
+ ///
+ /// @param name Name of the uniform variable to be assigned.
+ /// @param texture Texture to be sent.
+ ///
+ void sendTexture(const char* name, const Texture* texture);
+
+ ///
+ /// Send integer value to shader
+ ///
+ /// @param name Name of the uniform variable to be assigned.
+ /// @param value Value to be sent.
+ ///
+ void sendInt(const char* name, int value);
+
+ ///
+ /// Send 2D vector to shader.
+ ///
+ /// @param name Name of the uniform variable to be assigned.
+ /// @param x X value of the vector to be sent.
+ /// @param y Y value of the vector to be sent.
+ ///
+ void sendVec2(const char* name, float x, float y);
+
+ ///
+ /// Send 3D vector to shader.
+ ///
+ /// @param name Name of the uniform variable to be assigned.
+ /// @param x X value of the vector to be sent.
+ /// @param y Y value of the vector to be sent.
+ /// @param z Z value of the vector to be sent.
+ ///
+ void sendVec3(const char* name, float x, float y, float z);
+
+ ///
+ /// Send 4D vector to shader.
+ ///
+ /// @param name Name of the uniform variable to be assigned.
+ /// @param x X value of the vector to be sent.
+ /// @param y Y value of the vector to be sent.
+ /// @param z Z value of the vector to be sent.
+ /// @param w W value of the vector to be sent.
+ ///
+ void sendVec4(const char* name, float x, float y, float z, float w);
+
+ ///
+ /// Send canvas to shader.
+ ///
+ /// @param name Name of the uniform variable to be assigned.
+ /// @param canvas Canvas to be sent.
+ ///
+ void sendCanvas(const char* name, const Canvas* canvas);
+
+ ///
+ /// Send color to shader.
+ ///
+ /// @param name Name of the uniform variable to be assigned.
+ /// @param color Color to be sent.
+ ///
+ void sendColor(const char* name, const Color* color);
+
+ ///
+ /// Send 4 by 4 matrix to shader.
+ ///
+ /// @param name Name of the uniform variable to be assigned.
+ /// @param mat4 Matrix to be sent.
+ ///
+ void sendMatrix4(const char* name, const Math::Matrix* mat4);
+
+ ///
+ /// Set vertices value.
+ ///
+ /// @param n Number of vertices.
+ /// @param type Data type of each component in the array.
+ /// @param stride Byte offset between consecutive generic vertex attributes.
+ /// @param pointers Pointer to the first component of the first generic vertex attribute in the array.
+ ///
+ void bindVertexPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers);
+
+ ///
+ /// Set texture UV coordinates.
+ ///
+ /// @param n Number of vertices.
+ /// @param type Data type of each component in the array.
+ /// @param stride Byte offset between consecutive generic vertex attributes.
+ /// @param pointers Pointer to the first component of the first generic vertex attribute in the array.
+ ///
+ void bindUVPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers);
+
+ protected:
+ ///
+ /// Reference of current used shader.
+ ///
+ static Shader* CurrentShader;
+
+ ///
+ /// Get texture unit of the uniform texture. If not, assign one.
+ ///
+ /// @param name Name of the texture uniform variable.
+ /// @return Texture unit which texture variable be assigned.
+ ///
+ GLint claimTextureUnit(const std::string& name);
+
+ ///
+ /// Shader constructor.
+ ///
+ Shader(const std::string& program);
+
+ ///
+ /// Compile JSL program into GLSL source.
+ ///
+ /// @param program JSL source code.
+ /// @return Return true if compile successed, otherwise return false.
+ ///
+ bool compile(const std::string& program);
+
+ GLuint mPID;
+ GLint mCurrentTextureUnit;
+ std::map<std::string, GLint> mTextureUnits;
+
+ };
+
+ } // namespace Shaders
+ } // namespace Graphics
+} // namespace JinEngine
+
+#endif // (jin_graphics) && (jin_graphics & jin_graphics_shader)
+
+#endif // __JE_SHADER_H \ No newline at end of file
diff --git a/src/libjin/Utils/je_log.cpp b/src/libjin/Utils/je_log.cpp
index 2bcb25a..1704ce3 100644
--- a/src/libjin/Utils/je_log.cpp
+++ b/src/libjin/Utils/je_log.cpp
@@ -1,2 +1,81 @@
#define LOGHELPER_IMPLEMENT
-#include "je_log.h" \ No newline at end of file
+#include "je_log.h"
+
+#define hasbit(flag, bit) ((flag & bit) == bit)
+
+unsigned int Loghelper::dir = Loghelper::Direction::DIR_CERR;
+unsigned int Loghelper::levels = Loghelper::Level::LV_ALL;
+std::ofstream Loghelper::fs;
+
+void Loghelper::log(Level _level, const char* _fmt, ...)
+{
+ if (!hasbit(levels, _level))
+ return;
+#define FORMAT_MSG_BUFFER_SIZE (204800)
+ const char* levelStr = nullptr;
+ switch (_level)
+ {
+ case LV_ERROR:
+ levelStr = "[Jin internal error]: ";
+ break;
+ case LV_WARNING:
+ levelStr = "[Jin internal warning]: ";
+ break;
+ case LV_INFO:
+ levelStr = "[Jin internal info]: ";
+ break;
+ case LV_DEBUG:
+ levelStr = "[Jin internal debug]: ";
+ break;
+ default:
+ levelStr = "[Jin internal unknow]: ";
+ break;
+ }
+ char buffer[FORMAT_MSG_BUFFER_SIZE + 1] = { 0 };
+ strcpy(buffer, levelStr);
+ va_list args;
+ va_start(args, _fmt);
+ vsnprintf(buffer + strlen(buffer), FORMAT_MSG_BUFFER_SIZE, _fmt, args);
+ va_end(args);
+ if (hasbit(dir, DIR_CERR))
+ {
+ std::cerr << buffer << std::endl;
+ }
+ if (hasbit(dir, DIR_FILE))
+ {
+ fs << buffer << std::endl;
+ }
+#undef FORMAT_MSG_BUFFER_SIZE
+}
+
+// ض
+void Loghelper::redirect(unsigned int _dir, char* _path)
+{
+ dir = _dir;
+ if (hasbit(dir, DIR_FILE))
+ {
+ try
+ {
+ fs.open(_path, std::ios_base::app);
+ }
+ catch (std::ios_base::failure& e) {
+ dir = DIR_CERR;
+ log(Level::LV_WARNING, "ضlog· %s ʧ", _path);
+ }
+ }
+}
+
+// ɸѡȼ
+void Loghelper::restrict(unsigned int _levels)
+{
+ levels = _levels;
+}
+
+void Loghelper::close()
+{
+ if (!fs.fail())
+ fs.close();
+ fs.clear();
+}
+
+#undef hasbit
diff --git a/src/libjin/Utils/je_log.h b/src/libjin/Utils/je_log.h
index 928a009..aeb54d9 100644
--- a/src/libjin/Utils/je_log.h
+++ b/src/libjin/Utils/je_log.h
@@ -6,6 +6,8 @@
#include <fstream>
#include <stdarg.h>
+#include "../core/je_configuration.h"
+
class Loghelper
{
public:
@@ -21,7 +23,7 @@ public:
{
LV_NONE = 0, // none
LV_ERROR = 1 << 1, // error
- LV_WARN = 1 << 2, // warn
+ LV_WARNING = 1 << 2, // warn
LV_INFO = 1 << 3, // info
LV_DEBUG = 1 << 4, // debug
LV_ALL = 0xffffffff
@@ -43,89 +45,20 @@ private:
static std::ofstream fs; // ļ
};
-typedef Loghelper::Level Loglevel;
-
-#ifdef LOGHELPER_IMPLEMENT
-
-#define hasbit(flag, bit) ((flag & bit) == bit)
-
-unsigned int Loghelper::dir = Loghelper::Direction::DIR_CERR;
-unsigned int Loghelper::levels = Loghelper::Level::LV_ALL;
-std::ofstream Loghelper::fs;
-
-void Loghelper::log(Level _level, const char* _fmt, ...)
-{
- if (!hasbit(levels, _level))
- return;
-#define FORMAT_MSG_BUFFER_SIZE (204800)
- const char* levelStr = nullptr;
- switch (_level)
- {
- case LV_ERROR:
- levelStr = "[Jin Error]:";
- break;
- case LV_WARN:
- levelStr = "[Jin Warn]:";
- break;
- case LV_INFO:
- levelStr = "[Jin Info]:";
- break;
- case LV_DEBUG:
- levelStr = "[Jin Debug]:";
- break;
- default:
- levelStr = "[Jin Unknown]:";
- break;
- }
- char buffer[FORMAT_MSG_BUFFER_SIZE + 1] = { 0 };
- strcpy(buffer, levelStr);
- va_list args;
- va_start(args, _fmt);
- vsnprintf(buffer + strlen(buffer), FORMAT_MSG_BUFFER_SIZE, _fmt, args);
- va_end(args);
- if (hasbit(dir, DIR_CERR))
- {
- std::cerr << buffer << std::endl;
- }
- if (hasbit(dir, DIR_FILE))
- {
- fs << buffer << std::endl;
- }
-#undef FORMAT_MSG_BUFFER_SIZE
-}
-// ض
-void Loghelper::redirect(unsigned int _dir, char* _path)
-{
- dir = _dir;
- if (hasbit(dir, DIR_FILE))
- {
- try
- {
- fs.open(_path, std::ios_base::app);
- }
- catch (std::ios_base::failure& e) {
- dir = DIR_CERR;
- log(Level::LV_WARN, "ضlog· %s ʧ", _path);
- }
- }
-}
-
-// ɸѡȼ
-void Loghelper::restrict(unsigned int _levels)
-{
- levels = _levels;
-}
-
-void Loghelper::close()
-{
- if (!fs.fail())
- fs.close();
- fs.clear();
-}
-
-#undef hasbit
-
-#endif
+typedef Loghelper::Level Loglevel;
-#endif \ No newline at end of file
+#if defined(jin_debug)
+ #define jin_log_error(f, ...) Loghelper::log(Loghelper::LV_ERROR, f, __VA_ARGS__)
+ #define jin_log_info(f, ...) Loghelper::log(Loghelper::LV_INFO, f, __VA_ARGS__)
+ #define jin_log_warning(f, ...) Loghelper::log(Loghelper::LV_WARNING, f, __VA_ARGS__)
+ #define jin_log_debug(f, ...) Loghelper::log(Loghelper::LV_DEBUG, f, __VA_ARGS__)
+#else
+ #define jin_debug_log(level, fmt, ...)
+ #define jin_log_error(f, ...)
+ #define jin_log_info(f, ...)
+ #define jin_log_warning(f, ...)
+ #define jin_log_debug(f, ...)
+#endif
+
+#endif // __LOG_HELPER_H \ No newline at end of file
diff --git a/src/libjin/ai/je_ai.h b/src/libjin/ai/je_ai.h
new file mode 100644
index 0000000..74c4fd1
--- /dev/null
+++ b/src/libjin/ai/je_ai.h
@@ -0,0 +1,7 @@
+#ifndef __JE_AI_H
+#define __JE_AI_H
+
+#include "je_state_machine.h"
+#include "je_behavior_tree.h"
+
+#endif \ No newline at end of file
diff --git a/src/libjin/ai/je_behavior_tree.h b/src/libjin/ai/je_behavior_tree.h
index bfd0c6b..6c7c25f 100644
--- a/src/libjin/ai/je_behavior_tree.h
+++ b/src/libjin/ai/je_behavior_tree.h
@@ -19,8 +19,8 @@ namespace JinEngine
};
- }
-}
+ } // namespace AI
+} // namespace JinEngine
#endif // jin_ai
diff --git a/src/libjin/ai/je_state_machine.cpp b/src/libjin/ai/je_state_machine.cpp
index 3a8cd0d..2d82a0a 100644
--- a/src/libjin/ai/je_state_machine.cpp
+++ b/src/libjin/ai/je_state_machine.cpp
@@ -1,5 +1,7 @@
#include "je_state_machine.h"
+#include "../utils/je_log.h"
+
using namespace std;
namespace JinEngine
@@ -7,120 +9,471 @@ namespace JinEngine
namespace AI
{
- StateMachine::StateMachine()
+ StateMachine::StateMachine(Mode mode, void* userdata)
+ : mCurrentState("Empty")
+ , mUserData(userdata)
+ , mMode(mode)
{
-
+ addState("Empty");
}
StateMachine::~StateMachine()
{
+ }
+ void StateMachine::invokeCallback(const string& from, const string& to)
+ {
+ if (mExitCallback != nullptr)
+ mExitCallback(from, mUserData);
+ if (mTraslateCallback != nullptr)
+ mTraslateCallback(from, to, mUserData);
+ if (mEnterCallback != nullptr)
+ mEnterCallback(to, mUserData);
+ map<string, StateChangeCallback*>::iterator it = mOnExitState.find(from);
+ if (it != mOnExitState.end())
+ it->second(mUserData);
+ map<pair<string, string>, StateTranslateCallback*>::iterator transItr
+ = mOnStateTranslate.find(pair<string, string>(from, to));
+ if (transItr != mOnStateTranslate.end())
+ transItr->second(mUserData);
+ it = mOnEnterState.find(to);
+ if (it != mOnEnterState.end())
+ it->second(mUserData);
}
- void StateMachine::onUpdate()
+ void StateMachine::stepwiseProcess()
{
+ map<string, State>::iterator it = mStates.find(mCurrentState);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", mCurrentState);
+ return;
+ }
+ State& state = it->second;
+ for (int i = 0; i < state.transitions.size(); ++i)
+ {
+ if (processCondition(state.transitions[i].condition))
+ {
+ // Traslate
+ mCurrentState = state.transitions[i].state;
+ invokeCallback(state.name, mCurrentState);
+ return;
+ }
+ }
+ }
+ void StateMachine::iterativeProcess()
+ {
+ map<string, State>::iterator it = mStates.find(mCurrentState);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", mCurrentState);
+ return;
+ }
+ State& state = it->second;
+ for (int i = 0; i < state.transitions.size(); ++i)
+ {
+ if (processCondition(state.transitions[i].condition))
+ {
+ // Traslate
+ mCurrentState = state.transitions[i].state;
+ invokeCallback(state.name, mCurrentState);
+ return iterativeProcess();
+ }
+ }
}
- const string& StateMachine::getCurrentState()
+ void StateMachine::setMode(Mode mode)
{
+ mMode = mode;
+ }
+ //ģʽ״̬
+ void StateMachine::update()
+ {
+ switch (mMode)
+ {
+ case Mode::Iterative: iterativeProcess(); break;
+ case Mode::Stepwise: stepwiseProcess(); break;
+ }
}
- void StateMachine::addParameteri(const std::string& name)
+ bool StateMachine::processCondition(const Condition& condition)
{
+ map<string, Parameter>::iterator it = mParameters.find(condition.parameter);
+ if (it == mParameters.end())
+ {
+ jin_log_error("The parameter %s is not exist", condition.parameter);
+ return false;
+ }
+ Parameter& p = it->second;
+ switch (p.type)
+ {
+ case ParameterType::Int: return p.value._int == condition.value._int;
+ case ParameterType::Float: return p.value._float == condition.value._float;
+ case ParameterType::Bool: return p.value._bool == condition.value._bool;
+ case ParameterType::Trigger:
+ {
+ bool trigger = p.value._int == true;
+ if (trigger) p.value._int = false;
+ return trigger;
+ }
+ }
+ return false;
+ }
+ const string& StateMachine::getCurrentState()
+ {
+ return mCurrentState;
}
- void StateMachine::addParameterf(const std::string& name)
+ void StateMachine::addParameteri(const std::string& name)
{
+ if (mParameters.find(name) != mParameters.end())
+ {
+ jin_log_error("The parameter %s is already exist.", name);
+ return;
+ }
+ Parameter p;
+ p.type = ParameterType::Int;
+ p.value._int = 0;
+ mParameters.insert(pair<string, Parameter>(name, p));
+ }
+ void StateMachine::addParameterf(const std::string& name)
+ {
+ if (mParameters.find(name) != mParameters.end())
+ {
+ jin_log_error("The parameter %s is already exist.", name);
+ return;
+ }
+ Parameter p;
+ p.type = ParameterType::Float;
+ p.value._float = 0.0f;
+ mParameters.insert(pair<string, Parameter>(name, p));
}
void StateMachine::addParameterb(const std::string& name)
{
-
+ if (mParameters.find(name) != mParameters.end())
+ {
+ jin_log_error("The parameter %s is already exist.", name);
+ return;
+ }
+ Parameter p;
+ p.type = ParameterType::Bool;
+ p.value._bool = false;
+ mParameters.insert(pair<string, Parameter>(name, p));
}
void StateMachine::addParametert(const std::string& name)
{
-
+ if (mParameters.find(name) != mParameters.end())
+ {
+ jin_log_error("The parameter %s is already exist.", name);
+ return;
+ }
+ Parameter p;
+ p.type = ParameterType::Trigger;
+ p.value._trigger = false;
+ mParameters.insert(pair<string, Parameter>(name, p));
}
void StateMachine::addState(const std::string& name)
{
+ if (mStates.find(name) != mStates.end())
+ {
+ jin_log_error("The state %s is already exist.", name);
+ return;
+ }
+ State state;
+ state.name = name;
+ mStates.insert(pair<string, State>(name, state));
+ }
+ const char* StateMachine::parameterTypeString(ParameterType type)
+ {
+ switch (type)
+ {
+ case ParameterType::Int: return "int";
+ case ParameterType::Float: return "float";
+ case ParameterType::Bool: return "bool";
+ case ParameterType::Trigger: return "trigger";
+ }
}
void StateMachine::addTransitioni(const std::string& stateFrom, const std::string& stateTo, const std::string& name, int value)
{
-
+ map<string, State>::iterator it;
+ it = mStates.find(stateFrom);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", stateFrom);
+ return;
+ }
+ State& from = it->second;
+ it = mStates.find(stateTo);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", stateTo);
+ return;
+ }
+ State& to = it->second;
+ map<string, Parameter>::iterator itp;
+ itp = mParameters.find(name);
+ if (itp == mParameters.end())
+ {
+ jin_log_error("The parameter is not exist.", name);
+ return;
+ }
+ Parameter& parameter = itp->second;
+ if (parameter.type != ParameterType::Int)
+ {
+ jin_log_error("The type of parameter called %s is %s, but the transition gives a int value.", name, parameterTypeString(parameter.type));
+ return;
+ }
+ Transition trasition;
+ trasition.condition.parameter = name;
+ trasition.condition.value._int = value;
+ trasition.state = stateTo;
+ from.transitions.push_back(trasition);
}
void StateMachine::addTransitionf(const std::string& stateFrom, const std::string& stateTo, const std::string& name, float value)
{
-
+ map<string, State>::iterator it;
+ it = mStates.find(stateFrom);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", stateFrom);
+ return;
+ }
+ State& from = it->second;
+ it = mStates.find(stateTo);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", stateTo);
+ return;
+ }
+ State& to = it->second;
+ map<string, Parameter>::iterator itp;
+ itp = mParameters.find(name);
+ if (itp == mParameters.end())
+ {
+ jin_log_error("The parameter is not exist.", name);
+ return;
+ }
+ Parameter& parameter = itp->second;
+ if (parameter.type != ParameterType::Float)
+ {
+ jin_log_error("The type of parameter called %s is %s, but the transition gives a float value.", name, parameterTypeString(parameter.type));
+ return;
+ }
+ Transition trasition;
+ trasition.condition.parameter = name;
+ trasition.condition.value._float = value;
+ trasition.state = stateTo;
+ from.transitions.push_back(trasition);
}
void StateMachine::addTransitionb(const std::string& stateFrom, const std::string& stateTo, const std::string& name, bool value)
{
-
+ map<string, State>::iterator it;
+ it = mStates.find(stateFrom);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", stateFrom);
+ return;
+ }
+ State& from = it->second;
+ it = mStates.find(stateTo);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", stateTo);
+ return;
+ }
+ State& to = it->second;
+ map<string, Parameter>::iterator itp;
+ itp = mParameters.find(name);
+ if (itp == mParameters.end())
+ {
+ jin_log_error("The parameter is not exist.", name);
+ return;
+ }
+ Parameter& parameter = itp->second;
+ if (parameter.type != ParameterType::Bool)
+ {
+ jin_log_error("The type of parameter called %s is %s, but the transition gives a bool value.", name, parameterTypeString(parameter.type));
+ return;
+ }
+ Transition trasition;
+ trasition.condition.parameter = name;
+ trasition.condition.value._bool = value;
+ trasition.state = stateTo;
+ from.transitions.push_back(trasition);
}
void StateMachine::addTransitiont(const std::string& stateFrom, const std::string& stateTo, const std::string& name)
{
-
+ map<string, State>::iterator it;
+ it = mStates.find(stateFrom);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", stateFrom);
+ return;
+ }
+ State& from = it->second;
+ it = mStates.find(stateTo);
+ if (it == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", stateTo);
+ return;
+ }
+ State& to = it->second;
+ map<string, Parameter>::iterator itp;
+ itp = mParameters.find(name);
+ if (itp == mParameters.end())
+ {
+ jin_log_error("The parameter is not exist.", name);
+ return;
+ }
+ Parameter& parameter = itp->second;
+ if (parameter.type != ParameterType::Trigger)
+ {
+ jin_log_error("The type of parameter called %s is %s, but the transition gives a trigger value.", name, parameterTypeString(parameter.type));
+ return;
+ }
+ Transition trasition;
+ trasition.condition.parameter = name;
+ trasition.condition.value._trigger = true;
+ trasition.state = stateTo;
+ from.transitions.push_back(trasition);
}
void StateMachine::setParameteri(const std::string& name, int value)
{
-
+ map<string, Parameter>::iterator it = mParameters.find(name);
+ if (it == mParameters.end())
+ {
+ jin_log_error("The state %s is not exist.", name);
+ return;
+ }
+ Parameter& p = it->second;
+ if (p.type != ParameterType::Int)
+ {
+ jin_log_error("The type of parameter called %s is %s, but try to assign a int value to it", name, parameterTypeString(p.type));
+ return;
+ }
+ p.value._int = value;
}
void StateMachine::setParameterf(const std::string& name, float value)
{
-
+ map<string, Parameter>::iterator it = mParameters.find(name);
+ if (it == mParameters.end())
+ {
+ jin_log_error("The state %s is not exist.", name);
+ return;
+ }
+ Parameter& p = it->second;
+ if (p.type != ParameterType::Float)
+ {
+ jin_log_error("The type of parameter called %s is %s, but try to assign a float value to it", name, parameterTypeString(p.type));
+ return;
+ }
+ p.value._float = value;
}
void StateMachine::setParameterb(const std::string& name, bool value)
{
-
+ map<string, Parameter>::iterator it = mParameters.find(name);
+ if (it == mParameters.end())
+ {
+ jin_log_error("The state %s is not exist.", name);
+ return;
+ }
+ Parameter& p = it->second;
+ if (p.type != ParameterType::Bool)
+ {
+ jin_log_error("The type of parameter called %s is %s, but try to assign a bool value to it", name, parameterTypeString(p.type));
+ return;
+ }
+ p.value._bool = value;
}
void StateMachine::setParametert(const std::string& name)
{
-
+ map<string, Parameter>::iterator it = mParameters.find(name);
+ if (it == mParameters.end())
+ {
+ jin_log_error("The state %s is not exist.", name);
+ return;
+ }
+ Parameter& p = it->second;
+ if (p.type != ParameterType::Trigger)
+ {
+ jin_log_error("The type of parameter called %s is %s, but try to assign a trigger value to it", name, parameterTypeString(p.type));
+ return;
+ }
+ p.value._trigger = true;
}
- void StateMachine::trigger(const std::string& name)
+ void StateMachine::forceToState(const std::string& name)
{
-
+ if (mStates.find(name) == mStates.end())
+ {
+ jin_log_error("The state %s is not exist.", name);
+ return;
+ }
+ mCurrentState = name;
}
- void StateMachine::forceToState(const std::string& name)
+ void StateMachine::addEnterListener(const std::string& state, StateChangeCallback* callback)
{
-
+ if (mOnEnterState.find(state) != mOnEnterState.end())
+ {
+ jin_log_error("The enter listener of %s is already exist.", state);
+ return;
+ }
+ mOnEnterState.insert(pair<string, StateChangeCallback*>(state, callback));
}
- void StateMachine::reset()
+ void StateMachine::addExitListener(const std::string& state, StateChangeCallback* callback)
{
-
+ if (mOnExitState.find(state) != mOnExitState.end())
+ {
+ jin_log_error("The exit listener of %s is already exist.", state);
+ return;
+ }
+ mOnExitState.insert(pair<string, StateChangeCallback*>(state, callback));
}
- void StateMachine::addEnterListener(SingleStateCallback callback)
+ void StateMachine::addTranslateListener(const std::string& from, const std::string& to, StateChangeCallback* callback)
{
-
+ if (mOnStateTranslate.find(pair<string, string>(from, to)) != mOnStateTranslate.end())
+ {
+ jin_log_error("The traslate listener of %s to %s is already exist.", from, to);
+ return;
+ }
+ pair<string, string> key(from, to);
+ mOnStateTranslate.insert(pair<pair<string, string>, StateTranslateCallback*>(key, callback));
}
- void StateMachine::addExitListener(SingleStateCallback callback)
+ void StateMachine::setEnterListener(SingleStateCallback* callback)
{
-
+ mEnterCallback = callback;
}
- void StateMachine::addTranslateListener(DoubleStateCallback callback)
+ void StateMachine::setExitListener(SingleStateCallback* callback)
{
+ mExitCallback = callback;
+ }
+ void StateMachine::setTranslateListener(DoubleStateCallback* callback)
+ {
+ mTraslateCallback = callback;
}
+
} // namespace AI
} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin/ai/je_state_machine.h b/src/libjin/ai/je_state_machine.h
index 9d7994a..193ab65 100644
--- a/src/libjin/ai/je_state_machine.h
+++ b/src/libjin/ai/je_state_machine.h
@@ -14,7 +14,6 @@ namespace JinEngine
{
namespace AI
{
- // Grab from Unity engine.
///
/// A single layer statemachine.
@@ -26,17 +25,36 @@ namespace JinEngine
///
///
///
- typedef void(*SingleStateCallback)(const std::string& stateName);
+ enum Mode
+ {
+ Iterative, ///< Process until reach condition failed.(May cause endless loop)
+ Stepwise ///< Process one state each update.
+ };
///
///
///
- typedef void(*DoubleStateCallback)(const std::string& stateFrom, const std::string& stateTo);
+ typedef void(StateChangeCallback)(void* userdata);
+
+ ///
+ ///
+ ///
+ typedef void(StateTranslateCallback)(void* userdata);
+
+ ///
+ ///
+ ///
+ typedef void(SingleStateCallback)(const std::string& stateName, void* userdata);
+
+ ///
+ ///
+ ///
+ typedef void(DoubleStateCallback)(const std::string& stateFrom, const std::string& stateTo, void* userdata);
///
/// State machine constructor.
///
- StateMachine();
+ StateMachine(Mode mode = Mode::Stepwise, void* userdata = nullptr);
///
/// State machine destructor.
@@ -44,9 +62,14 @@ namespace JinEngine
~StateMachine();
///
- /// Update statemachine.
///
- void onUpdate();
+ ///
+ void setMode(Mode mode);
+
+ ///
+ /// Process current state..
+ ///
+ void update();
///
/// Get current state name.
@@ -54,7 +77,7 @@ namespace JinEngine
const std::string& getCurrentState();
///
- ///
+ /// Add a integer parameter.
///
void addParameteri(const std::string& name);
@@ -79,12 +102,12 @@ namespace JinEngine
void addState(const std::string& name);
///
- ///
+ ///
///
void addTransitioni(const std::string& stateFrom, const std::string& stateTo, const std::string& name, int value);
///
- ///
+ ///
///
void addTransitionf(const std::string& stateFrom, const std::string& stateTo, const std::string& name, float value);
@@ -119,51 +142,56 @@ namespace JinEngine
void setParametert(const std::string& name);
///
- /// Equivalent to setParameter(triggername);
+ /// Force change to state.
///
- void trigger(const std::string& name);
+ void forceToState(const std::string& name);
///
- /// Force change to state.
+ ///
///
- void forceToState(const std::string& name);
+ void addEnterListener(const std::string& state, StateChangeCallback* callback);
///
- /// Reset state machine.
///
- void reset();
+ ///
+ void addExitListener(const std::string& state, StateChangeCallback* callback);
///
- ///
///
- void addEnterListener(SingleStateCallback callback);
+ ///
+ void addTranslateListener(const std::string& from, const std::string& to, StateChangeCallback* callback);
///
///
///
- void addExitListener(SingleStateCallback callback);
+ void setEnterListener(SingleStateCallback* callback);
///
///
///
- void addTranslateListener(DoubleStateCallback callback);
+ void setExitListener(SingleStateCallback* callback);
+
+ ///
+ ///
+ ///
+ void setTranslateListener(DoubleStateCallback* callback);
private:
enum ParameterType
{
Int, ///< A integer value.
- FLoat, ///< A float value.
+ Float, ///< A float value.
Bool, ///< A bool value.
Trigger ///< A trigger will be reset to false after activated.
};
union ParameterValue
{
- int _int;
- float _float;
- bool _bool;
- byte _trigger;
+ int _int; ///< 0 by default.
+ float _float; ///< 0 by default.
+ bool _bool; ///< false by default.
+ bool _trigger; ///< false by default.
};
struct Parameter
@@ -187,7 +215,7 @@ namespace JinEngine
struct Transition
{
Condition condition; ///< Condition to active transition.
- std::string state; ///<
+ std::string state; ///< State to translate to.
};
///
@@ -199,12 +227,31 @@ namespace JinEngine
std::vector<Transition> transitions; ///< All transitions this state have.
};
+ const char* parameterTypeString(ParameterType type);
+
///
/// Check if condition is full filled.
///
/// @param condition Condition to check.
///
- bool checkCondition(const Condition& condition);
+ bool processCondition(const Condition& condition);
+
+ typedef void(Processor)(void*);
+
+ ///
+ ///
+ ///
+ void stepwiseProcess();
+
+ ///
+ ///
+ ///
+ void iterativeProcess();
+
+ ///
+ ///
+ ///
+ void invokeCallback(const std::string& from, const std::string& to);
///
/// All state this state machine keeps.
@@ -214,28 +261,47 @@ namespace JinEngine
///
///
///
- std::map<std::string, SingleStateCallback> mOnEnterState;
+ std::map<std::string, StateChangeCallback*> mOnEnterState;
///
///
///
- std::map<std::string, SingleStateCallback> mOnExitState;
+ std::map<std::string, StateChangeCallback*> mOnExitState;
///
/// From first to second.
///
- std::map<std::pair<std::string, std::string>, DoubleStateCallback> mOnStateTranslate;
+ std::map<std::pair<std::string, std::string>, StateTranslateCallback*> mOnStateTranslate;
+
+ ///
+ ///
+ ///
+ SingleStateCallback* mEnterCallback;
+
+ ///
+ ///
+ ///
+ SingleStateCallback* mExitCallback;
+
+ ///
+ ///
+ ///
+ DoubleStateCallback* mTraslateCallback;
///
/// Current state.
///
- const State* mCurrentState;
+ std::string mCurrentState;
///
/// All parameters.
///
std::map<std::string, Parameter> mParameters;
-
+
+ Mode mMode;
+
+ void* const mUserData;
+
};
} // namespace Graphics
diff --git a/src/libjin/jin.h b/src/libjin/jin.h
index a43730d..a8c00b5 100644
--- a/src/libjin/jin.h
+++ b/src/libjin/jin.h
@@ -16,6 +16,6 @@
#include "time/je_timer.h"
#include "multithread/je_thread.h"
#include "common/je_common.h"
-#include "ai/je_state_machine.h"
+#include "ai/je_ai.h"
#endif // __JE_H \ No newline at end of file
diff --git a/src/lua/modules/ai/je_lua_behavior_tree.cpp b/src/lua/modules/ai/je_lua_behavior_tree.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/lua/modules/ai/je_lua_behavior_tree.cpp
diff --git a/src/lua/modules/ai/je_lua_statemachine.cpp b/src/lua/modules/ai/je_lua_statemachine.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/lua/modules/ai/je_lua_statemachine.cpp
diff --git a/src/lua/modules/audio/je_lua_audio.cpp b/src/lua/modules/audio/je_lua_audio.cpp
index 8ffa794..0f2f713 100644
--- a/src/lua/modules/audio/je_lua_audio.cpp
+++ b/src/lua/modules/audio/je_lua_audio.cpp
@@ -4,6 +4,7 @@
#include "libjin/jin.h"
using namespace JinEngine::Audio;
+using namespace JinEngine::Audio::SDL;
using namespace JinEngine::Filesystem;
namespace JinEngine
diff --git a/src/lua/modules/graphics/je_lua_graphics.cpp b/src/lua/modules/graphics/je_lua_graphics.cpp
index d59a67d..7c417a5 100644
--- a/src/lua/modules/graphics/je_lua_graphics.cpp
+++ b/src/lua/modules/graphics/je_lua_graphics.cpp
@@ -9,6 +9,8 @@
using namespace std;
using namespace JinEngine;
using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
+using namespace JinEngine::Graphics::Shaders;
using namespace JinEngine::Filesystem;
namespace JinEngine
diff --git a/src/lua/modules/graphics/je_lua_page.cpp b/src/lua/modules/graphics/je_lua_page.cpp
index 7f3d1c8..36754a0 100644
--- a/src/lua/modules/graphics/je_lua_page.cpp
+++ b/src/lua/modules/graphics/je_lua_page.cpp
@@ -6,6 +6,8 @@
#include <iostream>
using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
+using namespace JinEngine::Graphics::Shaders;
namespace JinEngine
{
diff --git a/src/lua/modules/graphics/je_lua_shader.cpp b/src/lua/modules/graphics/je_lua_shader.cpp
index c15e37a..9131815 100644
--- a/src/lua/modules/graphics/je_lua_shader.cpp
+++ b/src/lua/modules/graphics/je_lua_shader.cpp
@@ -4,6 +4,7 @@
#include "libjin/jin.h"
using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Shaders;
namespace JinEngine
{
diff --git a/src/lua/modules/graphics/je_lua_texture_font.cpp b/src/lua/modules/graphics/je_lua_texture_font.cpp
index cee1c67..ba0a504 100644
--- a/src/lua/modules/graphics/je_lua_texture_font.cpp
+++ b/src/lua/modules/graphics/je_lua_texture_font.cpp
@@ -4,6 +4,7 @@
#include "libjin/jin.h"
using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
namespace JinEngine
{
diff --git a/src/lua/modules/graphics/je_lua_ttf.cpp b/src/lua/modules/graphics/je_lua_ttf.cpp
index 2818b06..49f13c0 100644
--- a/src/lua/modules/graphics/je_lua_ttf.cpp
+++ b/src/lua/modules/graphics/je_lua_ttf.cpp
@@ -4,6 +4,7 @@
#include "libjin/jin.h"
using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
namespace JinEngine
{
diff --git a/src/lua/modules/graphics/je_lua_ttf_data.cpp b/src/lua/modules/graphics/je_lua_ttf_data.cpp
index 269789c..4212778 100644
--- a/src/lua/modules/graphics/je_lua_ttf_data.cpp
+++ b/src/lua/modules/graphics/je_lua_ttf_data.cpp
@@ -4,6 +4,7 @@
#include "libjin/jin.h"
using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
namespace JinEngine
{