diff options
Diffstat (limited to 'src/libjin')
32 files changed, 2408 insertions, 0 deletions
diff --git a/src/libjin/audio/audio.cpp b/src/libjin/audio/audio.cpp new file mode 100644 index 0000000..88fe52b --- /dev/null +++ b/src/libjin/audio/audio.cpp @@ -0,0 +1,11 @@ +#include "audio.h" + +namespace jin +{ +namespace 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..652e7a8 --- /dev/null +++ b/src/libjin/audio/audio.h @@ -0,0 +1,15 @@ +#ifndef __JIN_AUDIO_H +#define __JIN_AUDIO_H + + +namespace jin +{ +namespace audio +{ + + + +} +} + +#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..1c47d87 --- /dev/null +++ b/src/libjin/core/game.cpp @@ -0,0 +1,14 @@ +#include "game.h" + +namespace jin +{ +namespace core +{ + + Game* Game::g_game = 0; + + Game::Game() :run(true) {}; + +} +} + diff --git a/src/libjin/core/game.h b/src/libjin/core/game.h new file mode 100644 index 0000000..d56b249 --- /dev/null +++ b/src/libjin/core/game.h @@ -0,0 +1,38 @@ +#ifndef __JIN_CORE_GAME_H +#define __JIN_CORE_GAME_H + +namespace jin +{ +namespace core +{ + class Game + { + public: + + static inline Game* get() + { + return g_game ? g_game : (g_game = new Game()); + } + + inline void quit() + { + run = false; + } + + inline bool running() + { + return run; + } + + private: + + Game(); + + static Game* g_game; + + bool run; + }; +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/fs/buffer.h b/src/libjin/fs/buffer.h new file mode 100644 index 0000000..d727d84 --- /dev/null +++ b/src/libjin/fs/buffer.h @@ -0,0 +1,42 @@ +#include <string.h> + +namespace jin +{ +namespace fs +{ + + /** + * A file data buffer. + */ + class Buffer + { + public: + + inline Buffer(): data(0), size(0) + { + } + + inline ~Buffer() + { + size = 0; + delete[] data; + } + + inline Buffer(void* d, int size) + { + data = new char(size); + memcpy(data, d, size); + } + + public: + + // data position in memory + void* data; + + // data buffer size + unsigned int size; + + }; + +} +}
\ No newline at end of file diff --git a/src/libjin/fs/dirent.h b/src/libjin/fs/dirent.h new file mode 100644 index 0000000..832b164 --- /dev/null +++ b/src/libjin/fs/dirent.h @@ -0,0 +1,951 @@ +/* +* Dirent interface for Microsoft Visual Studio +* Version 1.21 +* +* Copyright (C) 2006-2012 Toni Ronkko +* This file is part of dirent. Dirent may be freely distributed +* under the MIT license. For all details and documentation, see +* https://github.com/tronkko/dirent +*/ +#ifndef DIRENT_H +#define DIRENT_H + +/* +* Include windows.h without Windows Sockets 1.1 to prevent conflicts with +* Windows Sockets 2.0. +*/ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +#include <stdio.h> +#include <stdarg.h> +#include <wchar.h> +#include <string.h> +#include <stdlib.h> +#include <malloc.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* +* File type macros. Note that block devices, sockets and links cannot be +* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are +* only defined for compatibility. These macros should always return false +* on Windows. +*/ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of d_namlen without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return number of bytes needed to store d_namlen */ +#define _D_ALLOC_NAMLEN(p) (PATH_MAX) + + +#ifdef __cplusplus +extern "C" { +#endif + + + /* Wide-character version */ + struct _wdirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX]; + }; + typedef struct _wdirent _wdirent; + + struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; + }; + typedef struct _WDIR _WDIR; + + static _WDIR *_wopendir(const wchar_t *dirname); + static struct _wdirent *_wreaddir(_WDIR *dirp); + static int _wclosedir(_WDIR *dirp); + static void _wrewinddir(_WDIR* dirp); + + + /* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + + /* Multi-byte character versions */ + struct dirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX]; + }; + typedef struct dirent dirent; + + struct DIR { + struct dirent ent; + struct _WDIR *wdirp; + }; + typedef struct DIR DIR; + + static DIR *opendir(const char *dirname); + static struct dirent *readdir(DIR *dirp); + static int closedir(DIR *dirp); + static void rewinddir(DIR* dirp); + + + /* Internal utility functions */ + static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); + static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); + + static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + + static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + + static void dirent_set_errno(int error); + + /* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ + static _WDIR* + _wopendir( + const wchar_t *dirname) + { + _WDIR *dirp = NULL; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*)malloc(sizeof(struct _WDIR)); + if (dirp != NULL) { + DWORD n; + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + n = wcslen(dirname); +# else + n = GetFullPathNameW(dirname, 0, NULL, NULL); +# endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*)malloc(sizeof(wchar_t) * n + 16); + if (dirp->patt) { + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + wcsncpy_s(dirp->patt, n + 1, dirname, n); +# else + n = GetFullPathNameW(dirname, n, dirp->patt, NULL); +# endif + if (n > 0) { + wchar_t *p; + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + if (dirp->patt < p) { + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (dirent_first(dirp)) { + /* Directory stream opened successfully */ + error = 0; + } + else { + /* Cannot retrieve first entry */ + error = 1; + dirent_set_errno(ENOENT); + } + + } + else { + /* Cannot retrieve full path name */ + dirent_set_errno(ENOENT); + error = 1; + } + + } + else { + /* Cannot allocate memory for search pattern */ + error = 1; + } + + } + else { + /* Cannot allocate _WDIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + _wclosedir(dirp); + dirp = NULL; + } + + return dirp; + } + + /* + * Read next directory entry. The directory entry is returned in dirent + * structure in the d_name field. Individual directory entries returned by + * this function include regular files, sub-directories, pseudo-directories + * "." and ".." as well as volume labels, hidden files and system files. + */ + static struct _wdirent* + _wreaddir( + _WDIR *dirp) + { + WIN32_FIND_DATAW *datap; + struct _wdirent *entp; + + /* Read next directory entry */ + datap = dirent_next(dirp); + if (datap) { + size_t n; + DWORD attr; + + /* Pointer to directory entry to return */ + entp = &dirp->ent; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) { + entp->d_name[n] = datap->cFileName[n]; + n++; + } + dirp->ent.d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } + else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof(struct _wdirent); + + } + else { + + /* Last directory entry read */ + entp = NULL; + + } + + return entp; + } + + /* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ + static int + _wclosedir( + _WDIR *dirp) + { + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + } + + /* Release search pattern */ + if (dirp->patt) { + free(dirp->patt); + dirp->patt = NULL; + } + + /* Release directory structure */ + free(dirp); + ok = /*success*/0; + + } + else { + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/-1; + } + return ok; + } + + /* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ + static void + _wrewinddir( + _WDIR* dirp) + { + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose(dirp->handle); + } + + /* Open new search handle */ + dirent_first(dirp); + } + } + + /* Get first directory entry (internal) */ + static WIN32_FIND_DATAW* + dirent_first( + _WDIR *dirp) + { + WIN32_FIND_DATAW *datap; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } + else { + + /* Failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + } + return datap; + } + + /* Get next directory entry (internal) */ + static WIN32_FIND_DATAW* + dirent_next( + _WDIR *dirp) + { + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } + else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } + else { + /* The very last entry has been processed or an error occured */ + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } + else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; + } + + /* + * Open directory stream using plain old C-string. + */ + static DIR* + opendir( + const char *dirname) + { + struct DIR *dirp; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*)malloc(sizeof(struct DIR)); + if (dirp) { + wchar_t wname[PATH_MAX]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s(&n, wname, PATH_MAX, dirname, PATH_MAX); + if (!error) { + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir(wname); + if (dirp->wdirp) { + /* Directory stream opened */ + error = 0; + } + else { + /* Failed to open directory stream */ + error = 1; + } + + } + else { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + error = 1; + } + + } + else { + /* Cannot allocate DIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + free(dirp); + dirp = NULL; + } + + return dirp; + } + + /* + * Read next directory entry. + * + * When working with text consoles, please note that file names returned by + * readdir() are represented in the default ANSI code page while any output to + * console is typically formatted on another code page. Thus, non-ASCII + * characters in file names will not usually display correctly on console. The + * problem can be fixed in two ways: (1) change the character set of console + * to 1252 using chcp utility and use Lucida Console font, or (2) use + * _cprintf function when writing to console. The _cprinf() will re-encode + * ANSI strings to the console code page so many non-ASCII characters will + * display correcly. + */ + static struct dirent* + readdir( + DIR *dirp) + { + WIN32_FIND_DATAW *datap; + struct dirent *entp; + + /* Read next directory entry */ + datap = dirent_next(dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, + datap->cAlternateFileName, PATH_MAX); + } + + if (!error) { + DWORD attr; + + /* Initialize directory entry for return */ + entp = &dirp->ent; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } + else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof(struct dirent); + + } + else { + /* + * Cannot convert file name to multi-byte string so construct + * an errornous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entp = &dirp->ent; + entp->d_name[0] = '?'; + entp->d_name[1] = '\0'; + entp->d_namlen = 1; + entp->d_type = DT_UNKNOWN; + entp->d_ino = 0; + entp->d_reclen = 0; + } + + } + else { + /* No more directory entries */ + entp = NULL; + } + + return entp; + } + + /* + * Close directory stream. + */ + static int + closedir( + DIR *dirp) + { + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir(dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free(dirp); + + } + else { + + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/-1; + + } + return ok; + } + + /* + * Rewind directory stream to beginning. + */ + static void + rewinddir( + DIR* dirp) + { + /* Rewind wide-character string directory stream */ + _wrewinddir(dirp->wdirp); + } + + /* Convert multi-byte string to wide character string */ + static int + dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) + { + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs(wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resuting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } + else { + + /* Could not convert string */ + error = 1; + + } + +#endif + + return error; + } + + /* Convert wide-character string to multi-byte string */ + static int + dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) + { + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs(mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } + else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + + return error; + } + + /* Set errno variable */ + static void + dirent_set_errno( + int error) + { +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno(error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif + } + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ + diff --git a/src/libjin/fs/filesystem.cpp b/src/libjin/fs/filesystem.cpp new file mode 100644 index 0000000..72f1144 --- /dev/null +++ b/src/libjin/fs/filesystem.cpp @@ -0,0 +1,68 @@ +#include "filesystem.h" +#include <string.h> +#include <stdlib.h> +#include <stdio.h> /* defines FILENAME_MAX */ + +namespace jin +{ +namespace fs +{ + + Filesystem* Filesystem::fs = 0; + + Filesystem::Filesystem() + { + S = sm_newshared(); + } + + Filesystem* Filesystem::get() + { + return fs ? fs : (fs = new Filesystem()); + } + + /** + * r is relative path + */ + void Filesystem::mount(const char * path) + { + int err = sm_mount(S, path); + if (err) + { + printf("%s mounted path %s", sm_errstr(err), path); + exit(1); + } + } + + /** + * + */ + int Filesystem::read(const char* path, Buffer* buffer) + { + buffer->data = sm_read(S, path, &buffer->size); + if (buffer->data == 0) + return 0; + return 1; + } + + const char* Filesystem::getFull(const char* path) + { + return sm_fullpath(S, path); + } + + bool Filesystem::isDir(const char* path) + { + return sm_isdir(S, path); + } + + bool Filesystem::isFile(const char* path) + { + return sm_isreg(S, path); + } + + bool Filesystem::exists(const char* path) + { + return sm_exists(S, path) == 0; + } + +} +}
\ No newline at end of file diff --git a/src/libjin/fs/filesystem.h b/src/libjin/fs/filesystem.h new file mode 100644 index 0000000..8c8ef04 --- /dev/null +++ b/src/libjin/fs/filesystem.h @@ -0,0 +1,55 @@ +#include "buffer.h" +#include "3rdparty/smount/smount.h" + +namespace jin +{ +namespace fs +{ + + class Filesystem + { + public: + + Filesystem(); + + static Filesystem* get(); + + /** + * is a path a directroy or a single file + */ + bool isDir(const char* path); + + /** + * is a path a directroy or a single file + */ + bool isFile(const char* path); + + /** + * is path a valid path + */ + bool exists(const char* path); + + /** + * read a file and return data buffer + */ + int read(const char* path, Buffer* buffer); + + /** + * set root directory, can only mount once. + */ + void mount(const char* root); + + /** + * convret relative path to absolute path + */ + const char* getFull(const char* path); + + private: + + static Filesystem* fs; + + sm_Shared* S; + + }; +} +}
\ 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/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..55e3346 --- /dev/null +++ b/src/libjin/input/mouse.h @@ -0,0 +1,30 @@ +#ifndef __JIN_MOUSE_H +#define __JIN_MOUSE_H +namespace jin +{ +namespace input +{ + class Mouse + { + public: + + }; + + inline const char* buttonStr(int id) { + switch (id) { + case 1: return "left"; + case 2: return "middle"; + case 3: return "right"; + case 4: return "wheelup"; + case 5: return "wheeldown"; + default: return "?"; + } + } + + inline const char* wheelStr(int dir) + { + + } +} +} +#endif
\ No newline at end of file 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/render/canvas.cpp b/src/libjin/render/canvas.cpp new file mode 100644 index 0000000..494b0fa --- /dev/null +++ b/src/libjin/render/canvas.cpp @@ -0,0 +1,123 @@ +#include "utils/macros.h" +#include "canvas.h" +#include "window.h" + +namespace jin +{ +namespace render +{ + Canvas::Canvas() :Drawable() + { + } + + Canvas::~Canvas() + { + } + + // no canvas has binded + shared GLint Canvas::cur = -1; + + bool Canvas::init(int w, int h) + { + Drawable::init(w, h); + Drawable::setVertices( + new float [DRAWABLE_V_SIZE] { + 0, 0, + 0, (float)h, + (float)w, (float)h, + (float)w, 0, + }, + new float [DRAWABLE_V_SIZE] { + 0, 1, + 0, 0, + 1, 0, + 1, 1 + } + ); + + GLint current_fbo; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_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, w, h, 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); + Window* wnd = Window::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(); + } +} +}
\ 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..4600f8b --- /dev/null +++ b/src/libjin/render/canvas.h @@ -0,0 +1,33 @@ +#ifndef __JIN_CANVAS_H +#define __JIN_CANVAS_H +#include "drawable.h" +namespace jin +{ +namespace render +{ + class Canvas: public Drawable + { + public: + + Canvas(); + ~Canvas(); + + bool init(int w, int h); + + void bind(); + + static void unbind(); + + static bool hasbind(GLint fbo); + + private: + + GLuint fbo; + + // current binded fbo + static GLint cur; + }; +} +}// jin + +#endif diff --git a/src/libjin/render/color.h b/src/libjin/render/color.h new file mode 100644 index 0000000..dfb02e1 --- /dev/null +++ b/src/libjin/render/color.h @@ -0,0 +1,27 @@ +/** +* Some color operating here. +*/ +#ifndef __JIN_COLOR_H +#define __JIN_COLOR_H +#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 diff --git a/src/libjin/render/drawable.cpp b/src/libjin/render/drawable.cpp new file mode 100644 index 0000000..45d6044 --- /dev/null +++ b/src/libjin/render/drawable.cpp @@ -0,0 +1,92 @@ +#include "drawable.h" +#include "utils/matrix.h" +#include <stdlib.h> +namespace jin +{ +namespace render +{ + Drawable::Drawable():texture(0), width(0), height(0), ancx(0), ancy(0), textCoord(0), vertCoord(0) + { + } + + Drawable::~Drawable() + { + glDeleteTextures(1, &texture); + delete[] vertCoord; + delete[] textCoord; + } + + void Drawable::init(int w, int h) + { + texture = 0; + width = w; + height = h; + ancx = 0; + ancy = 0; + textCoord = 0; + vertCoord = 0; + } + + 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; + } + + int Drawable::getWidth() + { + return width; + } + + int Drawable::getHeight() + { + return height; + } + + 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::util::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); + } +} +} diff --git a/src/libjin/render/drawable.h b/src/libjin/render/drawable.h new file mode 100644 index 0000000..5eaf705 --- /dev/null +++ b/src/libjin/render/drawable.h @@ -0,0 +1,47 @@ +#ifndef __JIN_DRAWABLE +#define __JIN_DRAWABLE +#include "3rdparty/GLee/GLee.h" +namespace jin +{ +namespace render +{ + class Drawable + { + public: + + Drawable(); + virtual ~Drawable(); + + /* pseudo constructor*/ + void init(int w = 0, int h = 0); + + /* set anchor of texture, (0, 0) by default */ + void setAnchor(int x, int y); + + void draw(int x, int y, float sx, float sy, float r); + + int getWidth(); + int getHeight(); + + 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 diff --git a/src/libjin/render/font.cpp b/src/libjin/render/font.cpp new file mode 100644 index 0000000..287e0c0 --- /dev/null +++ b/src/libjin/render/font.cpp @@ -0,0 +1,189 @@ +#include "font.h" + +#include <stdio.h> + +#define STB_TRUETYPE_IMPLEMENTATION +#include "3rdparty/stb/stb_truetype.h" +#include "color.h" + +namespace jin +{ +namespace render +{ + +#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; + } + +} +}
\ 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..98a41b4 --- /dev/null +++ b/src/libjin/render/font.h @@ -0,0 +1,58 @@ +#ifndef __JIN_FONT_H +#define __JIN_FONT_H + +#include "drawable.h" +#include "3rdparty/stb/stb_truetype.h" +#include "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
\ 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..15d8a9c --- /dev/null +++ b/src/libjin/render/graphics.cpp @@ -0,0 +1,115 @@ +#include "graphics.h" +#include "utils/math.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); + } + } + +} +} diff --git a/src/libjin/render/graphics.h b/src/libjin/render/graphics.h new file mode 100644 index 0000000..242b19d --- /dev/null +++ b/src/libjin/render/graphics.h @@ -0,0 +1,37 @@ +#ifndef __JIN_GRAPHICS_H +#define __JIN_GRAPHICS_H + +#include "color.h" +#include "canvas.h" +#include "image.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 diff --git a/src/libjin/render/image.cpp b/src/libjin/render/image.cpp new file mode 100644 index 0000000..ac5947a --- /dev/null +++ b/src/libjin/render/image.cpp @@ -0,0 +1,97 @@ +#include "image.h" +#include "3rdparty/stb/stb_image.h" +#include "utils/utils.h" +namespace jin +{ +namespace render +{ + Image::Image(): Drawable(), pixels(0) + { + } + + Image::~Image() + { + stbi_image_free(pixels); + } + + void Image::init() + { + Drawable::init(); + pixels = 0; + } + + color Image::getPixel(int x, int y) + { + if (without(x, 0, width) || without(y, 0, height)) + { + return { 0 }; + } + return pixels[x + y * width]; + } + + bool Image::loadf(const char* f) + { + unsigned char* imageData = stbi_load(f, &width, &height, NULL, STBI_rgb_alpha); + if (imageData == 0) return false; + pixels = (color*)imageData; + + 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, imageData); + + // 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; + } + + bool Image::loadb(const char* b, int size) + { + // ʹstbi_load_from_memory + unsigned char* imageData = stbi_load_from_memory((unsigned char *)b, size, &width, &height, NULL, STBI_rgb_alpha); + if (imageData == 0) return false; + pixels = (color*)imageData; + + 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, imageData); + + // 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; + } +} +}
\ No newline at end of file diff --git a/src/libjin/render/image.h b/src/libjin/render/image.h new file mode 100644 index 0000000..7375fc4 --- /dev/null +++ b/src/libjin/render/image.h @@ -0,0 +1,34 @@ +#ifndef __JIN_IMAGE_H +#define __JIN_IMAGE_H +#include "3rdparty/GLee/GLee.h" +#include "color.h" +#include "drawable.h" +namespace jin +{ +namespace render +{ + class Image: public Drawable + { + public: + Image(); + ~Image(); + + // just like Image() + void init(); + + // load from file + bool loadf(const char* f); + + // load from memory + bool loadb(const char* b, int size); + + color getPixel(int x, int y); + + private: + + color* pixels; + }; +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/render/jsl.cpp b/src/libjin/render/jsl.cpp new file mode 100644 index 0000000..6fcee53 --- /dev/null +++ b/src/libjin/render/jsl.cpp @@ -0,0 +1,84 @@ +#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 Texel texture2D \n" + "#define extern uniform \n" + "uniform sampler2D _tex0_; \n" + "%s \n" + "void main(){ \n" + "gl_FragColor = effect(gl_Color, _tex0_, gl_TexCoord[0].xy, gl_FragCoord.xy);\n" + "}\0"; + + void JSLProgram::init(const char* program) + { + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &_max_texture_units); + + 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); + } + + shared std::map<std::string, GLint> JSLProgram::_texture_unit_pool; + shared GLint JSLProgram::_current_texture_unit = 0; + shared GLint JSLProgram::_max_texture_units = 0; + + shared GLint JSLProgram::getTextureUnit(const std::string& name) + { + std::map<std::string, GLint>::const_iterator it = _texture_unit_pool.find(name); + + if (it != _texture_unit_pool.end()) + return it->second; + + if (++_current_texture_unit >= _max_texture_units) + return 0; + + _texture_unit_pool[name] = _current_texture_unit; + return _current_texture_unit; + } + + void JSLProgram::use() + { + glUseProgram(pid); + } + + shared void JSLProgram::unuse() + { + glUseProgram(0); + } + + void JSLProgram::sendFloat(const char* variable, float number) + { + int loc = glGetUniformLocation(pid, variable); + glUniform1f(loc, number); + } + + void JSLProgram::sendImage(const char* variable, const Image* image) + { + GLint texture_unit = getTextureUnit(variable); + + GLint location = glGetUniformLocation(pid, variable); + + glActiveTexture(GL_TEXTURE0 + texture_unit); + glBindTexture(GL_TEXTURE_2D, image->getTexture()); // guarantee it gets bound + glUniform1i(location, texture_unit); + + // reset texture unit + glActiveTexture(GL_TEXTURE0); + } + +} +} diff --git a/src/libjin/render/jsl.h b/src/libjin/render/jsl.h new file mode 100644 index 0000000..570235b --- /dev/null +++ b/src/libjin/render/jsl.h @@ -0,0 +1,44 @@ +#ifndef __JIN_JSL_H +#define __JIN_JSL_H +#include <string> +#include <map> +#include "image.h" +#include "3rdparty/GLee/GLee.h" +namespace jin +{ +namespace render +{ + /** + * A JSL program for shadering textures which is + * actually a glsl program. + */ + class JSLProgram + { + public: + + void init(const char* program); + + void use(); + + static void unuse(); + + void sendFloat(const char* name, float number); + void sendImage(const char* name, const Image* image); + //void sendMatrix(const char* name, int size, const GLfloat* m, int count); + //void sendCanvas(const char* name, const Canvas& canvas); + + private: + JSLProgram(); + + // only id for identify glsl program + GLuint pid; + + static GLint _current_texture_unit; + static GLint _max_texture_units; + static std::map<std::string, GLint> _texture_unit_pool; + static GLint getTextureUnit(const std::string& name); + }; +} +} + +#endif diff --git a/src/libjin/render/quad.h b/src/libjin/render/quad.h new file mode 100644 index 0000000..3ae4cc4 --- /dev/null +++ b/src/libjin/render/quad.h @@ -0,0 +1,17 @@ +#ifndef __JIN_QUAD_H +#define __JIN_QUAD_H + +namespace jin +{ +namespace render +{ + + struct Quad + { + float x, y, w, h; + }; + +} +} + +#endif // !__JIN_RENDER_QUAD_H diff --git a/src/libjin/render/rect.h b/src/libjin/render/rect.h new file mode 100644 index 0000000..56b5bd1 --- /dev/null +++ b/src/libjin/render/rect.h @@ -0,0 +1,12 @@ +#ifndef __JIN_RECT_H +#define __JIN_RECT_H + +namespace jin +{ +class Rect +{ +public: + int x, y, w, h; +}; +}// jin +#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..20a6adc --- /dev/null +++ b/src/libjin/render/window.cpp @@ -0,0 +1,83 @@ +#include "window.h" +#include "3rdparty/GLee/GLee.h" +#include "canvas.h" +#include "utils/macros.h" +namespace jin +{ +namespace render +{ + + shared Window* Window::g_wnd = 0; + + Window::Window(): wnd(0), ctx(0) + { + } + + Window::~Window() + { + } + + void Window::init(int pw, int ph, const char* t) + { + w = pw; + h = ph; + + if (wnd) + { + SDL_DestroyWindow(wnd); + SDL_FlushEvent(SDL_WINDOWEVENT); + } + + 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); + + Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL ; + + int wx = SDL_WINDOWPOS_UNDEFINED, + wy = SDL_WINDOWPOS_UNDEFINED; + + /* Create window */ + wnd = SDL_CreateWindow(t, wx, wy, w, h, flags); + + // Create an opengl context + ctx = SDL_GL_CreateContext(wnd); + SDL_GL_MakeCurrent(wnd, ctx); + + // Default clear color + glClearColor(0.f, 0.f, 0.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + // Default render color + glColor4f(1, 1, 1, 1); + + /** + * Set the viewport to top-left corner. + * Bind to the default render buffer. + */ + Canvas::unbind(); + + // Swap window buffer + swapBuffers(); + } + + SDL_Window* Window::getWnd() + { + return wnd; + } + + SDL_GLContext Window::getCtx() + { + return ctx; + } + +} +}
\ 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..f29c82d --- /dev/null +++ b/src/libjin/render/window.h @@ -0,0 +1,53 @@ +#ifndef __JIN_RENDER_WINDOW +#define __JIN_RENDER_WINDOW +#include "SDL2/SDL.h" +namespace jin +{ +namespace render +{ + class Window + { + public: + + void init(int w, int h, const char* t); + + SDL_Window* getWnd(); + + SDL_GLContext getCtx(); + + static inline Window* get() + { + return (g_wnd ? g_wnd : (g_wnd = new Window())); + } + + inline int Window::getW() + { + return w; + } + + inline int Window::getH() + { + return h; + } + + inline void Window::swapBuffers() + { + if (wnd) + SDL_GL_SwapWindow(wnd); + } + private: + + Window(); + ~Window(); + + static Window* g_wnd; + + SDL_Window* wnd; + + SDL_GLContext ctx; + + int w, h; + }; +} +} +#endif
\ No newline at end of file |