aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2018-07-27 00:01:34 +0800
committerchai <chaifix@163.com>2018-07-27 00:01:34 +0800
commitb855ebb91ad8d97617ec1aa418b4add84670a07d (patch)
treeb11847a1879a2582c9cfd380074ad4c70f17a1a8 /src
parent1a882936e91826e4d69584745e16a79650272015 (diff)
*change name
Diffstat (limited to 'src')
-rw-r--r--src/libjin/Audio/Audio.cpp15
-rw-r--r--src/libjin/Audio/Audio.h46
-rw-r--r--src/libjin/Audio/OpenAL/Audio.cpp0
-rw-r--r--src/libjin/Audio/OpenAL/Audio.h0
-rw-r--r--src/libjin/Audio/OpenAL/Source.cpp0
-rw-r--r--src/libjin/Audio/OpenAL/Source.h0
-rw-r--r--src/libjin/Audio/SDL/Audio.cpp121
-rw-r--r--src/libjin/Audio/SDL/Audio.h68
-rw-r--r--src/libjin/Audio/SDL/Source.cpp399
-rw-r--r--src/libjin/Audio/SDL/Source.h116
-rw-r--r--src/libjin/Audio/Source.cpp28
-rw-r--r--src/libjin/Audio/Source.h51
-rw-r--r--src/libjin/Common/Data.h15
-rw-r--r--src/libjin/Common/Singleton.h38
-rw-r--r--src/libjin/Common/Subsystem.h42
-rw-r--r--src/libjin/Core/Core.h6
-rw-r--r--src/libjin/Core/Game.cpp12
-rw-r--r--src/libjin/Core/Game.h59
-rw-r--r--src/libjin/Core/Thread.cpp0
-rw-r--r--src/libjin/Core/Thread.h1
-rw-r--r--src/libjin/Core/Timer.cpp0
-rw-r--r--src/libjin/Core/Timer.h1
-rw-r--r--src/libjin/Debug/Debug.h6
-rw-r--r--src/libjin/Debug/Log.h14
-rw-r--r--src/libjin/Input/Event.cpp7
-rw-r--r--src/libjin/Input/Event.h13
-rw-r--r--src/libjin/Input/Input.h8
-rw-r--r--src/libjin/Input/Joypad.cpp0
-rw-r--r--src/libjin/Input/Joypad.h14
-rw-r--r--src/libjin/Input/Keyboard.cpp0
-rw-r--r--src/libjin/Input/Keyboard.h13
-rw-r--r--src/libjin/Input/Mouse.cpp0
-rw-r--r--src/libjin/Input/Mouse.h15
-rw-r--r--src/libjin/Math/Math.h16
-rw-r--r--src/libjin/Math/Matrix.cpp177
-rw-r--r--src/libjin/Math/Matrix.h153
-rw-r--r--src/libjin/Math/Quad.h17
-rw-r--r--src/libjin/Math/Vector.cpp2
-rw-r--r--src/libjin/Math/Vector.h14
-rw-r--r--src/libjin/Math/constant.h10
-rw-r--r--src/libjin/Net/Net.cpp0
-rw-r--r--src/libjin/Net/Net.h6
-rw-r--r--src/libjin/Physics/Physics.h12
-rw-r--r--src/libjin/Physics/Rigid.h0
-rw-r--r--src/libjin/Render/Canvas.cpp134
-rw-r--r--src/libjin/Render/Canvas.h40
-rw-r--r--src/libjin/Render/Color.h31
-rw-r--r--src/libjin/Render/Drawable.cpp77
-rw-r--r--src/libjin/Render/Drawable.h56
-rw-r--r--src/libjin/Render/Font.cpp193
-rw-r--r--src/libjin/Render/Font.h61
-rw-r--r--src/libjin/Render/Graphics.cpp121
-rw-r--r--src/libjin/Render/Graphics.h40
-rw-r--r--src/libjin/Render/JSL.cpp158
-rw-r--r--src/libjin/Render/JSL.h74
-rw-r--r--src/libjin/Render/Render.h15
-rw-r--r--src/libjin/Render/Texture.cpp99
-rw-r--r--src/libjin/Render/Texture.h38
-rw-r--r--src/libjin/Render/Window.cpp90
-rw-r--r--src/libjin/Render/Window.h59
-rw-r--r--src/libjin/Thread/Thread.cpp0
-rw-r--r--src/libjin/Thread/Thread.h1
-rw-r--r--src/libjin/Tilemap/Tilemap.h14
-rw-r--r--src/libjin/Tools/EventMsgCenter/EventMsgCenter.h0
-rw-r--r--src/libjin/UI/UI.h1
-rw-r--r--src/libjin/Utils/Log.cpp2
-rw-r--r--src/libjin/Utils/Log.h134
-rw-r--r--src/libjin/Utils/endian.h23
-rw-r--r--src/libjin/Utils/macros.h16
-rw-r--r--src/libjin/Utils/unittest.cpp108
-rw-r--r--src/libjin/Utils/utils.h9
71 files changed, 3109 insertions, 0 deletions
diff --git a/src/libjin/Audio/Audio.cpp b/src/libjin/Audio/Audio.cpp
new file mode 100644
index 0000000..363bf4d
--- /dev/null
+++ b/src/libjin/Audio/Audio.cpp
@@ -0,0 +1,15 @@
+#include "../modules.h"
+#if JIN_MODULES_AUDIO
+
+#include <SDL2/SDL.h>
+#include "audio.h"
+
+namespace jin
+{
+namespace audio
+{
+
+}
+}
+
+#endif // JIN_MODULES_AUDIO \ No newline at end of file
diff --git a/src/libjin/Audio/Audio.h b/src/libjin/Audio/Audio.h
new file mode 100644
index 0000000..faec4db
--- /dev/null
+++ b/src/libjin/Audio/Audio.h
@@ -0,0 +1,46 @@
+#ifndef __JIN_AUDIO_H
+#define __JIN_AUDIO_H
+#include "../modules.h"
+#if JIN_MODULES_AUDIO
+
+#include <SDL2/SDL.h>
+
+#include "../utils/macros.h"
+#include "../common/subsystem.h"
+
+namespace jin
+{
+namespace audio
+{
+ class Source;
+
+ template<class SubAudioSystem>
+ class AudioSystem : public Subsystem<SubAudioSystem>
+ {
+
+ public:
+
+ virtual void play() = 0;
+ virtual void stop() = 0;
+ virtual bool pause() = 0;
+ virtual bool pause(Source* source) = 0;
+ virtual bool resume() = 0;
+ virtual bool resume(Source* source) = 0;
+ virtual void rewind() = 0;
+ virtual void setVolume(float volume) = 0;
+ virtual float getVolume() = 0;
+
+ protected:
+
+ AudioSystem() {};
+ virtual ~AudioSystem() {};
+
+ SINGLETON(AudioSystem);
+
+ };
+
+}
+}
+
+#endif // JIN_MODULES_AUDIO
+#endif \ No newline at end of file
diff --git a/src/libjin/Audio/OpenAL/Audio.cpp b/src/libjin/Audio/OpenAL/Audio.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Audio/OpenAL/Audio.cpp
diff --git a/src/libjin/Audio/OpenAL/Audio.h b/src/libjin/Audio/OpenAL/Audio.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Audio/OpenAL/Audio.h
diff --git a/src/libjin/Audio/OpenAL/Source.cpp b/src/libjin/Audio/OpenAL/Source.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Audio/OpenAL/Source.cpp
diff --git a/src/libjin/Audio/OpenAL/Source.h b/src/libjin/Audio/OpenAL/Source.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Audio/OpenAL/Source.h
diff --git a/src/libjin/Audio/SDL/Audio.cpp b/src/libjin/Audio/SDL/Audio.cpp
new file mode 100644
index 0000000..47d8cf8
--- /dev/null
+++ b/src/libjin/Audio/SDL/Audio.cpp
@@ -0,0 +1,121 @@
+#include "../../modules.h"
+#if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO
+
+#include <iostream>
+#include "audio.h"
+#include "source.h"
+#include "../../math/math.h"
+#include "../../utils/log.h"
+
+namespace jin
+{
+namespace audio
+{
+
+ /* עcallbackƵ̵߳ */
+ static void defaultCallback(void *userdata, Uint8 *stream, int size)
+ {
+ static SDLAudio* audio = static_cast<SDLAudio*>(userdata);
+ audio->lock();
+ audio->processCommands();
+ audio->processSources(stream, size);
+ audio->unlock();
+ }
+
+ onlyonce bool SDLAudio::initSystem(const SettingBase* s)
+ {
+ Loghelper::log(Loglevel::LV_INFO, "Init 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(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;
+ }
+
+ onlyonce void SDLAudio::quitSystem()
+ {
+ SDL_CloseAudio();
+ }
+
+ void SDLAudio::lock()
+ {
+ SDL_LockAudioDevice(audioDevice);
+ }
+
+ void SDLAudio::unlock()
+ {
+ SDL_UnlockAudioDevice(audioDevice);
+ }
+
+ void SDLAudio::processCommands()
+ {
+ SDLSourceManager::get()->processCommands();
+ }
+
+ void SDLAudio::processSources(void* buffer, size_t len)
+ {
+ SDLSourceManager::get()->processSources(buffer, len);
+ }
+
+ void SDLAudio::play() {}
+
+ void SDLAudio::stop() {}
+
+ bool SDLAudio::pause()
+ {
+ return false;
+ }
+
+ bool SDLAudio::pause(Source* source)
+ {
+ return false;
+ }
+
+ bool SDLAudio::resume()
+ {
+ return false;
+ }
+
+ bool SDLAudio::resume(Source* source)
+ {
+ return false;
+ }
+
+ void SDLAudio::rewind()
+ {
+
+ }
+
+ void SDLAudio::setVolume(float volume)
+ {
+
+ }
+
+ float SDLAudio::getVolume()
+ {
+ return 0.f;
+ }
+
+}
+}
+
+#endif // JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO \ No newline at end of file
diff --git a/src/libjin/Audio/SDL/Audio.h b/src/libjin/Audio/SDL/Audio.h
new file mode 100644
index 0000000..6da6605
--- /dev/null
+++ b/src/libjin/Audio/SDL/Audio.h
@@ -0,0 +1,68 @@
+#ifndef __JIN_AUDIO_SDL_H
+#define __JIN_AUDIO_SDL_H
+#include "../../modules.h"
+#if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO
+
+#include <vector>
+#include "../audio.h"
+
+namespace jin
+{
+namespace audio
+{
+
+#define SDLAUDIO_BITDEPTH 16
+#define SDLAUDIO_BYTEDEPTH (SDLAUDIO_BITDEPTH >> 3)
+#define SDLAUDIO_CHANNELS 2
+
+ class SDLAudio : public AudioSystem<SDLAudio>
+ {
+
+ public:
+
+ struct Setting : SettingBase
+ {
+ public:
+ int samplerate; // Ƶ
+ int samples; // sample<=samplerate
+ };
+
+ /* IAudio interface */
+ void play() override;
+ void stop() override;
+ bool pause() override;
+ bool pause(Source* source) override;
+ bool resume() override;
+ bool resume(Source* source) override;
+ void rewind() override;
+ void setVolume(float volume) override;
+ float getVolume() override;
+
+ /* process functions*/
+ void processCommands();
+ void processSources(void* buffer, size_t len);
+
+ void lock();
+ void unlock();
+
+ private:
+
+ SDLAudio() {};
+ ~SDLAudio() {};
+
+ SINGLETON(SDLAudio);
+
+ onlyonce bool initSystem(const SettingBase* setting) override;
+ onlyonce void quitSystem() override;
+
+ unsigned int audioDevice;
+
+ };
+
+ typedef SDLAudio::Setting SDLAudioSetting;
+
+}
+}
+
+#endif // JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO
+#endif \ No newline at end of file
diff --git a/src/libjin/Audio/SDL/Source.cpp b/src/libjin/Audio/SDL/Source.cpp
new file mode 100644
index 0000000..0eedbba
--- /dev/null
+++ b/src/libjin/Audio/SDL/Source.cpp
@@ -0,0 +1,399 @@
+#include "../../modules.h"
+#if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO
+
+#include <exception>
+#include <fstream>
+
+#include "../../math/math.h"
+#include "../../utils/macros.h"
+#include "source.h"
+#include "3rdparty/wav/wav.h"
+#define STB_VORBIS_HEADER_ONLY
+#include "3rdparty/stb/stb_vorbis.c"
+
+#include "audio.h"
+
+namespace jin
+{
+namespace audio
+{
+
+#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
+
+ shared std::queue<Command*> Manager::commands;
+ shared std::stack<Command*> Manager::commandsPool;
+ shared std::vector<SDLSource*> Manager::sources;
+ shared 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));
+ }
+
+ 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.bitdepth / 8;
+ raw.end = (char*)raw.data + raw.length;
+ raw.samplerate = wav.samplerate;
+ raw.bitdepth = wav.bitdepth;
+ raw.samples = raw.length / (wav.bitdepth / 8.f) / wav.channels;
+ raw.channels = clamp(wav.channels, CHANNEL::MONO, CHANNEL::STEREO);
+ }
+ 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;
+ raw.length = samples * channels * sizeof(short);
+ raw.bitdepth = bitdepth;
+ raw.end = (char*)data + raw.length;
+ }
+
+#define ActionNone(T)\
+do{\
+Command* cmd = Manager::get()->getCommand();\
+cmd->action = Action::T; \
+cmd->source = this; \
+Manager::get()->pushCommand(cmd); \
+} while (0)
+
+#define ActionArg(T, ARGT, ARG)\
+do{\
+Command* cmd = Manager::get()->getCommand();\
+cmd->action = Action::T; \
+cmd->parameter.ARGT = ARG; \
+cmd->source = this; \
+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, volume);
+ }
+
+ bool SDLSource::setLoop(bool loop)
+ {
+ ActionBool(SetLoop, loop);
+ return false;
+ }
+
+ 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:
+ //float 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
+ unsigned int samples = size / SDLAUDIO_BYTEDEPTH;
+ short* sample;
+ short origin;
+
+ const char bitdepth = raw.bitdepth;
+ const char channles = raw.channels;
+
+ int pos = status.pos;
+ int pitch = status.pitch;
+ int state = status.state;
+ bool loop = status.loop;
+ int volume = status.volume;
+ short* clip16 = nullptr;
+ char* clip8 = nullptr;
+ int clip = 0;
+
+ if (bitdepth == 8)
+ clip8 = (char*)raw.data;
+ else if (bitdepth == 16)
+ clip16 = (short*)raw.data;
+
+ for (int i = 0; i < samples; i+=2 /*˫*/)
+ {
+ /* Ƶļsampleᱻ */
+ sample = buffer + i * SDLAUDIO_BYTEDEPTH;
+ origin = *sample;
+ if (bitdepth == 8)
+ {
+ clip = *clip8;
+ }
+ else if (bitdepth == 16)
+ clip = *clip16;
+
+ }
+ }
+
+ Manager* Manager::get()
+ {
+ return (manager == nullptr ? manager = new Manager() : manager);
+ }
+
+ shared 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 */
+ shared 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;
+ }
+ }
+
+ shared 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;
+ }
+ }
+
+ shared void Manager::pushSource(SDLSource* source)
+ {
+ if(source != nullptr)
+ sources.push_back(source);
+ }
+
+ shared void Manager::pushCommand(SDLSourceCommand* cmd)
+ {
+ commands.push(cmd);
+ }
+
+ shared Command* Manager::getCommand()
+ {
+ if (!commandsPool.empty())
+ {
+ Command* cmd = commandsPool.top();
+ commandsPool.pop();
+ return cmd;
+ }
+ return new Command();
+ }
+
+}
+}
+
+#endif // JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO \ No newline at end of file
diff --git a/src/libjin/Audio/SDL/Source.h b/src/libjin/Audio/SDL/Source.h
new file mode 100644
index 0000000..38f7ec4
--- /dev/null
+++ b/src/libjin/Audio/SDL/Source.h
@@ -0,0 +1,116 @@
+#ifndef __JIN_SOURCE_SDL_H
+#define __JIN_SOURCE_SDL_H
+#include "../../modules.h"
+#if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO
+
+#include <vector>
+#include <queue>
+#include <stack>
+#include <exception>
+
+#include "../source.h"
+
+namespace jin
+{
+namespace audio
+{
+
+ typedef struct SDLSourceCommand;
+ class SDLSourceManager;
+
+ class SDLSource : public Source
+ {
+
+ public:
+
+ ~SDLSource();
+
+ static SDLSource* createSource(const char* file);
+ static SDLSource* createSource(void* mem, size_t size);
+
+ /* ISource interface */
+ void play() override;
+ void stop() override;
+ void pause() override;
+ void resume() override;
+ void rewind() override;
+ bool isStopped() const override;
+ bool isPaused() const override;
+ void setPitch(float pitch) override;
+ // Ͻ
+ void setVolume(float volume) override;
+ bool setLoop(bool loop) override;
+ void setRate(float rate) override;
+
+ inline void handle(SDLSourceManager* manager, SDLSourceCommand* cmd);
+ inline void process(void* buffer, size_t size);
+
+ private:
+
+ SDLSource();
+
+ void decode_wav(void* mem, int size);
+ void decode_ogg(void* mem, int size);
+
+ inline bool is(int state) const { return (status.state & state) == state; }
+
+ 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
+ int volume; //
+ } status;
+
+ };
+
+ class SDLSourceManager
+ {
+
+ public:
+
+ static SDLSourceManager* get();
+
+ /* Process function */
+ static void processCommands();
+ static void processSources(void* buffer, size_t size);
+
+ static void removeSource(SDLSource* source);
+ static void pushSource(SDLSource* source);
+ static SDLSourceCommand* getCommand();
+ static void pushCommand(SDLSourceCommand* cmd);
+
+ static SDLSourceManager* manager;
+
+ static std::queue<SDLSourceCommand*> commands;
+ static std::stack<SDLSourceCommand*> commandsPool;
+ static std::vector<SDLSource*> sources; // processing sources
+
+ };
+
+ class SourceException : public std::exception
+ {
+ const char * what() const throw ()
+ {
+ return "Load Source Exception";
+ }
+ };
+
+}
+}
+
+#endif // JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO
+#endif \ No newline at end of file
diff --git a/src/libjin/Audio/Source.cpp b/src/libjin/Audio/Source.cpp
new file mode 100644
index 0000000..ceb882d
--- /dev/null
+++ b/src/libjin/Audio/Source.cpp
@@ -0,0 +1,28 @@
+#include "../modules.h"
+#if JIN_MODULES_AUDIO
+
+#include <cstring>
+#include "source.h"
+
+namespace jin
+{
+namespace audio
+{
+
+ static int check_header(const void *data, int size, char *str, int offset) {
+ int len = strlen(str);
+ return (size >= offset + len) && !memcmp((char*)data + offset, str, len);
+ }
+
+ SourceType Source::getType(const void* mem, int size)
+ {
+ if(check_header(mem, size, "WAVE", 8))
+ return SourceType::WAV;
+ if(check_header(mem, size, "OggS", 0))
+ return SourceType::OGG;
+ return SourceType::INVALID;
+ }
+
+}
+}
+#endif // JIN_MODULES_AUDIO \ No newline at end of file
diff --git a/src/libjin/Audio/Source.h b/src/libjin/Audio/Source.h
new file mode 100644
index 0000000..5b9c12b
--- /dev/null
+++ b/src/libjin/Audio/Source.h
@@ -0,0 +1,51 @@
+#ifndef __JIN_AUDIO_SOURCE_H
+#define __JIN_AUDIO_SOURCE_H
+#include "../modules.h"
+#if JIN_MODULES_AUDIO
+
+#include <SDL2/SDL.h>
+
+namespace jin
+{
+namespace audio
+{
+
+ enum SourceType
+ {
+ INVALID = 0,
+ WAV,
+ OGG,
+ };
+
+ class Source
+ {
+
+ public:
+
+ Source() {};
+ virtual ~Source() {};
+
+ /* interface */
+ virtual void play() = 0;
+ virtual void stop() = 0;
+ virtual void pause() = 0;
+ virtual void resume() = 0;
+ virtual void rewind() = 0;
+ virtual bool isStopped() const = 0;
+ virtual bool isPaused() const = 0;
+ virtual void setPitch(float pitch) = 0;
+ virtual void setVolume(float volume) = 0;
+ virtual bool setLoop(bool loop) = 0;
+ virtual void setRate(float rate) = 0;
+
+ protected:
+
+ static SourceType getType(const void* mem, int size);
+
+ };
+
+}
+}
+
+#endif // JIN_MODULES_AUDIO
+#endif \ No newline at end of file
diff --git a/src/libjin/Common/Data.h b/src/libjin/Common/Data.h
new file mode 100644
index 0000000..6f1c504
--- /dev/null
+++ b/src/libjin/Common/Data.h
@@ -0,0 +1,15 @@
+#ifndef __JIN_COMMON_DATA_H
+#define __JIN_COMMON_DATA_H
+
+namespace jin
+{
+
+ struct Buffer
+ {
+ unsigned int len;
+ char data[0];
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Common/Singleton.h b/src/libjin/Common/Singleton.h
new file mode 100644
index 0000000..a6c7d6d
--- /dev/null
+++ b/src/libjin/Common/Singleton.h
@@ -0,0 +1,38 @@
+#ifndef __JIN_SINGLETON_H
+#define __JIN_SINGLETON_H
+
+namespace jin
+{
+ template<class T>
+ class Singleton
+ {
+ public:
+ static T* get()
+ {
+ if (_instance == nullptr)
+ _instance = new T;
+ return _instance;
+ }
+ static void destroy()
+ {
+ delete _instance;
+ _instance = nullptr;
+ }
+ protected:
+ Singleton() {};
+ virtual ~Singleton() {};
+ private:
+ Singleton(const Singleton&);
+ Singleton& operator = (const Singleton&);
+
+ static T* _instance;
+ };
+
+ template<class T> T* Singleton<T>::_instance = nullptr;
+
+#define SINGLETON(T) \
+ friend Singleton<T>
+
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Common/Subsystem.h b/src/libjin/Common/Subsystem.h
new file mode 100644
index 0000000..35563da
--- /dev/null
+++ b/src/libjin/Common/Subsystem.h
@@ -0,0 +1,42 @@
+#ifndef __JIN_COMMON_SUBSYSTEM_H
+#define __JIN_COMMON_SUBSYSTEM_H
+
+#include "singleton.h"
+#include "../utils/macros.h"
+
+namespace jin
+{
+
+ template<class System>
+ class Subsystem : public Singleton<System>
+ {
+ public:
+ struct Setting {};
+ typedef Setting SettingBase;
+
+ void init(const SettingBase* setting)
+ {
+ CALLONCE(initSystem(setting));
+ }
+
+ void quit()
+ {
+ CALLONCE(quitSystem());
+ destroy();
+ }
+
+ protected:
+
+ Subsystem() {};
+ virtual ~Subsystem() {};
+
+ SINGLETON(System);
+
+ virtual onlyonce bool initSystem(const Setting* setting) = 0;
+ virtual onlyonce void quitSystem() = 0;
+
+ };
+
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Core/Core.h b/src/libjin/Core/Core.h
new file mode 100644
index 0000000..dd902b4
--- /dev/null
+++ b/src/libjin/Core/Core.h
@@ -0,0 +1,6 @@
+#ifndef __JIN_CORE_H
+#define __JIN_CORE_H
+
+#include "game.h"
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Core/Game.cpp b/src/libjin/Core/Game.cpp
new file mode 100644
index 0000000..5c2e69b
--- /dev/null
+++ b/src/libjin/Core/Game.cpp
@@ -0,0 +1,12 @@
+#include "game.h"
+
+namespace jin
+{
+namespace core
+{
+
+ Game::Game() :run(true) {};
+
+}
+}
+
diff --git a/src/libjin/Core/Game.h b/src/libjin/Core/Game.h
new file mode 100644
index 0000000..e155607
--- /dev/null
+++ b/src/libjin/Core/Game.h
@@ -0,0 +1,59 @@
+#ifndef __JIN_CORE_GAME_H
+#define __JIN_CORE_GAME_H
+
+#include <SDL2/SDL.h>
+
+#include "../common/singleton.h"
+#include "../utils/macros.h"
+
+namespace jin
+{
+namespace core
+{
+ class Game : public Singleton<Game>
+ {
+ public:
+
+ struct Setting
+ {
+
+ };
+
+ inline void quit() // quit game loop
+ {
+ CALLONCE(_quit());
+ }
+
+ inline bool running()
+ {
+ return run;
+ }
+
+ inline void exit() // exit game
+ {
+ CALLONCE(_exit());
+ }
+
+ private:
+
+ Game();
+ ~Game() {};
+
+ SINGLETON(Game);
+
+ bool run;
+
+ inline void _exit()
+ {
+ SDL_Quit();
+ }
+
+ inline void _quit()
+ {
+ run = false;
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Core/Thread.cpp b/src/libjin/Core/Thread.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Core/Thread.cpp
diff --git a/src/libjin/Core/Thread.h b/src/libjin/Core/Thread.h
new file mode 100644
index 0000000..6f70f09
--- /dev/null
+++ b/src/libjin/Core/Thread.h
@@ -0,0 +1 @@
+#pragma once
diff --git a/src/libjin/Core/Timer.cpp b/src/libjin/Core/Timer.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Core/Timer.cpp
diff --git a/src/libjin/Core/Timer.h b/src/libjin/Core/Timer.h
new file mode 100644
index 0000000..6f70f09
--- /dev/null
+++ b/src/libjin/Core/Timer.h
@@ -0,0 +1 @@
+#pragma once
diff --git a/src/libjin/Debug/Debug.h b/src/libjin/Debug/Debug.h
new file mode 100644
index 0000000..9fa9fe1
--- /dev/null
+++ b/src/libjin/Debug/Debug.h
@@ -0,0 +1,6 @@
+#ifndef __JIN_DEBUG_H
+#define __JIN_DEBUG_H
+
+
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Debug/Log.h b/src/libjin/Debug/Log.h
new file mode 100644
index 0000000..e1624f5
--- /dev/null
+++ b/src/libjin/Debug/Log.h
@@ -0,0 +1,14 @@
+#ifndef __JIN_LOG_H
+#define __JIN_LOG_H
+
+namespace jin
+{
+namespace debug
+{
+
+ const char* err;
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Input/Event.cpp b/src/libjin/Input/Event.cpp
new file mode 100644
index 0000000..8eb45e6
--- /dev/null
+++ b/src/libjin/Input/Event.cpp
@@ -0,0 +1,7 @@
+#include "event.h"
+#include "SDL2\SDL.h"
+
+namespace jin
+{
+
+} \ No newline at end of file
diff --git a/src/libjin/Input/Event.h b/src/libjin/Input/Event.h
new file mode 100644
index 0000000..e09f422
--- /dev/null
+++ b/src/libjin/Input/Event.h
@@ -0,0 +1,13 @@
+#ifndef __JIN_EVENT_H
+#define __JIN_EVENT_H
+namespace jin
+{
+namespace input
+{
+
+
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Input/Input.h b/src/libjin/Input/Input.h
new file mode 100644
index 0000000..217edd2
--- /dev/null
+++ b/src/libjin/Input/Input.h
@@ -0,0 +1,8 @@
+#ifndef __JIN_INPUT_H
+#define __JIN_INPUT_H
+
+#include "event.h"
+#include "keyboard.h"
+#include "mouse.h"
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Input/Joypad.cpp b/src/libjin/Input/Joypad.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Input/Joypad.cpp
diff --git a/src/libjin/Input/Joypad.h b/src/libjin/Input/Joypad.h
new file mode 100644
index 0000000..e8d309b
--- /dev/null
+++ b/src/libjin/Input/Joypad.h
@@ -0,0 +1,14 @@
+#ifndef __JIN_JOYPAD_H
+#define __JIN_JOYPAD_H
+
+namespace jin
+{
+namespace input
+{
+
+
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Input/Keyboard.cpp b/src/libjin/Input/Keyboard.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Input/Keyboard.cpp
diff --git a/src/libjin/Input/Keyboard.h b/src/libjin/Input/Keyboard.h
new file mode 100644
index 0000000..bbb6456
--- /dev/null
+++ b/src/libjin/Input/Keyboard.h
@@ -0,0 +1,13 @@
+#ifndef __JIN_KEYBOARD_H
+#define __JIN_KEYBOARD_H
+namespace jin
+{
+namespace input
+{
+ class Keyboard
+ {
+
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/libjin/Input/Mouse.cpp b/src/libjin/Input/Mouse.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Input/Mouse.cpp
diff --git a/src/libjin/Input/Mouse.h b/src/libjin/Input/Mouse.h
new file mode 100644
index 0000000..b926327
--- /dev/null
+++ b/src/libjin/Input/Mouse.h
@@ -0,0 +1,15 @@
+#ifndef __JIN_MOUSE_H
+#define __JIN_MOUSE_H
+namespace jin
+{
+namespace input
+{
+ class Mouse
+ {
+ public:
+
+ };
+
+}
+}
+#endif \ No newline at end of file
diff --git a/src/libjin/Math/Math.h b/src/libjin/Math/Math.h
new file mode 100644
index 0000000..849f74b
--- /dev/null
+++ b/src/libjin/Math/Math.h
@@ -0,0 +1,16 @@
+#ifndef __JIN_UTILS_MATH_H
+#define __JIN_UTILS_MATH_H
+
+#include <math.h>
+
+#include "constant.h"
+#include "matrix.h"
+#include "quad.h"
+
+#define min(a,b) (a < b ? a : b)
+#define max(a,b) (a > b ? a : b)
+#define clamp(a, mi,ma) (min(max(a,mi),ma))
+#define within(a,min,max) (a >= min && a <= max)
+#define without(a,min,max) (a < min || a > max)
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Math/Matrix.cpp b/src/libjin/Math/Matrix.cpp
new file mode 100644
index 0000000..97e9178
--- /dev/null
+++ b/src/libjin/Math/Matrix.cpp
@@ -0,0 +1,177 @@
+#include "Matrix.h"
+
+#include <cstring> // memcpy
+#include <cmath>
+
+namespace jin
+{
+namespace math
+{
+
+ // | e0 e4 e8 e12 |
+ // | e1 e5 e9 e13 |
+ // | e2 e6 e10 e14 |
+ // | e3 e7 e11 e15 |
+
+ Matrix::Matrix()
+ {
+ setIdentity();
+ }
+
+ Matrix::~Matrix()
+ {
+ }
+
+ // | e0 e4 e8 e12 |
+ // | e1 e5 e9 e13 |
+ // | e2 e6 e10 e14 |
+ // | e3 e7 e11 e15 |
+ // | e0 e4 e8 e12 |
+ // | e1 e5 e9 e13 |
+ // | e2 e6 e10 e14 |
+ // | e3 e7 e11 e15 |
+
+ Matrix Matrix::operator * (const Matrix & m) const
+ {
+ Matrix t;
+
+ t.e[0] = (e[0] * m.e[0]) + (e[4] * m.e[1]) + (e[8] * m.e[2]) + (e[12] * m.e[3]);
+ t.e[4] = (e[0] * m.e[4]) + (e[4] * m.e[5]) + (e[8] * m.e[6]) + (e[12] * m.e[7]);
+ t.e[8] = (e[0] * m.e[8]) + (e[4] * m.e[9]) + (e[8] * m.e[10]) + (e[12] * m.e[11]);
+ t.e[12] = (e[0] * m.e[12]) + (e[4] * m.e[13]) + (e[8] * m.e[14]) + (e[12] * m.e[15]);
+
+ t.e[1] = (e[1] * m.e[0]) + (e[5] * m.e[1]) + (e[9] * m.e[2]) + (e[13] * m.e[3]);
+ t.e[5] = (e[1] * m.e[4]) + (e[5] * m.e[5]) + (e[9] * m.e[6]) + (e[13] * m.e[7]);
+ t.e[9] = (e[1] * m.e[8]) + (e[5] * m.e[9]) + (e[9] * m.e[10]) + (e[13] * m.e[11]);
+ t.e[13] = (e[1] * m.e[12]) + (e[5] * m.e[13]) + (e[9] * m.e[14]) + (e[13] * m.e[15]);
+
+ t.e[2] = (e[2] * m.e[0]) + (e[6] * m.e[1]) + (e[10] * m.e[2]) + (e[14] * m.e[3]);
+ t.e[6] = (e[2] * m.e[4]) + (e[6] * m.e[5]) + (e[10] * m.e[6]) + (e[14] * m.e[7]);
+ t.e[10] = (e[2] * m.e[8]) + (e[6] * m.e[9]) + (e[10] * m.e[10]) + (e[14] * m.e[11]);
+ t.e[14] = (e[2] * m.e[12]) + (e[6] * m.e[13]) + (e[10] * m.e[14]) + (e[14] * m.e[15]);
+
+ t.e[3] = (e[3] * m.e[0]) + (e[7] * m.e[1]) + (e[11] * m.e[2]) + (e[15] * m.e[3]);
+ t.e[7] = (e[3] * m.e[4]) + (e[7] * m.e[5]) + (e[11] * m.e[6]) + (e[15] * m.e[7]);
+ t.e[11] = (e[3] * m.e[8]) + (e[7] * m.e[9]) + (e[11] * m.e[10]) + (e[15] * m.e[11]);
+ t.e[15] = (e[3] * m.e[12]) + (e[7] * m.e[13]) + (e[11] * m.e[14]) + (e[15] * m.e[15]);
+
+ return t;
+ }
+
+ void Matrix::operator *= (const Matrix & m)
+ {
+ Matrix t = (*this) * m;
+ memcpy((void*)this->e, (void*)t.e, sizeof(float) * 16);
+ }
+
+ const float * Matrix::getElements() const
+ {
+ return e;
+ }
+
+ void Matrix::setIdentity()
+ {
+ memset(e, 0, sizeof(float) * 16);
+ e[0] = e[5] = e[10] = e[15] = 1;
+ }
+
+ void Matrix::setTranslation(float x, float y)
+ {
+ setIdentity();
+ e[12] = x;
+ e[13] = y;
+ }
+
+ void Matrix::setRotation(float rad)
+ {
+ setIdentity();
+ float c = cos(rad), s = sin(rad);
+ e[0] = c; e[4] = -s;
+ e[1] = s; e[5] = c;
+ }
+
+ void Matrix::setScale(float sx, float sy)
+ {
+ setIdentity();
+ e[0] = sx;
+ e[5] = sy;
+ }
+
+ void Matrix::setShear(float kx, float ky)
+ {
+ setIdentity();
+ e[1] = ky;
+ e[4] = kx;
+ }
+
+ void Matrix::setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy)
+ {
+ memset(e, 0, sizeof(float) * 16); // zero out matrix
+ float c = cos(angle), s = sin(angle);
+ // matrix multiplication carried out on paper:
+ // |1 x| |c -s | |sx | |1 -ox|
+ // | 1 y| |s c | | sy | | 1 -oy|
+ // | 1 | | 1 | | 1 | | 1 |
+ // | 1| | 1| | 1| | 1 |
+ // move rotate scale origin
+ e[10] = e[15] = 1.0f;
+ e[0] = c * sx ; // = a
+ e[1] = s * sx ; // = b
+ e[4] = - s * sy; // = c
+ e[5] = c * sy; // = d
+ e[12] = x - ox * e[0] - oy * e[4];
+ e[13] = y - ox * e[1] - oy * e[5];
+ }
+
+ void Matrix::translate(float x, float y)
+ {
+ Matrix t;
+ t.setTranslation(x, y);
+ this->operator *=(t);
+ }
+
+ void Matrix::rotate(float rad)
+ {
+ Matrix t;
+ t.setRotation(rad);
+ this->operator *=(t);
+ }
+
+ void Matrix::scale(float sx, float sy)
+ {
+ Matrix t;
+ t.setScale(sx, sy);
+ this->operator *=(t);
+ }
+
+ void Matrix::shear(float kx, float ky)
+ {
+ Matrix t;
+ t.setShear(kx, ky);
+ this->operator *=(t);
+ }
+
+ // | x |
+ // | y |
+ // | 0 |
+ // | 1 |
+ // | e0 e4 e8 e12 |
+ // | e1 e5 e9 e13 |
+ // | e2 e6 e10 e14 |
+ // | e3 e7 e11 e15 |
+
+ void Matrix::transform(vertex * dst, const vertex * src, int size) const
+ {
+ for (int i = 0; i<size; ++i)
+ {
+ // Store in temp variables in case src = dst
+ float x = (e[0] * src[i].x) + (e[4] * src[i].y) + (0) + (e[12]);
+ float y = (e[1] * src[i].x) + (e[5] * src[i].y) + (0) + (e[13]);
+
+ dst[i].x = x;
+ dst[i].y = y;
+ }
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/libjin/Math/Matrix.h b/src/libjin/Math/Matrix.h
new file mode 100644
index 0000000..673d253
--- /dev/null
+++ b/src/libjin/Math/Matrix.h
@@ -0,0 +1,153 @@
+#ifndef __JIN_MATRIX_H
+#define __JIN_MATRIX_H
+#include <math.h>
+namespace jin
+{
+namespace math
+{
+
+ struct vertex
+ {
+ unsigned char r, g, b, a;
+ float x, y;
+ float s, t;
+ };
+ /**
+ * This class is the basis for all transformations in LOVE. Althought not
+ * really needed for 2D, it contains 4x4 elements to be compatible with
+ * OpenGL without conversions.
+ **/
+ class Matrix
+ {
+ private:
+
+ /**
+ * | e0 e4 e8 e12 |
+ * | e1 e5 e9 e13 |
+ * | e2 e6 e10 e14 |
+ * | e3 e7 e11 e15 |
+ **/
+ float e[16];
+
+ public:
+
+ /**
+ * Creates a new identity matrix.
+ **/
+ Matrix();
+
+ /**
+ * Destructor.
+ **/
+ ~Matrix();
+
+ /**
+ * Multiplies this Matrix with another Matrix, changing neither.
+ * @param m The Matrix to multiply with this Matrix.
+ * @return The combined matrix.
+ **/
+ Matrix operator * (const Matrix & m) const;
+
+ /**
+ * Multiplies a Matrix into this Matrix.
+ * @param m The Matrix to combine into this Matrix.
+ **/
+ void operator *= (const Matrix & m);
+
+ /**
+ * Gets a pointer to the 16 array elements.
+ * @return The array elements.
+ **/
+ const float * getElements() const;
+
+ /**
+ * Resets this Matrix to the identity matrix.
+ **/
+ void setIdentity();
+
+ /**
+ * Resets this Matrix to a translation.
+ * @param x Translation along x-axis.
+ * @param y Translation along y-axis.
+ **/
+ void setTranslation(float x, float y);
+
+ /**
+ * Resets this Matrix to a rotation.
+ * @param r The angle in radians.
+ **/
+ void setRotation(float r);
+
+ /**
+ * Resets this Matrix to a scale transformation.
+ * @param sx Scale factor along the x-axis.
+ * @param sy Scale factor along the y-axis.
+ **/
+ void setScale(float sx, float sy);
+
+ /**
+ * Resets this Matrix to a shear transformation.
+ * @param kx Shear along x-axis.
+ * @param ky Shear along y-axis.
+ **/
+ void setShear(float kx, float ky);
+
+ /**
+ * Creates a transformation with a certain position, orientation, scale
+ * and offset. Perfect for Drawables -- what a coincidence!
+ *
+ * @param x The translation along the x-axis.
+ * @param y The translation along the y-axis.
+ * @param angle The rotation (rad) around the center with offset (ox,oy).
+ * @param sx Scale along x-axis.
+ * @param sy Scale along y-axis.
+ * @param ox The offset for rotation along the x-axis.
+ * @param oy The offset for rotation along the y-axis.
+ * @param kx Shear along x-axis
+ * @param ky Shear along y-axis
+ **/
+ void setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy);
+
+ /**
+ * Multiplies this Matrix with a translation.
+ * @param x Translation along x-axis.
+ * @param y Translation along y-axis.
+ **/
+ void translate(float x, float y);
+
+ /**
+ * Multiplies this Matrix with a rotation.
+ * @param r Angle in radians.
+ **/
+ void rotate(float r);
+
+ /**
+ * Multiplies this Matrix with a scale transformation.
+ * @param sx Scale factor along the x-axis.
+ * @param sy Scale factor along the y-axis.
+ **/
+ void scale(float sx, float sy);
+
+ /**
+ * Multiplies this Matrix with a shear transformation.
+ * @param kx Shear along the x-axis.
+ * @param ky Shear along the y-axis.
+ **/
+ void shear(float kx, float ky);
+
+ /**
+ * Transforms an array of vertices by this Matrix. The sources and
+ * destination arrays may be the same.
+ *
+ * @param dst Storage for the transformed vertices.
+ * @param src The source vertices.
+ * @param size The number of vertices.
+ **/
+ void transform(vertex * dst, const vertex * src, int size) const;
+
+ };
+
+}
+}
+
+#endif
diff --git a/src/libjin/Math/Quad.h b/src/libjin/Math/Quad.h
new file mode 100644
index 0000000..a50cc9e
--- /dev/null
+++ b/src/libjin/Math/Quad.h
@@ -0,0 +1,17 @@
+#ifndef __JIN_QUAD_H
+#define __JIN_QUAD_H
+
+namespace jin
+{
+namespace math
+{
+
+ struct Quad
+ {
+ float x, y, w, h;
+ };
+
+}
+}
+
+#endif
diff --git a/src/libjin/Math/Vector.cpp b/src/libjin/Math/Vector.cpp
new file mode 100644
index 0000000..f26d0c4
--- /dev/null
+++ b/src/libjin/Math/Vector.cpp
@@ -0,0 +1,2 @@
+#include "vector.h"
+
diff --git a/src/libjin/Math/Vector.h b/src/libjin/Math/Vector.h
new file mode 100644
index 0000000..43e249e
--- /dev/null
+++ b/src/libjin/Math/Vector.h
@@ -0,0 +1,14 @@
+#ifndef __JIN_VECTOR_H
+#define __JIN_VECTOR_H
+
+namespace jin
+{
+namespace math
+{
+
+
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Math/constant.h b/src/libjin/Math/constant.h
new file mode 100644
index 0000000..f2f740f
--- /dev/null
+++ b/src/libjin/Math/constant.h
@@ -0,0 +1,10 @@
+#ifndef __JIN_MATH_CONSTANT_H
+#define __JIN_MATH_CONSTANT_H
+
+#define PI 3.1415926f
+
+// int16 Χ
+#define INT16_RANGE_LEFT -32768
+#define INT16_RANGE_RIGHT 32767
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Net/Net.cpp b/src/libjin/Net/Net.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Net/Net.cpp
diff --git a/src/libjin/Net/Net.h b/src/libjin/Net/Net.h
new file mode 100644
index 0000000..6b86a45
--- /dev/null
+++ b/src/libjin/Net/Net.h
@@ -0,0 +1,6 @@
+#ifndef __JIN_NET_H
+#define __JIN_NET_H
+
+
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Physics/Physics.h b/src/libjin/Physics/Physics.h
new file mode 100644
index 0000000..9927301
--- /dev/null
+++ b/src/libjin/Physics/Physics.h
@@ -0,0 +1,12 @@
+#ifndef __JIN_PHYSICS_H
+#define __JIN_PHYSICS_H
+
+namespace jin
+{
+namespace physics
+{
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Physics/Rigid.h b/src/libjin/Physics/Rigid.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Physics/Rigid.h
diff --git a/src/libjin/Render/Canvas.cpp b/src/libjin/Render/Canvas.cpp
new file mode 100644
index 0000000..8cb34ca
--- /dev/null
+++ b/src/libjin/Render/Canvas.cpp
@@ -0,0 +1,134 @@
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "../utils/macros.h"
+#include "canvas.h"
+#include "window.h"
+
+namespace jin
+{
+namespace render
+{
+
+ shared Canvas* Canvas::createCanvas(int w, int h)
+ {
+ return new Canvas(w, h);
+ }
+
+ Canvas::Canvas(int w, int h)
+ : Drawable(w, h)
+ {
+ init();
+ }
+
+ Canvas::~Canvas()
+ {
+ }
+
+ shared GLint Canvas::cur = -1;
+
+ bool Canvas::init()
+ {
+ setVertices(
+ new float [DRAWABLE_V_SIZE] {
+ 0, 0,
+ 0, (float)height,
+ (float)width, (float)height,
+ (float)width, 0,
+ },
+ new float [DRAWABLE_V_SIZE] {
+ 0, 1,
+ 0, 0,
+ 1, 0,
+ 1, 1
+ }
+ );
+
+ GLint current_fbo;
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_fbo);
+
+ // generate a new render buffer object
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ // generate texture save target
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ // unbind framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ return false;
+ return true;
+ }
+
+ bool Canvas::hasbind(GLint fbo)
+ {
+ return cur == fbo;
+ }
+
+ /**
+ * bind to canvas
+ */
+ void Canvas::bind()
+ {
+ if (hasbind(fbo)) return;
+
+ cur = fbo;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glViewport(0, 0, width, height);
+ glOrtho(0, width, height, 0, -1, 1);
+
+ // Switch back to modelview matrix
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ }
+
+ /**
+ * bind to default screen render buffer.
+ */
+ shared void Canvas::unbind()
+ {
+ if (hasbind(0)) return;
+
+ cur = 0;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ WindowSystem* wnd = WindowSystem::get();
+ int ww = wnd->getW(),
+ wh = wnd->getH();
+
+ glViewport(0, 0, ww, wh);
+
+ // load back to normal
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ // set viewport matrix
+ glOrtho(0, ww, wh, 0, -1, 1);
+
+ // switch to model matrix
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ }
+
+}
+}
+#endif // JIN_MODULES_RENDER \ No newline at end of file
diff --git a/src/libjin/Render/Canvas.h b/src/libjin/Render/Canvas.h
new file mode 100644
index 0000000..8cced23
--- /dev/null
+++ b/src/libjin/Render/Canvas.h
@@ -0,0 +1,40 @@
+#ifndef __JIN_CANVAS_H
+#define __JIN_CANVAS_H
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "drawable.h"
+namespace jin
+{
+namespace render
+{
+ class Canvas: public Drawable
+ {
+ public:
+
+ static Canvas* createCanvas(int w, int h);
+
+ ~Canvas();
+
+ void bind();
+
+ static void unbind();
+
+ static bool hasbind(GLint fbo);
+
+ private:
+
+ Canvas(int w, int h);
+
+ GLuint fbo;
+
+ // current binded fbo
+ static GLint cur;
+
+ bool init();
+ };
+}
+}
+
+#endif
+#endif // JIN_MODULES_RENDER
diff --git a/src/libjin/Render/Color.h b/src/libjin/Render/Color.h
new file mode 100644
index 0000000..7b88799
--- /dev/null
+++ b/src/libjin/Render/Color.h
@@ -0,0 +1,31 @@
+/**
+* Some color operating here.
+*/
+#ifndef __JIN_COLOR_H
+#define __JIN_COLOR_H
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "../utils/endian.h"
+
+namespace jin
+{
+namespace render
+{
+
+ union color {
+ struct {
+#if JIN_BYTEORDER == JIN_BIG_ENDIAN
+ unsigned char r, g, b, a;
+#else
+ unsigned char a, b, g, r;
+#endif
+ }rgba;
+ int word;
+ };
+
+}
+}
+
+#endif // JIN_MODULES_RENDER
+#endif \ No newline at end of file
diff --git a/src/libjin/Render/Drawable.cpp b/src/libjin/Render/Drawable.cpp
new file mode 100644
index 0000000..cbdf250
--- /dev/null
+++ b/src/libjin/Render/Drawable.cpp
@@ -0,0 +1,77 @@
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "drawable.h"
+#include "../math/matrix.h"
+#include <stdlib.h>
+
+namespace jin
+{
+namespace render
+{
+ Drawable::Drawable(int w, int h):texture(0), width(w), height(h), ancx(0), ancy(0), textCoord(0), vertCoord(0)
+ {
+ }
+
+ Drawable::~Drawable()
+ {
+ glDeleteTextures(1, &texture);
+ delete[] vertCoord;
+ delete[] textCoord;
+ }
+
+ void Drawable::setVertices(float* v, float* t)
+ {
+ // render area
+ if (vertCoord)
+ delete[] vertCoord;
+ vertCoord = v;
+
+ // textrue
+ if (textCoord)
+ delete[] textCoord;
+ textCoord = t;
+ }
+
+ void Drawable::setAnchor(int x, int y)
+ {
+ ancx = x;
+ ancy = y;
+ }
+
+ void Drawable::draw(int x, int y, float sx, float sy, float r)
+ {
+ // Must set textCoord and vertCoord before renderring
+ if (! textCoord||! vertCoord) return;
+
+ static jin::math::Matrix t;
+ t.setTransformation(x, y, r, sx, sy, ancx, ancy);
+
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ // push modle matrix
+ glPushMatrix();
+ glMultMatrixf((const GLfloat*)t.getElements());
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, textCoord);
+ glVertexPointer(2, GL_FLOAT, 0, vertCoord);
+ glDrawArrays(GL_QUADS, 0, 4);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ // pop the model matrix
+ glPopMatrix();
+
+ // bind texture to default screen
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glDisable(GL_TEXTURE_2D);
+ }
+}
+}
+
+#endif // JIN_MODULES_RENDER \ No newline at end of file
diff --git a/src/libjin/Render/Drawable.h b/src/libjin/Render/Drawable.h
new file mode 100644
index 0000000..f8e25a2
--- /dev/null
+++ b/src/libjin/Render/Drawable.h
@@ -0,0 +1,56 @@
+#ifndef __JIN_DRAWABLE
+#define __JIN_DRAWABLE
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "3rdparty/GLee/GLee.h"
+namespace jin
+{
+namespace render
+{
+ class Drawable
+ {
+ public:
+ Drawable(int w = 0, int h = 0);
+ virtual ~Drawable();
+
+ void setAnchor(int x, int y);
+
+ void draw(int x, int y, float sx, float sy, float r);
+
+ inline int Drawable::getWidth() const
+ {
+ return width;
+ }
+
+ inline int Drawable::getHeight() const
+ {
+ return height;
+ }
+
+ inline GLuint getTexture() const
+ {
+ return texture;
+ };
+
+ protected:
+#define DRAWABLE_V_SIZE 8
+ void setVertices(float* v, float* t);
+
+ GLuint texture;
+
+ int width, height;
+
+ /* anchor point */
+ int ancx, ancy;
+
+ // render coords
+ float* textCoord;
+ float* vertCoord;
+
+ };
+}
+}// jin
+
+#endif // JIN_MODULES_RENDER
+#endif
diff --git a/src/libjin/Render/Font.cpp b/src/libjin/Render/Font.cpp
new file mode 100644
index 0000000..e8e71b2
--- /dev/null
+++ b/src/libjin/Render/Font.cpp
@@ -0,0 +1,193 @@
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "font.h"
+#include <stdio.h>
+#define STB_TRUETYPE_IMPLEMENTATION
+#include "3rdparty/stb/stb_truetype.h"
+#include "color.h"
+
+namespace jin
+{
+namespace render
+{
+
+ using namespace jin::math;
+
+#define BITMAP_WIDTH 512
+#define BITMAP_HEIGHT 512
+#define PIXEL_HEIGHT 32
+
+ Font::Font():Drawable()
+ {
+ }
+
+ // ttf file read buffer
+ static unsigned char ttf_buffer[1 << 20];
+
+ // bitmap for saving font data
+ static unsigned char temp_bitmap[BITMAP_WIDTH * BITMAP_HEIGHT];
+
+ void Font::loadf(const char* path)
+ {
+ fread(ttf_buffer, 1, 1 << 20, fopen(path, "rb"));
+
+ loadb(ttf_buffer);
+ }
+
+ /**
+ * load from memory
+ */
+ void Font::loadb(const unsigned char* data)
+ {
+ stbtt_BakeFontBitmap(data, 0, PIXEL_HEIGHT, temp_bitmap, BITMAP_WIDTH, BITMAP_HEIGHT, 32, 96, cdata);
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_WIDTH,
+ BITMAP_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ /**
+ * get texture quad
+ */
+ static Quad getCharQuad(const stbtt_bakedchar* chardata, int pw, int ph, int char_index)
+ {
+ float ipw = 1.0f / pw, iph = 1.0f / ph;
+ const stbtt_bakedchar *b = chardata + char_index;
+ Quad q;
+ q.x = b->x0 * ipw;
+ q.y = b->y0 * iph;
+ q.w = b->x1 * ipw - b->x0 * ipw;
+ q.h = b->y1 * iph - b->y0 * iph;
+ return q;
+ }
+
+ /**
+ * render function draw mutiple times
+ * in loop
+ */
+ void Font::render(
+ const char* text, // rendered text
+ float x, float y, // render position
+ int fheight, // font height
+ int spacing, // font spacing
+ int lheight) // line height
+ {
+ float _x = x,
+ _y = y;
+
+ int len = strlen(text);
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ // for saving clip quad
+ stbtt_aligned_quad q;
+
+ // render every given character
+ int xc = x;
+ int yc = y;
+
+ float factor = fheight / (float)PIXEL_HEIGHT;
+
+ for (int i = 0; i < len; ++i)
+ {
+ char c = text[i];
+ if (c == '\n')
+ {
+ xc = x;
+ yc += lheight;
+ continue;
+ }
+
+ // only support ASCII
+ Quad q = getCharQuad(cdata, 512, 512, c - 32);
+ float s0 = q.x,
+ s1 = q.x + q.w,
+ t0 = q.y,
+ t1 = q.y + q.h;
+
+ // texture quad
+ float tc[] = {
+ s0, t1,
+ s1, t1,
+ s1, t0,
+ s0, t0
+ };
+
+ // character bound box
+ stbtt_bakedchar box = cdata[c - 32];
+
+ float width = factor * (box.x1 - box.x0);
+ float height = factor * (box.y1 - box.y0);
+ float xoffset = factor * box.xoff;
+ // I don't know why add PIXEL_HEIGHT to box.yoff, but
+ // it works.
+ float yoffset = factor * (box.yoff + PIXEL_HEIGHT);
+ float xadvance = factor * box.xadvance;
+
+ // render quad
+ float vc[] = {
+ xc + xoffset, yc + height + yoffset,
+ xc + width + xoffset, yc + height + yoffset,
+ xc + width + xoffset, yc + yoffset,
+ xc + xoffset, yc + yoffset
+ };
+
+ // forward to next character
+ xc += xadvance + spacing;
+
+ glTexCoordPointer(2, GL_FLOAT, 0, tc);
+ glVertexPointer(2, GL_FLOAT, 0, vc);
+ glDrawArrays(GL_QUADS, 0, 4);
+ }
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+ }
+
+ void Font::box(const char* str, int fheight, int spacing, int lheight, int* w, int * h)
+ {
+ int len = strlen(str);
+
+ float xc = 0;
+ int yc = len ? lheight: 0;
+ int maxX = 0;
+
+ float factor = fheight / (float)PIXEL_HEIGHT;
+
+ for (int i = 0; i < len; ++i)
+ {
+ char c = str[i];
+ if (c == '\n')
+ {
+ yc += lheight;
+ xc = 0;
+ continue;
+ }
+ stbtt_bakedchar box = cdata[c - 32];
+
+ xc += factor * box.xadvance + spacing;
+ if (xc > maxX) maxX = xc;
+ }
+
+ *w = maxX;
+ *h = yc;
+ }
+
+}
+}
+#endif // JIN_MODULES_RENDER \ No newline at end of file
diff --git a/src/libjin/Render/Font.h b/src/libjin/Render/Font.h
new file mode 100644
index 0000000..f2a57ed
--- /dev/null
+++ b/src/libjin/Render/Font.h
@@ -0,0 +1,61 @@
+#ifndef __JIN_FONT_H
+#define __JIN_FONT_H
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "drawable.h"
+#include "3rdparty/stb/stb_truetype.h"
+#include "../math/quad.h"
+
+namespace jin
+{
+namespace render
+{
+ /**
+ * Usage of stb_truetype.h here might be a little
+ * bit dummy. Implementation of Font is referring
+ * to stb_truetype.h L243~284. I basicly copy it:)
+ */
+ class Font: public Drawable
+ {
+ public:
+
+ Font();
+
+ /**
+ * load ttf font data from .ttf
+ */
+ void loadf(const char* file);
+
+ /**
+ * load ttf font data from memory
+ */
+ void loadb(const unsigned char* data);
+
+ /**
+ * render text to screen
+ */
+ void render(
+ const char* str, // rendered text
+ float x, float y, // render position
+ int fheight, // font size
+ int spacing, // font spacing
+ int lheight // line height
+ );
+
+ void box(const char* str, int fheight, int spacing, int lheight, int* w, int * h);
+
+ private:
+
+ /**
+ * ASCII 32(space)..126(~) is 95 glyphs
+ */
+ stbtt_bakedchar cdata[96];
+
+ };
+
+}
+}
+
+#endif // JIN_MODULES_RENDER
+#endif \ No newline at end of file
diff --git a/src/libjin/Render/Graphics.cpp b/src/libjin/Render/Graphics.cpp
new file mode 100644
index 0000000..f54021b
--- /dev/null
+++ b/src/libjin/Render/Graphics.cpp
@@ -0,0 +1,121 @@
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "graphics.h"
+#include "../math/matrix.h"
+#include "../math/constant.h"
+#include <string>
+namespace jin
+{
+namespace render
+{
+
+ void point(int x, int y)
+ {
+ float vers[] = { x + 0.5f , y + 0.5f };
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, (GLvoid*)vers);
+ glDrawArrays(GL_POINTS, 0, 1);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+
+ void points(int n, GLshort* p)
+ {
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ glVertexPointer(2, GL_SHORT, 0, (GLvoid*)p);
+ glDrawArrays(GL_POINTS, 0, n);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+
+ void line(int x1, int y1, int x2, int y2)
+ {
+ glDisable(GL_TEXTURE_2D);
+ float verts[] = {
+ x1, y1,
+ x2, y2
+ };
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, (GLvoid*)verts);
+ glDrawArrays(GL_LINES, 0, 2);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+
+ void circle(RENDER_MODE mode, int x, int y, int r)
+ {
+ r = r < 0 ? 0 : r;
+
+ int points = 40;
+ float two_pi = static_cast<float>(PI * 2);
+ if (points <= 0) points = 1;
+ float angle_shift = (two_pi / points);
+ float phi = .0f;
+
+ float *coords = new float[2 * (points + 1)];
+ for (int i = 0; i < points; ++i, phi += angle_shift)
+ {
+ coords[2 * i] = x + r * cos(phi);
+ coords[2 * i + 1] = y + r * sin(phi);
+ }
+
+ coords[2 * points] = coords[0];
+ coords[2 * points + 1] = coords[1];
+
+ polygon(mode, coords, points);
+
+ delete[] coords;
+ }
+
+ void rect(RENDER_MODE mode, int x, int y, int w, int h)
+ {
+ float coords[] = { x, y, x + w, y, x + w, y + h, x, y + h };
+ polygon(mode, coords, 4);
+ }
+
+ void triangle(RENDER_MODE mode, int x1, int y1, int x2, int y2, int x3, int y3)
+ {
+ float coords[] = { x1, y1, x2, y2, x3, y3 };
+ polygon(mode, coords, 3);
+ }
+
+ void polygon_line(float* p, int count)
+ {
+ float* verts = new float[count * 4];
+ for (int i = 0; i < count; ++i)
+ {
+ // each line has two point n,n+1
+ verts[i * 4] = p[i * 2];
+ verts[i * 4 + 1] = p[i * 2 + 1];
+ verts[i * 4 + 2] = p[(i + 1) % count * 2];
+ verts[i * 4 + 3] = p[(i + 1) % count * 2 + 1];
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, (GLvoid*)verts);
+ glDrawArrays(GL_LINES, 0, count * 2);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ delete[] verts;
+ }
+
+ void polygon(RENDER_MODE mode, float* p, int count)
+ {
+ if (mode == LINE)
+ {
+ polygon_line(p, count);
+ }
+ else if (mode == FILL)
+ {
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)p);
+ glDrawArrays(GL_POLYGON, 0, count);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+ }
+
+}
+}
+
+#endif // JIN_MODULES_RENDER \ No newline at end of file
diff --git a/src/libjin/Render/Graphics.h b/src/libjin/Render/Graphics.h
new file mode 100644
index 0000000..13dd4d1
--- /dev/null
+++ b/src/libjin/Render/Graphics.h
@@ -0,0 +1,40 @@
+#ifndef __JIN_GRAPHICS_H
+#define __JIN_GRAPHICS_H
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "color.h"
+#include "canvas.h"
+#include "texture.h"
+
+namespace jin
+{
+namespace render
+{
+ typedef enum {
+ NONE = 0,
+ FILL ,
+ LINE
+ }RENDER_MODE;
+
+ /**
+ * TODO:
+ * drawPixels(int n, points)
+ */
+ extern void line(int x1, int y1, int x2, int y2);
+
+ extern void rect(RENDER_MODE mode, int x, int y, int w, int h);
+
+ extern void triangle(RENDER_MODE mode, int x1, int y1, int x2, int y2, int x3, int y3);
+
+ extern void circle(RENDER_MODE mode, int x, int y, int r);
+
+ extern void point(int x, int y);
+
+ extern void points(int n, GLshort* p, GLubyte* c);
+
+ extern void polygon(RENDER_MODE mode, float* p, int count);
+}
+}
+#endif // JIN_MODULES_RENDER
+#endif // __JIN_GRAPHICS_H
diff --git a/src/libjin/Render/JSL.cpp b/src/libjin/Render/JSL.cpp
new file mode 100644
index 0000000..4ce660b
--- /dev/null
+++ b/src/libjin/Render/JSL.cpp
@@ -0,0 +1,158 @@
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "../utils/macros.h"
+#include "jsl.h"
+namespace jin
+{
+namespace render
+{
+ //vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords)
+ static const char* base_f = " "
+ //"#version 120 \n"
+ "#define number float \n"
+ "#define Image sampler2D \n"
+ "#define Canvas sampler2D \n"
+ "#define Color vec4 \n"
+ "#define Texel texture2D \n"
+ "#define extern uniform \n"
+ "uniform Image _tex0_; \n"
+ "%s \n"
+ "void main(){ \n"
+ " gl_FragColor = effect(gl_Color, _tex0_, gl_TexCoord[0].xy, gl_FragCoord.xy);\n"
+ "}\0";
+
+ shared JSLProgram* JSLProgram::currentJSLProgram = nullptr;
+
+ JSLProgram* JSLProgram::createJSLProgram(const char* program)
+ {
+ return new JSLProgram(program);
+ }
+
+ JSLProgram::JSLProgram(const char* program)
+ : currentTextureUnit(0)
+ {
+ initialize(program);
+ }
+
+ JSLProgram::~JSLProgram()
+ {
+ destroy();
+ }
+
+ inline void JSLProgram::destroy()
+ {
+ if (currentJSLProgram == this)
+ unuse();
+ }
+
+ inline void JSLProgram::initialize(const char* program)
+ {
+ char* fs = (char*)alloca(strlen(program) + strlen(base_f));
+ sprintf(fs, base_f, program);
+ GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fragmentShader, 1, (const GLchar**)&fs, NULL);
+ glCompileShader(fragmentShader);
+
+ pid = glCreateProgram();
+ glAttachShader(pid, fragmentShader);
+ glLinkProgram(pid);
+ }
+
+ static inline GLint getMaxTextureUnits()
+ {
+ GLint maxTextureUnits = 0;
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+ return maxTextureUnits;
+ }
+
+ GLint JSLProgram::getTextureUnit(const std::string& name)
+ {
+ std::map<std::string, GLint>::iterator texture_unit = texturePool.find(name);
+ if (texture_unit != texturePool.end())
+ return texture_unit->second;
+ static GLint maxTextureUnits = getMaxTextureUnits();
+ if (++currentTextureUnit >= maxTextureUnits)
+ return 0;
+ texturePool[name] = currentTextureUnit;
+ return currentTextureUnit;
+ }
+
+#define checkJSL() if (currentJSLProgram != this) return
+
+ void JSLProgram::sendFloat(const char* variable, float number)
+ {
+ checkJSL();
+
+ int loc = glGetUniformLocation(pid, variable);
+ glUniform1f(loc, number);
+ }
+
+ void JSLProgram::sendTexture(const char* variable, const Texture* tex)
+ {
+ checkJSL();
+
+ GLint location = glGetUniformLocation(pid, variable);
+ if (location == -1)
+ return;
+ GLint texture_unit = getTextureUnit(variable);
+ glUniform1i(location, texture_unit);
+ glActiveTexture(GL_TEXTURE0 + texture_unit);
+ glBindTexture(GL_TEXTURE_2D, tex->getTexture());
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ void JSLProgram::sendCanvas(const char* variable, const Canvas* canvas)
+ {
+ checkJSL();
+
+ GLint location = glGetUniformLocation(pid, variable);
+ if (location == -1)
+ return;
+ GLint texture_unit = getTextureUnit(variable);
+ glUniform1i(location, texture_unit);
+ glActiveTexture(GL_TEXTURE0 + texture_unit);
+ glBindTexture(GL_TEXTURE_2D, canvas->getTexture());
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ void JSLProgram::sendVec2(const char* name, float x, float y)
+ {
+ checkJSL();
+
+ int loc = glGetUniformLocation(pid, name);
+ glUniform2f(loc, x, y);
+ }
+
+ void JSLProgram::sendVec3(const char* name, float x, float y, float z)
+ {
+ checkJSL();
+
+ int loc = glGetUniformLocation(pid, name);
+ glUniform3f(loc, x, y, z);
+ }
+
+ void JSLProgram::sendVec4(const char* name, float x, float y, float z, float w)
+ {
+ checkJSL();
+
+ int loc = glGetUniformLocation(pid, name);
+ glUniform4f(loc, x, y, z, w);
+ }
+
+ void JSLProgram::sendColor(const char* name, const color* col)
+ {
+ checkJSL();
+
+ int loc = glGetUniformLocation(pid, name);
+ glUniform4f(loc,
+ col->rgba.r / 255.f,
+ col->rgba.g / 255.f,
+ col->rgba.b / 255.f,
+ col->rgba.a / 255.f
+ );
+ }
+
+}
+}
+#endif // JIN_MODULES_RENDER
diff --git a/src/libjin/Render/JSL.h b/src/libjin/Render/JSL.h
new file mode 100644
index 0000000..741983a
--- /dev/null
+++ b/src/libjin/Render/JSL.h
@@ -0,0 +1,74 @@
+#ifndef __JIN_JSL_H
+#define __JIN_JSL_H
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include <string>
+#include <map>
+#include "color.h"
+#include "texture.h"
+#include "canvas.h"
+#include "3rdparty/GLee/GLee.h"
+
+namespace jin
+{
+namespace render
+{
+
+ class JSLProgram
+ {
+
+ public:
+
+ static JSLProgram* createJSLProgram(const char* program);
+
+ ~JSLProgram();
+
+ inline void JSLProgram::use()
+ {
+ glUseProgram(pid);
+ currentJSLProgram = this;
+ }
+
+ static inline void JSLProgram::unuse()
+ {
+ glUseProgram(0);
+ currentJSLProgram = nullptr;
+ }
+
+ void sendFloat(const char* name, float number);
+ void sendTexture(const char* name, const Texture* image);
+ void sendVec2(const char* name, float x, float y);
+ void sendVec3(const char* name, float x, float y, float z);
+ void sendVec4(const char* name, float x, float y, float z, float w);
+ void sendCanvas(const char* name, const Canvas* canvas);
+ void sendColor(const char* name, const color* col);
+
+ static inline JSLProgram* getCurrentJSL()
+ {
+ return currentJSLProgram;
+ }
+
+ private:
+
+ JSLProgram(const char* program);
+
+ static JSLProgram* currentJSLProgram;
+
+ GLuint pid;
+
+ std::map<std::string, GLint> texturePool;
+
+ GLint currentTextureUnit;
+ GLint getTextureUnit(const std::string& name);
+
+ inline void initialize(const char* program);
+ inline void destroy();
+
+ };
+
+}
+}
+
+#endif // JIN_MODULES_RENDER
+#endif
diff --git a/src/libjin/Render/Render.h b/src/libjin/Render/Render.h
new file mode 100644
index 0000000..e51051e
--- /dev/null
+++ b/src/libjin/Render/Render.h
@@ -0,0 +1,15 @@
+#ifndef __JIN_RENDER_H
+#define __JIN_RENDER_H
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "canvas.h"
+#include "color.h"
+#include "font.h"
+#include "graphics.h"
+#include "texture.h"
+#include "jsl.h"
+#include "window.h"
+
+#endif // JIN_MODULES_RENDER
+#endif \ No newline at end of file
diff --git a/src/libjin/Render/Texture.cpp b/src/libjin/Render/Texture.cpp
new file mode 100644
index 0000000..cee3552
--- /dev/null
+++ b/src/libjin/Render/Texture.cpp
@@ -0,0 +1,99 @@
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include <fstream>
+#include "texture.h"
+#include "3rdparty/stb/stb_image.h"
+#include "../utils/utils.h"
+#include "../math/math.h"
+
+namespace jin
+{
+namespace render
+{
+
+ Texture* Texture::createTexture(const char* file)
+ {
+ std::ifstream fs;
+ fs.open(file, std::ios::binary);
+ Texture* tex = nullptr;
+ if (fs.is_open())
+ {
+ 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);
+ tex = createTexture(buffer, size);
+ free(buffer);
+ }
+ fs.close();
+ return tex;
+ }
+
+ Texture* Texture::createTexture(const void* mem, size_t size)
+ {
+ Texture* tex = new Texture();
+ if(!tex->loadb(mem, size))
+ {
+ delete tex;
+ tex = nullptr;
+ }
+ return tex;
+ }
+
+ Texture::Texture()
+ : Drawable(), pixels(0)
+ {
+ }
+
+ Texture::~Texture()
+ {
+ stbi_image_free(pixels);
+ }
+
+ color Texture::getPixel(int x, int y)
+ {
+ if (without(x, 0, width) || without(y, 0, height))
+ {
+ return { 0 };
+ }
+ return pixels[x + y * width];
+ }
+
+ bool Texture::loadb(const void* b, size_t size)
+ {
+ // ʹstbi_load_from_memory
+ unsigned char* textureData = stbi_load_from_memory((unsigned char *)b, size, &width, &height, NULL, STBI_rgb_alpha);
+ if (textureData == 0) return false;
+ pixels = (color*)textureData;
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width,
+ height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
+
+ // set render vertices
+ Drawable::setVertices(
+ new float [DRAWABLE_V_SIZE] {
+ 0, 0,
+ 0, (float)height,
+ (float)width, (float)height,
+ (float)width, 0,
+ },
+ new float [DRAWABLE_V_SIZE] {
+ 0, 0,
+ 0, 1,
+ 1, 1,
+ 1, 0
+ }
+ );
+
+ return true;
+ }
+}
+}
+#endif // JIN_MODULES_RENDER \ No newline at end of file
diff --git a/src/libjin/Render/Texture.h b/src/libjin/Render/Texture.h
new file mode 100644
index 0000000..d2e4bd0
--- /dev/null
+++ b/src/libjin/Render/Texture.h
@@ -0,0 +1,38 @@
+#ifndef __JIN_IMAGE_H
+#define __JIN_IMAGE_H
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include "3rdparty/GLee/GLee.h"
+#include "color.h"
+#include "drawable.h"
+namespace jin
+{
+namespace render
+{
+ class Texture: public Drawable
+ {
+
+ public:
+
+ static Texture* createTexture(const char* file);
+ static Texture* createTexture(const void* mem, size_t size);
+
+ ~Texture();
+
+ color getPixel(int x, int y);
+
+ private:
+
+ Texture();
+
+ bool loadb(const void* buffer, size_t size);
+
+ color* pixels;
+
+ };
+}
+}
+
+#endif // JIN_MODULES_RENDER
+#endif \ No newline at end of file
diff --git a/src/libjin/Render/Window.cpp b/src/libjin/Render/Window.cpp
new file mode 100644
index 0000000..6507691
--- /dev/null
+++ b/src/libjin/Render/Window.cpp
@@ -0,0 +1,90 @@
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include <iostream>
+#include "window.h"
+#include "3rdparty/GLee/GLee.h"
+#include "canvas.h"
+#include "../utils/utils.h"
+#include "../audio/sdl/audio.h"
+#include "../utils/log.h"
+
+namespace jin
+{
+namespace render
+{
+
+ onlyonce bool WindowSystem::initSystem(const SettingBase* s)
+ {
+ Loghelper::log(Loglevel::LV_INFO, "Init window system");
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ return false;
+
+ const WindowSetting* setting = (WindowSetting*)s;
+
+ width = setting->width;
+ height = setting->height;
+ bool vsync = setting->vsync;
+ const char* title = setting->title;
+
+ if (wnd)
+ {
+ SDL_DestroyWindow(wnd);
+ SDL_FlushEvent(SDL_WINDOWEVENT);
+ }
+
+ SDL_GLContext ctx = NULL;
+
+ if (ctx)
+ {
+ SDL_GL_DeleteContext(ctx);
+ }
+
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ int wx = SDL_WINDOWPOS_UNDEFINED,
+ wy = SDL_WINDOWPOS_UNDEFINED;
+
+ wnd = SDL_CreateWindow(title, wx, wy, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
+ if (wnd == NULL)
+ return false;
+ ctx = SDL_GL_CreateContext(wnd);
+ if (ctx == NULL)
+ return false;
+ SDL_GL_SetSwapInterval(vsync ? 1 : 0);
+ SDL_GL_MakeCurrent(wnd, ctx);
+ glClearColor(0.f, 0.f, 0.f, 1.f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glColor4f(1, 1, 1, 1);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ Canvas::unbind();
+ swapBuffers();
+ return true;
+ }
+
+ onlyonce void WindowSystem::quitSystem()
+ {
+ SDL_DestroyWindow(wnd);
+ }
+
+ inline void WindowSystem::swapBuffers()
+ {
+ if (wnd)
+ SDL_GL_SwapWindow(wnd);
+ }
+
+}
+}
+
+#endif // JIN_MODULES_RENDER \ No newline at end of file
diff --git a/src/libjin/Render/Window.h b/src/libjin/Render/Window.h
new file mode 100644
index 0000000..77b1963
--- /dev/null
+++ b/src/libjin/Render/Window.h
@@ -0,0 +1,59 @@
+#ifndef __JIN_RENDER_WINDOW
+#define __JIN_RENDER_WINDOW
+#include "../modules.h"
+#if JIN_MODULES_RENDER
+
+#include <SDL2/SDL.h>
+#include "../utils/utils.h"
+#include "../common/subsystem.h"
+
+namespace jin
+{
+namespace render
+{
+
+ class WindowSystem : public Subsystem<WindowSystem>
+ {
+ public:
+
+ struct Setting : SettingBase
+ {
+ public:
+ int width, height; // ڴС
+ bool vsync; // ֱͬ
+ const char* title; //
+ };
+
+ inline int getW()
+ {
+ return width;
+ }
+
+ inline int getH()
+ {
+ return height;
+ }
+
+ inline void swapBuffers();
+
+ private:
+
+ WindowSystem() {};
+ virtual ~WindowSystem() {};
+
+ SINGLETON(WindowSystem);
+
+ SDL_Window* wnd;
+
+ int width, height;
+
+ onlyonce bool initSystem(const SettingBase* setting) override;
+ onlyonce void quitSystem() override;
+ };
+
+ typedef WindowSystem::Setting WindowSetting;
+
+}
+}
+#endif // JIN_MODULES_RENDER
+#endif \ No newline at end of file
diff --git a/src/libjin/Thread/Thread.cpp b/src/libjin/Thread/Thread.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Thread/Thread.cpp
diff --git a/src/libjin/Thread/Thread.h b/src/libjin/Thread/Thread.h
new file mode 100644
index 0000000..6f70f09
--- /dev/null
+++ b/src/libjin/Thread/Thread.h
@@ -0,0 +1 @@
+#pragma once
diff --git a/src/libjin/Tilemap/Tilemap.h b/src/libjin/Tilemap/Tilemap.h
new file mode 100644
index 0000000..27cbe51
--- /dev/null
+++ b/src/libjin/Tilemap/Tilemap.h
@@ -0,0 +1,14 @@
+#ifndef __JIN_TILEMAP_H
+#define __JIN_TILEMAP_H
+
+namespace jin
+{
+namespace tilemap
+{
+
+
+
+}// tilemap
+}// jin
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Tools/EventMsgCenter/EventMsgCenter.h b/src/libjin/Tools/EventMsgCenter/EventMsgCenter.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Tools/EventMsgCenter/EventMsgCenter.h
diff --git a/src/libjin/UI/UI.h b/src/libjin/UI/UI.h
new file mode 100644
index 0000000..6f70f09
--- /dev/null
+++ b/src/libjin/UI/UI.h
@@ -0,0 +1 @@
+#pragma once
diff --git a/src/libjin/Utils/Log.cpp b/src/libjin/Utils/Log.cpp
new file mode 100644
index 0000000..5299942
--- /dev/null
+++ b/src/libjin/Utils/Log.cpp
@@ -0,0 +1,2 @@
+#define LOGHELPER_IMPLEMENT
+#include "log.h" \ No newline at end of file
diff --git a/src/libjin/Utils/Log.h b/src/libjin/Utils/Log.h
new file mode 100644
index 0000000..b047402
--- /dev/null
+++ b/src/libjin/Utils/Log.h
@@ -0,0 +1,134 @@
+/**
+* Single.h/loghelper.h
+* Copyright (C) 2017~2018 chai
+*/
+#ifndef __LOG_HELPER_H
+#define __LOG_HELPER_H
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <stdarg.h>
+
+class Loghelper
+{
+public:
+ // logĿ
+ enum Direction
+ {
+ DIR_CERR = 1 << 1, // ׼
+ DIR_FILE = 1 << 2, // logļ
+ };
+
+ // ȼ
+ enum Level
+ {
+ LV_NONE = 0, // none
+ LV_ERROR = 1 << 1, // error
+ LV_WARN = 1 << 2, // warn
+ LV_INFO = 1 << 3, // info
+ LV_DEBUG = 1 << 4, // debug
+ LV_ALL = 0xffffffff
+ };
+
+ static void log(Level _level, const char* _fmt, ...);
+
+ // ض
+ static void redirect(unsigned int _dir, char* _path = nullptr);
+
+ // ɸѡȼ
+ static void restrict(unsigned int levels);
+
+ static void close();
+
+private:
+ static unsigned int dir; // Ŀ
+ static unsigned int levels; // ȼ
+ 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)
+ char* levelStr = nullptr;
+ switch (_level)
+ {
+ case LV_ERROR:
+ levelStr = "Error: ";
+ break;
+ case LV_WARN:
+ levelStr = "Warn: ";
+ break;
+ case LV_INFO:
+ levelStr = "Info: ";
+ break;
+ case LV_DEBUG:
+ levelStr = "Debug: ";
+ break;
+ default:
+ levelStr = "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
+
+#endif
diff --git a/src/libjin/Utils/endian.h b/src/libjin/Utils/endian.h
new file mode 100644
index 0000000..d4c441a
--- /dev/null
+++ b/src/libjin/Utils/endian.h
@@ -0,0 +1,23 @@
+#ifndef JIN_LIL_ENDIAN && JIN_BIG_ENDIAN
+
+#define JIN_LIL_ENDIAN 2
+#define JIN_BIG_ENDIAN 4
+
+#endif
+
+#ifndef JIN_BYTEORDER
+#ifdef __linux__
+#include <endian.h>
+#define JIN_BYTEORDER __BYTE_ORDER
+#else /* __linux__ */
+#if defined(__hppa__) || \
+ defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
+ (defined(__MIPS__) && defined(__MISPEB__)) || \
+ defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
+ defined(__sparc__)
+#define JIN_BYTEORDER JIN_BIG_ENDIAN
+#else
+#define JIN_BYTEORDER JIN_LIL_ENDIAN
+#endif
+#endif /* __linux__ */
+#endif /* !SDL_BYTEORDER */ \ No newline at end of file
diff --git a/src/libjin/Utils/macros.h b/src/libjin/Utils/macros.h
new file mode 100644
index 0000000..684e8e8
--- /dev/null
+++ b/src/libjin/Utils/macros.h
@@ -0,0 +1,16 @@
+#ifndef __JIN_MACROS_H
+#define __JIN_MACROS_H
+#include <cstring>
+
+#define implement // ʵֽӿ
+
+#define shared // ķ
+
+#define MASK // enum
+
+#define CALLONCE(call) static char __dummy__=(call, 1) // ֻһ
+#define onlyonce // ֻһ
+
+#define zero(mem) memset(&mem, 0, sizeof(mem))
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Utils/unittest.cpp b/src/libjin/Utils/unittest.cpp
new file mode 100644
index 0000000..2952b0b
--- /dev/null
+++ b/src/libjin/Utils/unittest.cpp
@@ -0,0 +1,108 @@
+#include "utils.h"
+#if UNITTEST
+
+#include <iostream>
+#include <stdio.h>
+#include <fstream>
+#include "../audio/sdl/source.h"
+#include "../audio/sdl/audio.h"
+
+using namespace jin::audio;
+using namespace std;
+
+int main(int argc, char* argv[])
+{
+ SDLAudio* audio = SDLAudio::get();
+ audio->init(0);
+ SDLSource* source = SDLSource::createSource("a.ogg");
+ SDLSource* source2 = SDLSource::createSource("a.wav");
+ //source->play();
+ source2->play();
+ source->setLoop(true);
+ source2->setLoop(true);
+ int i = 0;
+ while (true)
+ {
+ SDL_Delay(1000);
+ }
+ audio->quit();
+ return 0;
+}
+
+/*
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <SDL2/SDL.h>
+
+#include <3rdparty/cmixer/cmixer.h>
+
+static SDL_mutex* audio_mutex;
+
+static void lock_handler(cm_Event *e) {
+ if (e->type == CM_EVENT_LOCK) {
+ SDL_LockMutex(audio_mutex);
+ }
+ if (e->type == CM_EVENT_UNLOCK) {
+ SDL_UnlockMutex(audio_mutex);
+ }
+}
+
+
+static void audio_callback(void *udata, Uint8 *stream, int size) {
+ cm_process((cm_Int16*)stream, size / 2);
+}
+
+
+int main(int argc, char **argv) {
+ SDL_AudioDeviceID dev;
+ SDL_AudioSpec fmt, got;
+ cm_Source *src;
+ cm_Source* src2;
+
+
+ SDL_Init(SDL_INIT_AUDIO);
+ audio_mutex = SDL_CreateMutex();
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.freq = 44100;
+ fmt.format = AUDIO_S16;
+ fmt.channels = 2;
+ fmt.samples = 1024;
+ fmt.callback = audio_callback;
+
+ dev = SDL_OpenAudioDevice(NULL, 0, &fmt, &got, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
+ if (dev == 0) {
+ fprintf(stderr, "Error: failed to open audio device '%s'\n", SDL_GetError());
+ exit(EXIT_FAILURE);
+ }
+
+ cm_init(got.freq);
+ cm_set_lock(lock_handler);
+ cm_set_master_gain(0.5);
+
+ SDL_PauseAudioDevice(dev, 0);
+
+ src = cm_new_source_from_file("a.ogg");
+ src2 = cm_new_source_from_file("loop.wav");
+ if (!src) {
+ fprintf(stderr, "Error: failed to create source '%s'\n", cm_get_error());
+ exit(EXIT_FAILURE);
+ }
+ cm_set_loop(src2, 1);
+
+ cm_play(src);
+ cm_play(src2);
+
+ printf("Press [return] to exit\n");
+ getchar();
+
+ cm_destroy_source(src);
+ SDL_CloseAudioDevice(dev);
+ SDL_Quit();
+
+ return EXIT_SUCCESS;
+}
+*/
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Utils/utils.h b/src/libjin/Utils/utils.h
new file mode 100644
index 0000000..cf0920e
--- /dev/null
+++ b/src/libjin/Utils/utils.h
@@ -0,0 +1,9 @@
+#ifndef __JIN_UTILS_H
+#define __JIN_UTILS_H
+
+#include "macros.h"
+#include "endian.h"
+
+#define UNITTEST 0
+
+#endif \ No newline at end of file