first stable version OK
This commit is contained in:
parent
a5213c552a
commit
d92247535f
|
@ -1,2 +1,7 @@
|
|||
build
|
||||
.vscode
|
||||
testExecutor
|
||||
install
|
||||
TODO.txt
|
||||
.cache
|
||||
compile_flags.txt
|
|
@ -0,0 +1,2 @@
|
|||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
project(HazelLuaEngine
|
||||
VERSION 0.1.0
|
||||
DESCRIPTION "a tiny engine made with C and Lua for 1MGames"
|
||||
|
@ -15,17 +13,35 @@ set(HAZEL_LUA_BRIDGE_NAME hazel)
|
|||
include(cmake/FindLua.cmake)
|
||||
include(cmake/FindGLFW.cmake)
|
||||
include(cmake/FindGLAD.cmake)
|
||||
include(cmake/FindSTB.cmake)
|
||||
|
||||
# hazel
|
||||
# hazel-core
|
||||
aux_source_directory(src HAZEL_SRC)
|
||||
add_library(${HAZEL_CORE_NAME} STATIC ${HAZEL_SRC})
|
||||
target_link_libraries(${HAZEL_CORE_NAME} PUBLIC glad glfw)
|
||||
add_library(${HAZEL_CORE_NAME} SHARED ${HAZEL_SRC})
|
||||
target_link_libraries(${HAZEL_CORE_NAME} PUBLIC glad glfw stb_image)
|
||||
target_include_directories(${HAZEL_CORE_NAME} PUBLIC .)
|
||||
target_compile_features(${HAZEL_CORE_NAME} PUBLIC c_std_11)
|
||||
target_precompile_headers(${HAZEL_CORE_NAME} PUBLIC hazel/pch.h)
|
||||
|
||||
if(WIN32)
|
||||
target_compile_definitions(${HAZEL_CORE_NAME} PUBLIC WIN32)
|
||||
endif(WIN32)
|
||||
elseif(APPLE)
|
||||
target_compile_definitions(${HAZEL_CORE_NAME} PUBLIC APPLE)
|
||||
endif()
|
||||
|
||||
# sandbox
|
||||
# lua
|
||||
add_subdirectory(binding/lua)
|
||||
|
||||
# test
|
||||
add_subdirectory(test)
|
||||
|
||||
# install
|
||||
install(
|
||||
TARGETS ${HAZEL_LUA_BRIDGE_NAME} lua ${HAZEL_EXECUTOR_NAME} ${HAZEL_CORE_NAME}
|
||||
DESTINATION ${CMAKE_SOURCE_DIR}/install
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY shader
|
||||
DESTINATION ${CMAKE_SOURCE_DIR}/install
|
||||
)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
add_library(${HAZEL_LUA_BRIDGE_NAME} SHARED bridge.c)
|
||||
target_link_libraries(${HAZEL_LUA_BRIDGE_NAME} PUBLIC ${HAZEL_CORE_NAME} lua)
|
||||
target_precompile_headers(${HAZEL_LUA_BRIDGE_NAME} REUSE_FROM ${HAZEL_CORE_NAME})
|
||||
|
||||
add_executable(${HAZEL_EXECUTOR_NAME} executor.c)
|
||||
target_link_libraries(${HAZEL_EXECUTOR_NAME} PUBLIC lua)
|
||||
target_link_libraries(${HAZEL_EXECUTOR_NAME} PUBLIC lua ${HAZEL_CORE_NAME})
|
||||
|
|
|
@ -4,18 +4,182 @@
|
|||
#include "luaconf.h"
|
||||
|
||||
#include "hazel/hazel.h"
|
||||
#include "hazel/renderer.h"
|
||||
|
||||
static int LuaBridge_RunExampleWindow(lua_State* L) {
|
||||
Hazel_RunExampleWindow();
|
||||
static int LuaBridge_RenderSetClearColor(lua_State* L) {
|
||||
float r = luaL_checknumber(L, 1);
|
||||
float g = luaL_checknumber(L, 2);
|
||||
float b = luaL_checknumber(L, 3);
|
||||
float a = luaL_checknumber(L, 4);
|
||||
Hazel_RenderSetClearColor(r, g, b, a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg hazel[] = {
|
||||
{"RunExampleWindow", LuaBridge_RunExampleWindow},
|
||||
static int LuaBridge_SayHello(lua_State* L) {
|
||||
printf("Hello Hazel\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_RenderClear(lua_State* L) {
|
||||
Hazel_RenderClear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_RenderSetDrawColor(lua_State* L) {
|
||||
float r = luaL_checknumber(L, 1);
|
||||
float g = luaL_checknumber(L, 2);
|
||||
float b = luaL_checknumber(L, 3);
|
||||
float a = luaL_checknumber(L, 4);
|
||||
Hazel_RenderSetDrawColor(r, g, b, a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_RenderDrawLine(lua_State* L) {
|
||||
float x1 = luaL_checknumber(L, 1);
|
||||
float y1 = luaL_checknumber(L, 2);
|
||||
float x2 = luaL_checknumber(L, 3);
|
||||
float y2 = luaL_checknumber(L, 4);
|
||||
Hazel_RenderDrawLine(x1, y1, x2, y2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_RenderDrawRect(lua_State* L) {
|
||||
float x = luaL_checknumber(L, 1);
|
||||
float y = luaL_checknumber(L, 2);
|
||||
float w = luaL_checknumber(L, 3);
|
||||
float h = luaL_checknumber(L, 4);
|
||||
Hazel_RenderDrawRect(x, y, w, h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_RenderFillRect(lua_State* L) {
|
||||
float x = luaL_checknumber(L, 1);
|
||||
float y = luaL_checknumber(L, 2);
|
||||
float w = luaL_checknumber(L, 3);
|
||||
float h = luaL_checknumber(L, 4);
|
||||
Hazel_RenderFillRect(x, y, w, h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_LoadTexture(lua_State* L) {
|
||||
const char* filename = luaL_checkstring(L, 1);
|
||||
Hazel_Texture* texture = Hazel_LoadTexture(filename);
|
||||
lua_pushlightuserdata(L, texture);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaBridge_DestroyTexture(lua_State* L) {
|
||||
Hazel_Texture* texture = (Hazel_Texture*)lua_topointer(L, 1);
|
||||
Hazel_DestroyTexture(texture);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_TextureGetSize(lua_State* L) {
|
||||
Hazel_Texture* texture = (Hazel_Texture*)lua_topointer(L, 1);
|
||||
int w, h;
|
||||
Hazel_TextureGetSize(texture, &w, &h);
|
||||
lua_pushnumber(L, w);
|
||||
lua_pushnumber(L, h);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int LuaBridge_RenderDrawTexture(lua_State* L) {
|
||||
Hazel_Texture* texture = (Hazel_Texture*)lua_topointer(L, 1);
|
||||
int rx = luaL_checknumber(L, 2);
|
||||
int ry = luaL_checknumber(L, 3);
|
||||
int rw = luaL_checknumber(L, 4);
|
||||
int rh = luaL_checknumber(L, 5);
|
||||
int dx = luaL_checknumber(L, 6);
|
||||
int dy = luaL_checknumber(L, 7);
|
||||
int dw = luaL_checknumber(L, 8);
|
||||
int dh = luaL_checknumber(L, 9);
|
||||
Hazel_RenderFlip flip = luaL_checknumber(L, 10);
|
||||
Hazel_RenderDrawTexture(texture, rx, ry, rw, rh, dx, dy, dw, dh, flip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_GetCanvaSize(lua_State* L) {
|
||||
int w, h;
|
||||
Hazel_GetCanvaSize(&w, &h);
|
||||
lua_pushnumber(L, w);
|
||||
lua_pushnumber(L, h);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int LuaBridge_WindowSetIcon(lua_State* L) {
|
||||
const char* filename = luaL_checkstring(L, 1);
|
||||
Hazel_WindowSetIcon(filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_GetKeyState(lua_State* L) {
|
||||
int key = luaL_checkinteger(L, 1);
|
||||
lua_pushnumber(L, Hazel_GetKeyState(key));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaBridge_GetMousePos(lua_State* L) {
|
||||
double x, y;
|
||||
Hazel_GetMousePos(&x, &y);
|
||||
lua_pushnumber(L, x);
|
||||
lua_pushnumber(L, y);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int LuaBridge_GetMouseButtonState(lua_State* L) {
|
||||
int btn = luaL_checknumber(L, 1);
|
||||
lua_pushnumber(L, Hazel_GetMouseBtnState(btn));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaBridge_GetTime(lua_State* L) {
|
||||
lua_pushnumber(L, Hazel_GetTime());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaBridge_GetWindowSize(lua_State* L) {
|
||||
int w, h;
|
||||
Hazel_WindowGetSize(&w, &h);
|
||||
lua_pushnumber(L, w);
|
||||
lua_pushnumber(L, h);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int LuaBridge_HideCursor() {
|
||||
Hazel_HideCursor();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaBridge_ShowCursor() {
|
||||
Hazel_ShowCursor();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg libhazel[] = {
|
||||
{"RenderSetClearColor", LuaBridge_RenderSetClearColor},
|
||||
{"RenderSetDrawColor", LuaBridge_RenderSetDrawColor},
|
||||
{"RenderClear", LuaBridge_RenderClear},
|
||||
{"RenderDrawLine", LuaBridge_RenderDrawLine},
|
||||
{"RenderDrawRect", LuaBridge_RenderDrawRect},
|
||||
{"RenderFillRect", LuaBridge_RenderFillRect},
|
||||
{"RenderDrawTexture", LuaBridge_RenderDrawTexture},
|
||||
{"TextureGetSize", LuaBridge_TextureGetSize},
|
||||
{"LoadTexture", LuaBridge_LoadTexture},
|
||||
{"DestroyTexture", LuaBridge_DestroyTexture},
|
||||
{"GetCanvaSize", LuaBridge_GetCanvaSize},
|
||||
{"WindowSetIcon", LuaBridge_WindowSetIcon},
|
||||
{"GetTime", LuaBridge_GetTime},
|
||||
{"GetWindowSize", LuaBridge_GetWindowSize},
|
||||
{"GetMousePos", LuaBridge_GetMousePos},
|
||||
{"GetMouseButtonState", LuaBridge_GetMouseButtonState},
|
||||
{"GetKeyState", LuaBridge_GetKeyState},
|
||||
{"HideCursor", LuaBridge_HideCursor},
|
||||
{"ShowCursor", LuaBridge_ShowCursor},
|
||||
{"SayHello", LuaBridge_SayHello},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
DLLEXPORT int luaopen_hazel(lua_State* L) {
|
||||
luaL_newlib(L, hazel);
|
||||
DLLEXPORT int luaopen_libhazel(lua_State* L) {
|
||||
luaL_newlib(L, libhazel);
|
||||
return 1;
|
||||
}
|
|
@ -2,19 +2,184 @@
|
|||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
int main() {
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "hazel/hazel.h"
|
||||
|
||||
typedef struct {
|
||||
int WindowWidth;
|
||||
int WindowHeight;
|
||||
char WindowTitle[1024];
|
||||
char LuaEntryFile[1024];
|
||||
} Config;
|
||||
|
||||
int getNumber(lua_State* L, const char* name, int* num) {
|
||||
int isnum;
|
||||
lua_getglobal(L, name);
|
||||
*num = (int)lua_tointegerx(L, -1, &isnum);
|
||||
if (!isnum) {
|
||||
printf("Please check your %s field", name);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int getString(lua_State* L, const char* name, char* str) {
|
||||
lua_getglobal(L, name);
|
||||
const char* s = lua_tostring(L, -1);
|
||||
if (!s) {
|
||||
printf("Please check your %s filed", name);
|
||||
lua_close(L);
|
||||
return 0;
|
||||
}
|
||||
strcpy(str, s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* LuaConfigFileTemplate =
|
||||
"WindowWidth = 800\n"
|
||||
"WindowHeight = 600\n"
|
||||
"Title = \"LuaTinyEngine\"\n"
|
||||
"EntryFile = \"main.lua\"";
|
||||
|
||||
void createLuaConfigFile() {
|
||||
FILE* file = fopen("config.lua", "w+");
|
||||
if (!file) {
|
||||
printf("can't open file config.lua");
|
||||
return ;
|
||||
}
|
||||
fputs(LuaConfigFileTemplate, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
const char* LuaEntryFileTemplate =
|
||||
"local hazel = require \"hazel\"\n"
|
||||
"\n"
|
||||
"function GameStart()\n"
|
||||
" hazel.SayHello()\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function GameLoop()\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function GameQuit()\n"
|
||||
"end";
|
||||
|
||||
void createLuaEntryFile() {
|
||||
FILE* file = fopen("main.lua", "w+");
|
||||
if (!file) {
|
||||
printf("can't open file main.lua");
|
||||
return ;
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
long size = ftell(file);
|
||||
if (size <= 0) {
|
||||
fputs(LuaEntryFileTemplate, file);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
int ReadConfig(Config* config) {
|
||||
if (!config) {
|
||||
printf("please give me a valid config");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_State* L = luaL_newstate();
|
||||
if (!L) {
|
||||
printf("Fatal Error, create lua stack failed");
|
||||
return 1;
|
||||
}
|
||||
if (luaL_loadfile(L, "config.lua") != 0) {
|
||||
printf("You don't have a config.lua, create one for you.Modify it to your config.");
|
||||
createLuaConfigFile();
|
||||
goto ERR_HANDLE;
|
||||
}
|
||||
if (lua_pcall(L, 0, 0, 0) != 0) {
|
||||
printf("pcall config file failed");
|
||||
goto ERR_HANDLE;
|
||||
}
|
||||
|
||||
if (!getNumber(L, "WindowWidth", &config->WindowWidth)) {
|
||||
goto ERR_HANDLE;
|
||||
}
|
||||
if (!getNumber(L, "WindowHeight", &config->WindowHeight)) {
|
||||
goto ERR_HANDLE;
|
||||
}
|
||||
if (!getString(L, "Title", config->WindowTitle)) {
|
||||
goto ERR_HANDLE;
|
||||
}
|
||||
if (!getString(L, "EntryFile", config->LuaEntryFile)) {
|
||||
goto ERR_HANDLE;
|
||||
}
|
||||
|
||||
lua_close(L);
|
||||
return 1;
|
||||
|
||||
ERR_HANDLE:
|
||||
lua_close(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_State* L = NULL;
|
||||
|
||||
void GameStart() {
|
||||
lua_getglobal(L, "GameStart");
|
||||
if (lua_pcall(L, 0, 0, 0)) {
|
||||
GAME_LOG_ERROR("call GameStart function in lua failed");
|
||||
const char* error = luaL_checkstring(L, -1);
|
||||
GAME_LOG_ERROR("[Lua Error]: %s", error);
|
||||
}
|
||||
}
|
||||
|
||||
void GameLoop() {
|
||||
lua_getglobal(L, "GameLoop");
|
||||
if (lua_pcall(L, 0, 0, 0)) {
|
||||
GAME_LOG_ERROR("call GameLoop function in lua failed");
|
||||
const char* error = luaL_checkstring(L, -1);
|
||||
GAME_LOG_ERROR("[Lua Error]: %s", error);
|
||||
}
|
||||
}
|
||||
|
||||
void GameQuit() {
|
||||
lua_getglobal(L, "GameQuit");
|
||||
if (lua_pcall(L, 0, 0, 0)) {
|
||||
GAME_LOG_ERROR("call GameQuit function in lua failed");
|
||||
const char* error = luaL_checkstring(L, -1);
|
||||
GAME_LOG_ERROR("[Lua Error]: %s", error);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
Config config;
|
||||
if (!ReadConfig(&config)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
L = luaL_newstate();
|
||||
if (!L) {
|
||||
printf("lua init failed\n");
|
||||
return 1;
|
||||
}
|
||||
luaL_openlibs(L);
|
||||
|
||||
if (luaL_loadfile(L, "main.lua") || lua_pcall(L, 0, 0, 0)) {
|
||||
printf("main.lua load and execute failed\n");
|
||||
if (luaL_loadfile(L, config.LuaEntryFile)) {
|
||||
createLuaEntryFile();
|
||||
ENGINE_LOG_CRITICAL("%s load and execute failed, create main.lua for you\n", config.LuaEntryFile);
|
||||
}
|
||||
|
||||
if (lua_pcall(L, 0, 0, 0)) {
|
||||
ENGINE_LOG_ERROR("[Lua Error]: %s", luaL_checkstring(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
Hazel_Init(config.WindowTitle, config.WindowWidth, config.WindowHeight);
|
||||
Hazel_RegistGameFuncs(GameStart, GameLoop, GameQuit);
|
||||
|
||||
Hazel_Run();
|
||||
|
||||
Hazel_Quit();
|
||||
lua_close(L);
|
||||
return 0;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
---@class hazel
|
||||
---@field RunExampleWindow function
|
||||
local hazel = require "hazel"
|
||||
|
||||
hazel.RunExampleWindow()
|
|
@ -33,7 +33,7 @@ set(LUA_SRC
|
|||
3rdlibs/lua/src/linit.c
|
||||
)
|
||||
|
||||
add_library(lua STATIC ${LUA_SRC})
|
||||
add_library(lua SHARED ${LUA_SRC})
|
||||
target_include_directories(lua PUBLIC ./3rdlibs/lua/src)
|
||||
target_compile_features(lua PRIVATE c_std_99)
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
add_library(stb_image STATIC 3rdlibs/stb/stb_image.c)
|
||||
target_include_directories(stb_image PUBLIC 3rdlibs/stb)
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __HAZEL_DLLEXPORT_H__
|
||||
#define __HAZEL_DLLEXPORT_H__
|
||||
|
||||
#ifdef WIN32
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLLEXPORT
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef __HAZEL_GLHELPER_H__
|
||||
#define __HAZEL_GLHELPER_H__
|
||||
|
||||
#include "glad/glad.h"
|
||||
|
||||
#define TRY_GET_GL_ERROR_MAX_LOOP 10000
|
||||
|
||||
const char* GLGetErrorString(GLenum);
|
||||
|
||||
void GLClearError();
|
||||
|
||||
#define GL_CALL(statement) do { \
|
||||
GLClearError(); \
|
||||
statement; \
|
||||
GLenum ___err_inner_use = glGetError(); \
|
||||
if (___err_inner_use != GL_NO_ERROR) { GL_LOG_ERROR("%s", GLGetErrorString(___err_inner_use)); } \
|
||||
} while(0)
|
||||
|
||||
#endif
|
|
@ -2,7 +2,28 @@
|
|||
#define __HAZEL_HAZEL_H__
|
||||
|
||||
#include "pch.h"
|
||||
#include "window.h"
|
||||
#include "renderer.h"
|
||||
|
||||
DLLEXPORT void Hazel_RunExampleWindow();
|
||||
typedef void(*Hazel_BeforeGameStartFunc)(void);
|
||||
typedef void(*Hazel_GameLoopFunc)(void);
|
||||
typedef void(*Hazel_BeforeGameQuitFunc)(void);
|
||||
typedef void(*Hazel_KeyInputFunc)(GLFWwindow*, int, int, int, int);
|
||||
typedef void(*Hazel_MousePosInputFunc)(GLFWwindow*, double, double);
|
||||
typedef void(*Hazel_MouseButtonInputFunc)(GLFWwindow*, int, int , int);
|
||||
|
||||
DLLEXPORT void Hazel_Init(const char* title, int w, int h);
|
||||
DLLEXPORT void Hazel_Quit();
|
||||
DLLEXPORT int Hazel_ShouldClose();
|
||||
DLLEXPORT void Hazel_Run();
|
||||
DLLEXPORT void Hazel_RegistGameFuncs(Hazel_BeforeGameStartFunc, Hazel_GameLoopFunc, Hazel_BeforeGameQuitFunc);
|
||||
DLLEXPORT void Hazel_RegistInputFuncs(Hazel_KeyInputFunc, Hazel_MousePosInputFunc, Hazel_MouseButtonInputFunc);
|
||||
DLLEXPORT int Hazel_GetKeyState(int key);
|
||||
DLLEXPORT int Hazel_GetMouseBtnState(int btn);
|
||||
DLLEXPORT void Hazel_SetCursorPos(double x, double y);
|
||||
DLLEXPORT void Hazel_GetMousePos(double* x, double* y);
|
||||
DLLEXPORT double Hazel_GetTime();
|
||||
DLLEXPORT void Hazel_HideCursor();
|
||||
DLLEXPORT void Hazel_ShowCursor();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "dllexport.h"
|
||||
|
||||
DLLEXPORT const char* GetFilename(const char* fullpath);
|
||||
|
||||
#define ENGINE_LOG_CRITICAL(fmt, ...) do {printf("[Engine Critical][%d]%s - %s]: " fmt "\n", __LINE__, GetFilename(__FILE__), __FUNCTION__, ##__VA_ARGS__); fflush(stdout), exit(1); } while(0)
|
||||
#define ENGINE_LOG_ERROR(fmt, ...) do {printf("[Engine Error][%d][%s - %s]: " fmt "\n", __LINE__, GetFilename(__FILE__), __FUNCTION__, ##__VA_ARGS__); fflush(stdout); } while(0)
|
||||
#define ENGINE_LOG_INFO(fmt, ...) do {printf("[Engine Info][%d][%s - %s]: " fmt "\n", __LINE__, GetFilename(__FILE__), __FUNCTION__, ##__VA_ARGS__); fflush(stdout); } while(0)
|
||||
#define ENGINE_LOG_WARN(fmt, ...) do {printf("[Engine Warn][%d][%s - %s]: " fmt "\n", __LINE__, GetFilename(__FILE__), __FUNCTION__, ##__VA_ARGS__); fflush(stdout); } while(0)
|
||||
#define ENGINE_LOG_DEBUG(fmt, ...) do {printf("[Engine Debug][%d][%s - %s]: " fmt "\n", __LINE__, GetFilename(__FILE__), __FUNCTION__, ##__VA_ARGS__); fflush(stdout); } while(0)
|
||||
|
||||
#define GL_LOG_CRITICAL(fmt, ...) do {printf("[GL Critical][%d][%s - %s]: " fmt "\n", __LINE__, GetFilename(__FILE__), __FUNCTION__, ##__VA_ARGS__); fflush(stdout); exit(1); } while(0)
|
||||
#define GL_LOG_ERROR(fmt, ...) do {printf("[GL Error][%d][%s - %s]: " fmt "\n", __LINE__, __FUNCTION__, GetFilename(__FILE__), ##__VA_ARGS__); fflush(stdout);} while(0)
|
||||
#define GL_LOG_INFO(fmt, ...) do {printf("[GL Info][%d][%s - %s]: " fmt "\n", __LINE__, __FUNCTION__, GetFilename(__FILE__), ##__VA_ARGS__); fflush(stdout);} while(0)
|
||||
#define GL_LOG_WARN(fmt, ...) do {printf("[GL Warn][%d][%s - %s]: " fmt "\n", __LINE__, __FUNCTION__, GetFilename(__FILE__), ##__VA_ARGS__); fflush(stdout);} while(0)
|
||||
#define GL_LOG_DEBUG(fmt, ...) do {printf("[GL Debug][%d][%s - %s]: " fmt "\n", __LINE__, __FUNCTION__, GetFilename(__FILE__), ##__VA_ARGS__); fflush(stdout);} while(0)
|
||||
|
||||
#define GAME_LOG_CRITICAL(fmt, ...) do {printf("[Game Critical][%d][%s - %s]: " fmt "\n", __LINE__, __FUNCTION__, ##__VA_ARGS__); fflush(stdout); } while(0)
|
||||
#define GAME_LOG_ERROR(fmt, ...) do {printf("[Game Error][%d][%s - %s]: " fmt "\n", __LINE__, __FUNCTION__, GetFilename(__FILE__), ##__VA_ARGS__); fflush(stdout);} while(0)
|
||||
#define GAME_LOG_INFO(fmt, ...) do {printf("[Game Info][%d][%s - %s]: " fmt "\n", __LINE__, __FUNCTION__, GetFilename(__FILE__), ##__VA_ARGS__); fflush(stdout);} while(0)
|
||||
#define GAME_LOG_WARN(fmt, ...) do {printf("[Game Warn][%d][%s - %s]: " fmt "\n", __LINE__, __FUNCTION__, GetFilename(__FILE__), ##__VA_ARGS__); fflush(stdout);} while(0)
|
||||
#define GAME_LOG_DEBUG(fmt, ...) do {printf("[Game Debug][%d][%s - %s]: " fmt "\n", __LINE__, __FUNCTION__, GetFilename(__FILE__), ##__VA_ARGS__); fflush(stdout);} while(0)
|
13
hazel/pch.h
13
hazel/pch.h
|
@ -4,16 +4,13 @@
|
|||
#define GLFW_INCLUDE_NONE
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
#include "glad/glad.h"
|
||||
#include "stb_image.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLLEXPORT
|
||||
#endif
|
||||
#include "log.h"
|
||||
#include "glhelper.h"
|
||||
#include "dllexport.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef __HAZEL_RENDERER_H__
|
||||
#define __HAZEL_RENDERER_H__
|
||||
|
||||
#include "pch.h"
|
||||
#include "texture.h"
|
||||
|
||||
typedef enum {
|
||||
FLIP_NONE = 0x00,
|
||||
FLIP_HORIZONTAL = 0x01,
|
||||
FLIP_VERTICAL = 0x02,
|
||||
FLIP_BOTH = FLIP_HORIZONTAL | FLIP_VERTICAL,
|
||||
} Hazel_RenderFlip;
|
||||
|
||||
DLLEXPORT void Hazel_RenderInit(int w, int h);
|
||||
DLLEXPORT void Hazel_RenderQuit();
|
||||
|
||||
DLLEXPORT void Hazel_RenderSetClearColor(float r, float g, float b, float a);
|
||||
DLLEXPORT void Hazel_RenderClear();
|
||||
DLLEXPORT void Hazel_RenderSetDrawColor(float r, float g, float b, float a);
|
||||
DLLEXPORT void Hazel_RenderSetViewport(int x, int y, int w, int h);
|
||||
|
||||
DLLEXPORT void Hazel_RenderDrawLine(int x1, int y1, int x2, int y2);
|
||||
DLLEXPORT void Hazel_RenderDrawRect(int x, int y, int w, int h);
|
||||
DLLEXPORT void Hazel_RenderFillRect(int x, int y, int w, int h);
|
||||
|
||||
DLLEXPORT void Hazel_RenderDrawTexture(Hazel_Texture *texture,
|
||||
int rx, int ry, int rw, int rh,
|
||||
int dx, int dy, int dw, int dh,
|
||||
Hazel_RenderFlip);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef __HAZEL_TEXTURE_H__
|
||||
#define __HAZEL_TEXTURE_H__
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
struct Hazel_Texture;
|
||||
typedef struct Hazel_Texture Hazel_Texture;
|
||||
|
||||
DLLEXPORT Hazel_Texture* Hazel_LoadTexture(const char* filename);
|
||||
DLLEXPORT Hazel_Texture* Hazel_CreateTexture(const unsigned char* data, int w, int h);
|
||||
DLLEXPORT void Hazel_DestroyTexture(Hazel_Texture*);
|
||||
DLLEXPORT void Hazel_TextureGetSize(Hazel_Texture*, int* w, int* h);
|
||||
DLLEXPORT void Hazel_TextureSetAlpha(Hazel_Texture*, float);
|
||||
DLLEXPORT void Hazel_TextureSetColor(Hazel_Texture*, float r, float g, float b);
|
||||
DLLEXPORT float Hazel_TextureGetAlpha(Hazel_Texture*);
|
||||
DLLEXPORT void Hazel_TextureGetColor(Hazel_Texture*, float* r, float* g, float* b);
|
||||
void Hazel_BindTexture(Hazel_Texture*);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef __HAZEL_WINDOW_H__
|
||||
#define __HAZEL_WINDOW_H__
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
extern GLFWwindow* window;
|
||||
|
||||
int Hazel_InitWindow(const char* title, int width, int height);
|
||||
DLLEXPORT void Hazel_WindowGetSize(int* w, int* h);
|
||||
DLLEXPORT void Hazel_GetCanvaSize(int* w, int* h);
|
||||
DLLEXPORT void Hazel_WindowSetIcon(const char* filename);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
#version 330 core
|
||||
|
||||
in vec2 Texcoord;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform vec4 Color;
|
||||
uniform sampler2D Texture;
|
||||
|
||||
void main() {
|
||||
FragColor = Color * texture(Texture, Texcoord);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec2 aPos;
|
||||
layout (location = 1) in vec2 aTexcoord;
|
||||
|
||||
out vec2 Texcoord;
|
||||
|
||||
uniform mat4 Project;
|
||||
|
||||
void main() {
|
||||
Texcoord = aTexcoord;
|
||||
gl_Position = Project * vec4(aPos, 0, 1);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#include "hazel/glhelper.h"
|
||||
|
||||
void GLClearError() {
|
||||
int loop = 0;
|
||||
while (loop < TRY_GET_GL_ERROR_MAX_LOOP && glGetError() != GL_NO_ERROR) { loop++; }
|
||||
}
|
||||
|
||||
#define CASE(e) case e: return #e;
|
||||
|
||||
const char* GLGetErrorString(GLenum err) {
|
||||
switch (err) {
|
||||
CASE(GL_NO_ERROR)
|
||||
CASE(GL_INVALID_ENUM)
|
||||
CASE(GL_INVALID_VALUE)
|
||||
CASE(GL_INVALID_OPERATION)
|
||||
CASE(GL_OUT_OF_MEMORY)
|
||||
CASE(GL_INVALID_FRAMEBUFFER_OPERATION)
|
||||
default:
|
||||
return "Unknown Error";
|
||||
}
|
||||
}
|
107
src/hazel.c
107
src/hazel.c
|
@ -1,37 +1,82 @@
|
|||
#include "hazel/hazel.h"
|
||||
|
||||
void Hazel_RunExampleWindow() {
|
||||
GLFWwindow* window;
|
||||
Hazel_GameLoopFunc gameLoopCallback = NULL;
|
||||
Hazel_BeforeGameStartFunc beforeGameStartCallback = NULL;
|
||||
Hazel_BeforeGameQuitFunc beforeGameQuitCallback = NULL;
|
||||
|
||||
/* Initialize the library */
|
||||
if (!glfwInit())
|
||||
return;
|
||||
|
||||
/* Create a windowed mode window and its OpenGL context */
|
||||
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
|
||||
if (!window) {
|
||||
glfwTerminate();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make the window's context current */
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
/* Use Glad to load OpenGL */
|
||||
gladLoadGL();
|
||||
|
||||
glClearColor(0.1, 0.1, 0.1, 1);
|
||||
/* Loop until the user closes the window */
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
/* Render here */
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
/* Swap front and back buffers */
|
||||
glfwSwapBuffers(window);
|
||||
|
||||
/* Poll for and process events */
|
||||
glfwPollEvents();
|
||||
}
|
||||
void Hazel_Init(const char* title, int w, int h) {
|
||||
Hazel_InitWindow(title, w, h);
|
||||
Hazel_RenderInit(w, h);
|
||||
}
|
||||
|
||||
void Hazel_Quit() {
|
||||
Hazel_RenderQuit();
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
int Hazel_ShouldClose() {
|
||||
return glfwWindowShouldClose(window);
|
||||
}
|
||||
|
||||
|
||||
void Hazel_RegistGameFuncs(Hazel_BeforeGameStartFunc before, Hazel_GameLoopFunc doing, Hazel_BeforeGameQuitFunc after) {
|
||||
beforeGameStartCallback = before;
|
||||
gameLoopCallback = doing;
|
||||
beforeGameQuitCallback = after;
|
||||
}
|
||||
|
||||
void Hazel_Run() {
|
||||
if (beforeGameStartCallback) {
|
||||
beforeGameStartCallback();
|
||||
}
|
||||
|
||||
while (!Hazel_ShouldClose()) {
|
||||
glfwPollEvents();
|
||||
|
||||
if (gameLoopCallback) {
|
||||
gameLoopCallback();
|
||||
}
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
if (beforeGameQuitCallback) {
|
||||
beforeGameQuitCallback();
|
||||
}
|
||||
}
|
||||
|
||||
double Hazel_GetTime() {
|
||||
return glfwGetTime();
|
||||
}
|
||||
|
||||
void Hazel_RegistInputFuncs(Hazel_KeyInputFunc keyInput,
|
||||
Hazel_MousePosInputFunc mousePosInput,
|
||||
Hazel_MouseButtonInputFunc mouseBtnInput) {
|
||||
glfwSetKeyCallback(window, keyInput);
|
||||
glfwSetCursorPosCallback(window, mousePosInput);
|
||||
glfwSetMouseButtonCallback(window, mouseBtnInput);
|
||||
}
|
||||
|
||||
int Hazel_GetKeyState(int key) {
|
||||
return glfwGetKey(window, key);
|
||||
}
|
||||
|
||||
void Hazel_GetMousePos(double* x, double* y) {
|
||||
glfwGetCursorPos(window, x, y);
|
||||
}
|
||||
|
||||
void Hazel_SetCursorPos(double x, double y) {
|
||||
glfwSetCursorPos(window, x, y);
|
||||
}
|
||||
|
||||
int Hazel_GetMouseBtnState(int btn) {
|
||||
return glfwGetMouseButton(window, btn);
|
||||
}
|
||||
|
||||
void Hazel_HideCursor() {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
}
|
||||
|
||||
void Hazel_ShowCursor() {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#include "hazel/log.h"
|
||||
|
||||
const char* GetFilename(const char* fullpath) {
|
||||
const char* ptr = fullpath + strlen(fullpath);
|
||||
while (*ptr != '/' && *ptr != '\\' && ptr != fullpath) ptr--;
|
||||
return ptr == fullpath ? ptr : ptr + 1;
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
#include "hazel/renderer.h"
|
||||
|
||||
struct {
|
||||
GLuint shader, vbo, vao;
|
||||
Hazel_Texture* whiteTexture;
|
||||
float currentR, currentG, currentB, currentA;
|
||||
} RenderContext;
|
||||
|
||||
void loadFile(const char* filename, char* buf) {
|
||||
FILE* file = fopen(filename, "r+");
|
||||
if (!file) {
|
||||
fclose(file);
|
||||
ENGINE_LOG_CRITICAL("shader file %s load failed", filename);
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
long len = ftell(file);
|
||||
rewind(file);
|
||||
len = fread(buf, 1, len, file);
|
||||
buf[len] = '\0';
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
GLuint createShader() {
|
||||
int bufSize = sizeof(GLchar) * 1024;
|
||||
GLchar* buf = malloc(bufSize);
|
||||
memset(buf, 0, bufSize);
|
||||
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
loadFile("shader/shader.vert", buf);
|
||||
GL_CALL(glShaderSource(vertexShader, 1, &buf, NULL));
|
||||
GL_CALL(glCompileShader(vertexShader));
|
||||
|
||||
int success;
|
||||
char infoLog[1024];
|
||||
GL_CALL(glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success));
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(vertexShader, sizeof(infoLog), NULL, infoLog);
|
||||
ENGINE_LOG_ERROR("vertex shader compile error:\n%s", infoLog);
|
||||
}
|
||||
|
||||
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
loadFile("shader/shader.frag", buf);
|
||||
GL_CALL(glShaderSource(fragShader, 1, &buf, NULL));
|
||||
GL_CALL(glCompileShader(fragShader));
|
||||
GL_CALL(glGetShaderiv(fragShader, GL_COMPILE_STATUS, &success));
|
||||
if (!success) {
|
||||
GL_CALL(glGetShaderInfoLog(fragShader, sizeof(infoLog), NULL, infoLog));
|
||||
ENGINE_LOG_ERROR("fragment shader compile error:\n%s", infoLog);
|
||||
}
|
||||
|
||||
GLuint shader = glCreateProgram();
|
||||
GL_CALL(glAttachShader(shader, vertexShader));
|
||||
GL_CALL(glAttachShader(shader, fragShader));
|
||||
GL_CALL(glLinkProgram(shader));
|
||||
|
||||
GL_CALL(glGetProgramiv(shader, GL_LINK_STATUS, &success));
|
||||
if(!success) {
|
||||
GL_CALL(glGetProgramInfoLog(shader, sizeof(infoLog), NULL, infoLog));
|
||||
ENGINE_LOG_ERROR("shader link error:\n%s", infoLog);
|
||||
}
|
||||
|
||||
GL_CALL(glDeleteShader(vertexShader));
|
||||
GL_CALL(glDeleteShader(fragShader));
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void setProjectUniform(int w, int h) {
|
||||
float left = 0, right = w, top = 0, bottom = h, near = -1, far = 1;
|
||||
float projectMat[] = {
|
||||
2 / (right - left), 0, 0, 0,
|
||||
0, 2 / (top - bottom), 0, 0,
|
||||
0, 0, 2 / (near - far), 0,
|
||||
(right + left) / (left - right), (top + bottom) / (bottom - top), (near + far) / (far - near), 1,
|
||||
};
|
||||
GLint loc = glGetUniformLocation(RenderContext.shader, "Project");
|
||||
if (loc < 0) {
|
||||
ENGINE_LOG_ERROR("shader uniform variable Project not found");
|
||||
}
|
||||
GL_CALL(glUniformMatrix4fv(loc, 1, GL_FALSE, projectMat));
|
||||
}
|
||||
|
||||
void initBuffer() {
|
||||
GL_CALL(glGenBuffers(1, &RenderContext.vbo));
|
||||
if (RenderContext.vbo == 0) {
|
||||
ENGINE_LOG_CRITICAL("vertex buffer create failed");
|
||||
}
|
||||
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, RenderContext.vbo));
|
||||
}
|
||||
|
||||
void initVertexArray() {
|
||||
GL_CALL(glGenVertexArrays(1, &RenderContext.vao));
|
||||
if (RenderContext.vao == 0) {
|
||||
ENGINE_LOG_CRITICAL("vertex array create failed");
|
||||
}
|
||||
GL_CALL(glBindVertexArray(RenderContext.vao));
|
||||
GL_CALL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0));
|
||||
GL_CALL(glEnableVertexAttribArray(0));
|
||||
GL_CALL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))));
|
||||
GL_CALL(glEnableVertexAttribArray(1));
|
||||
}
|
||||
|
||||
|
||||
void Hazel_RenderInit(int w, int h) {
|
||||
RenderContext.shader = createShader();
|
||||
|
||||
GL_CALL(glUseProgram(RenderContext.shader));
|
||||
setProjectUniform(w, h);
|
||||
|
||||
initBuffer();
|
||||
initVertexArray();
|
||||
|
||||
unsigned char data[] = {255, 255, 255, 255};
|
||||
RenderContext.whiteTexture = Hazel_CreateTexture((void*)data, 1, 1);
|
||||
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0));
|
||||
Hazel_RenderSetDrawColor(1, 1, 1, 1);
|
||||
|
||||
GL_CALL(glEnable(GL_BLEND));
|
||||
GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
|
||||
void Hazel_RenderQuit() {
|
||||
Hazel_DestroyTexture(RenderContext.whiteTexture);
|
||||
GL_CALL(glDeleteProgram(RenderContext.shader));
|
||||
GL_CALL(glDeleteBuffers(1, &RenderContext.vbo));
|
||||
GL_CALL(glDeleteVertexArrays(1, &RenderContext.vao));
|
||||
}
|
||||
|
||||
void Hazel_RenderSetClearColor(float r, float g, float b, float a) {
|
||||
GL_CALL(glClearColor(r, g, b, a));
|
||||
}
|
||||
|
||||
void Hazel_RenderSetDrawColor(float r, float g, float b, float a) {
|
||||
if (RenderContext.currentR == r &&
|
||||
RenderContext.currentG == g &&
|
||||
RenderContext.currentB == b &&
|
||||
RenderContext.currentA == a) {
|
||||
return;
|
||||
}
|
||||
GLint loc = glGetUniformLocation(RenderContext.shader, "Color");
|
||||
if (loc < 0) {
|
||||
ENGINE_LOG_ERROR("shader uniform variable Color not found");
|
||||
return;
|
||||
}
|
||||
GL_CALL(glUniform4f(loc, r, g, b, a));
|
||||
RenderContext.currentR = r;
|
||||
RenderContext.currentG = g;
|
||||
RenderContext.currentB = b;
|
||||
RenderContext.currentA = a;
|
||||
}
|
||||
|
||||
void Hazel_RenderClear() {
|
||||
GL_CALL(glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
|
||||
}
|
||||
|
||||
void Hazel_RenderSetViewport(int x, int y, int w, int h) {
|
||||
GL_CALL(glViewport(x, y, w, h));
|
||||
}
|
||||
|
||||
void Hazel_RenderDrawLine(int x1, int y1, int x2, int y2) {
|
||||
Hazel_BindTexture(RenderContext.whiteTexture);
|
||||
float vertices[] = {
|
||||
x1, y1, 0, 0,
|
||||
x2, y2, 0, 0,
|
||||
};
|
||||
GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
|
||||
GL_CALL(glDrawArrays(GL_LINES, 0, 2));
|
||||
}
|
||||
|
||||
void Hazel_RenderDrawRect(int x, int y, int w, int h) {
|
||||
Hazel_BindTexture(RenderContext.whiteTexture);
|
||||
float vertices[] = {
|
||||
x, y, 0, 0,
|
||||
x + w, y, 0, 0,
|
||||
x + w, y + h, 0, 0,
|
||||
x, y + h, 0, 0,
|
||||
};
|
||||
GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
|
||||
GL_CALL(glDrawArrays(GL_LINE_LOOP, 0, 4));
|
||||
}
|
||||
|
||||
void Hazel_RenderFillRect(int x, int y, int w, int h) {
|
||||
Hazel_BindTexture(RenderContext.whiteTexture);
|
||||
float vertices[] = {
|
||||
x, y, 0, 0,
|
||||
x + w, y, 0, 0,
|
||||
x + w, y + h, 0, 0,
|
||||
|
||||
x, y, 0, 0,
|
||||
x + w, y + h, 0, 0,
|
||||
x, y + h, 0, 0,
|
||||
};
|
||||
GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
|
||||
GL_CALL(glDrawArrays(GL_TRIANGLES, 0, 6));
|
||||
}
|
||||
|
||||
void swap(float* v1, float* v2) {
|
||||
float tmp = *v1;
|
||||
*v1 = *v2;
|
||||
*v2 = tmp;
|
||||
}
|
||||
|
||||
void Hazel_RenderDrawTexture(Hazel_Texture* texture,
|
||||
int rx, int ry, int rw, int rh,
|
||||
int dx, int dy, int dw, int dh,
|
||||
Hazel_RenderFlip flip) {
|
||||
if (!texture) return;
|
||||
float r, g, b, a = Hazel_TextureGetAlpha(texture);
|
||||
Hazel_TextureGetColor(texture, &r, &g, &b);
|
||||
Hazel_RenderSetDrawColor(r, g, b, a);
|
||||
Hazel_BindTexture(texture);
|
||||
|
||||
int w, h;
|
||||
Hazel_TextureGetSize(texture, &w, &h);
|
||||
float p1x = dx, p1y = dy,
|
||||
p2x = dx + dw, p2y = dy,
|
||||
p3x = dx + dw, p3y = dy + dh,
|
||||
p4x = dx, p4y = dy + dh;
|
||||
if (flip & FLIP_HORIZONTAL) {
|
||||
swap(&p1x, &p2x);
|
||||
swap(&p3x, &p4x);
|
||||
}
|
||||
if (flip & FLIP_VERTICAL) {
|
||||
swap(&p1y, &p3y);
|
||||
swap(&p2y, &p4y);
|
||||
}
|
||||
float vertices[] = {
|
||||
p1x, p1y, rx / (float)w, ry / (float)h,
|
||||
p2x, p2y, (rx + rw) / (float)w, ry / (float)h,
|
||||
p3x, p3y, (rx + rw) / (float)w, (ry + rh) / (float)h,
|
||||
|
||||
p1x, p1y, rx / (float)w, ry / (float)h,
|
||||
p3x, p3y, (rx + rw) / (float)w, (ry + rh) / (float)h,
|
||||
p4x, p4y, rx / (float)w, (ry + rh) / (float)h,
|
||||
};
|
||||
GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
|
||||
GL_CALL(glDrawArrays(GL_TRIANGLES, 0, 6));
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#include "hazel/texture.h"
|
||||
|
||||
struct Hazel_Texture {
|
||||
GLuint id;
|
||||
int w;
|
||||
int h;
|
||||
float r, g, b, a;
|
||||
};
|
||||
|
||||
Hazel_Texture* Hazel_LoadTexture(const char* filename) {
|
||||
int w, h, channel;
|
||||
unsigned char* data = stbi_load(filename, &w, &h, &channel, 4);
|
||||
if (!data) {
|
||||
ENGINE_LOG_ERROR("load %s failed", filename);
|
||||
return NULL;
|
||||
}
|
||||
Hazel_Texture* texture = Hazel_CreateTexture(data, w, h);
|
||||
stbi_image_free(data);
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Hazel_TextureSetAlpha(Hazel_Texture* texture, float alpha) {
|
||||
if (!texture) return;
|
||||
texture->a = alpha;
|
||||
}
|
||||
|
||||
void Hazel_TextureSetColor(Hazel_Texture* texture, float r, float g, float b) {
|
||||
if (!texture) return;
|
||||
texture->r = r;
|
||||
texture->g = g;
|
||||
texture->b = b;
|
||||
}
|
||||
|
||||
Hazel_Texture* Hazel_CreateTexture(const unsigned char* data, int w, int h) {
|
||||
Hazel_Texture* result = (Hazel_Texture*)malloc(sizeof(Hazel_Texture));
|
||||
result->w = w;
|
||||
result->h = h;
|
||||
result->r = 1;
|
||||
result->g = 1;
|
||||
result->b = 1;
|
||||
result->a = 1;
|
||||
GL_CALL(glGenTextures(1, &result->id));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, result->id));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data));
|
||||
return result;
|
||||
}
|
||||
|
||||
void Hazel_DestroyTexture(Hazel_Texture* texture) {
|
||||
if (texture) {
|
||||
GL_CALL(glDeleteTextures(1, &texture->id));
|
||||
free(texture);
|
||||
}
|
||||
}
|
||||
|
||||
void Hazel_TextureGetSize(Hazel_Texture* texture, int* w, int* h) {
|
||||
if (texture) {
|
||||
if (w) *w = texture->w;
|
||||
if (h) *h = texture->h;
|
||||
} else {
|
||||
if (w) *w = 0;
|
||||
if (h) *h = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Hazel_BindTexture(Hazel_Texture* texture) {
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, texture ? texture->id : 0));
|
||||
}
|
||||
|
||||
float Hazel_TextureGetAlpha(Hazel_Texture* texture) {
|
||||
return texture ? texture->a : -1;
|
||||
}
|
||||
|
||||
void Hazel_TextureGetColor(Hazel_Texture* texture, float* r, float* g, float* b) {
|
||||
if (texture) {
|
||||
if (r) *r = texture->r;
|
||||
if (g) *g = texture->g;
|
||||
if (b) *b = texture->b;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
#include "hazel/window.h"
|
||||
|
||||
GLFWwindow* window = NULL;
|
||||
int canvaW = 0, canvaH = 0;
|
||||
|
||||
void Hazel_GetCanvaSize(int* w, int* h) {
|
||||
if (w) *w = canvaW;
|
||||
if (h) *h = canvaH;
|
||||
}
|
||||
|
||||
void windowResizeCallback(GLFWwindow* window, int width, int height) {
|
||||
GL_CALL(glViewport(0, 0, width, height));
|
||||
}
|
||||
|
||||
int Hazel_InitWindow(const char* title, int width, int height) {
|
||||
if (!glfwInit()) {
|
||||
GAME_LOG_CRITICAL("glfw init failed");
|
||||
return 0;
|
||||
}
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
#ifdef APPLE
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
#endif
|
||||
|
||||
window = glfwCreateWindow(width, height, title, NULL, NULL);
|
||||
if (!window) {
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
canvaW = width;
|
||||
canvaH = height;
|
||||
|
||||
GAME_LOG_INFO("window create OK");
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
gladLoadGL();
|
||||
GL_CALL(glViewport(0, 0, width, height));
|
||||
glfwSetFramebufferSizeCallback(window, windowResizeCallback);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Hazel_WindowGetSize(int* w, int* h) {
|
||||
glfwGetWindowSize(window, w, h);
|
||||
}
|
||||
|
||||
void Hazel_WindowSetIcon(const char* filename) {
|
||||
GLFWimage icon;
|
||||
int channel;
|
||||
icon.pixels = stbi_load(filename, &icon.width, &icon.height, &channel, 0);
|
||||
if (!icon.pixels) {
|
||||
ENGINE_LOG_ERROR("icon %s load failed", filename);
|
||||
} else {
|
||||
glfwSetWindowIcon(window, 1, &icon);
|
||||
stbi_image_free(icon.pixels);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
add_executable(main main.c)
|
||||
target_link_libraries(main PUBLIC ${HAZEL_CORE_NAME})
|
||||
target_precompile_headers(main REUSE_FROM ${HAZEL_CORE_NAME})
|
|
@ -0,0 +1,40 @@
|
|||
#include "hazel/hazel.h"
|
||||
#include "hazel/renderer.h"
|
||||
|
||||
Hazel_Texture* texture = NULL;
|
||||
|
||||
void GameStart() {
|
||||
texture = Hazel_LoadTexture("test/resources/player.png");
|
||||
Hazel_TextureSetColor(texture, 0, 1, 0);
|
||||
Hazel_TextureSetAlpha(texture, 0.3);
|
||||
}
|
||||
|
||||
void GameLoop() {
|
||||
Hazel_RenderSetClearColor(0.1, 0.1, 0.1, 1);
|
||||
Hazel_RenderClear();
|
||||
|
||||
Hazel_RenderSetDrawColor(0.5, 0.1, 0.1, 1);
|
||||
Hazel_RenderDrawLine(0, 0, 800, 600);
|
||||
|
||||
Hazel_RenderSetDrawColor(0, 0.8, 0.1, 1);
|
||||
Hazel_RenderDrawRect(100, 100, 200, 100);
|
||||
|
||||
int w, h;
|
||||
Hazel_TextureGetSize(texture, &w, &h);
|
||||
Hazel_RenderDrawTexture(texture, 10, 0, 10, 10, 0, 0, w * 3, h * 3, FLIP_HORIZONTAL);
|
||||
|
||||
Hazel_RenderSetDrawColor(0, 0, 0.9, 1);
|
||||
Hazel_RenderFillRect(100, 300, 200, 100);
|
||||
}
|
||||
|
||||
void GameQuit() {
|
||||
Hazel_DestroyTexture(texture);
|
||||
}
|
||||
|
||||
int main() {
|
||||
Hazel_Init("test", 800, 600);
|
||||
Hazel_RegistGameFuncs(GameStart, GameLoop, GameQuit);
|
||||
Hazel_Run();
|
||||
Hazel_Quit();
|
||||
return 0;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 408 B |
Binary file not shown.
After Width: | Height: | Size: 219 B |
Reference in New Issue