first stable version OK
This commit is contained in:
parent
a5213c552a
commit
d92247535f
|
@ -1,2 +1,7 @@
|
||||||
build
|
build
|
||||||
.vscode
|
.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)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
||||||
|
|
||||||
project(HazelLuaEngine
|
project(HazelLuaEngine
|
||||||
VERSION 0.1.0
|
VERSION 0.1.0
|
||||||
DESCRIPTION "a tiny engine made with C and Lua for 1MGames"
|
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/FindLua.cmake)
|
||||||
include(cmake/FindGLFW.cmake)
|
include(cmake/FindGLFW.cmake)
|
||||||
include(cmake/FindGLAD.cmake)
|
include(cmake/FindGLAD.cmake)
|
||||||
|
include(cmake/FindSTB.cmake)
|
||||||
|
|
||||||
# hazel
|
# hazel-core
|
||||||
aux_source_directory(src HAZEL_SRC)
|
aux_source_directory(src HAZEL_SRC)
|
||||||
add_library(${HAZEL_CORE_NAME} STATIC ${HAZEL_SRC})
|
add_library(${HAZEL_CORE_NAME} SHARED ${HAZEL_SRC})
|
||||||
target_link_libraries(${HAZEL_CORE_NAME} PUBLIC glad glfw)
|
target_link_libraries(${HAZEL_CORE_NAME} PUBLIC glad glfw stb_image)
|
||||||
target_include_directories(${HAZEL_CORE_NAME} PUBLIC .)
|
target_include_directories(${HAZEL_CORE_NAME} PUBLIC .)
|
||||||
target_compile_features(${HAZEL_CORE_NAME} PUBLIC c_std_11)
|
target_compile_features(${HAZEL_CORE_NAME} PUBLIC c_std_11)
|
||||||
|
target_precompile_headers(${HAZEL_CORE_NAME} PUBLIC hazel/pch.h)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_compile_definitions(${HAZEL_CORE_NAME} PUBLIC 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)
|
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)
|
add_library(${HAZEL_LUA_BRIDGE_NAME} SHARED bridge.c)
|
||||||
target_link_libraries(${HAZEL_LUA_BRIDGE_NAME} PUBLIC ${HAZEL_CORE_NAME} lua)
|
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)
|
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 "luaconf.h"
|
||||||
|
|
||||||
#include "hazel/hazel.h"
|
#include "hazel/hazel.h"
|
||||||
|
#include "hazel/renderer.h"
|
||||||
|
|
||||||
static int LuaBridge_RunExampleWindow(lua_State* L) {
|
static int LuaBridge_RenderSetClearColor(lua_State* L) {
|
||||||
Hazel_RunExampleWindow();
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct luaL_Reg hazel[] = {
|
static int LuaBridge_SayHello(lua_State* L) {
|
||||||
{"RunExampleWindow", LuaBridge_RunExampleWindow},
|
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},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
DLLEXPORT int luaopen_hazel(lua_State* L) {
|
DLLEXPORT int luaopen_libhazel(lua_State* L) {
|
||||||
luaL_newlib(L, hazel);
|
luaL_newlib(L, libhazel);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
|
@ -2,19 +2,184 @@
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
#include "lauxlib.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();
|
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) {
|
if (!L) {
|
||||||
printf("lua init failed\n");
|
printf("lua init failed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
luaL_openlibs(L);
|
luaL_openlibs(L);
|
||||||
|
|
||||||
if (luaL_loadfile(L, "main.lua") || lua_pcall(L, 0, 0, 0)) {
|
if (luaL_loadfile(L, config.LuaEntryFile)) {
|
||||||
printf("main.lua load and execute failed\n");
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Hazel_Init(config.WindowTitle, config.WindowWidth, config.WindowHeight);
|
||||||
|
Hazel_RegistGameFuncs(GameStart, GameLoop, GameQuit);
|
||||||
|
|
||||||
|
Hazel_Run();
|
||||||
|
|
||||||
|
Hazel_Quit();
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
return 0;
|
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
|
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_include_directories(lua PUBLIC ./3rdlibs/lua/src)
|
||||||
target_compile_features(lua PRIVATE c_std_99)
|
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__
|
#define __HAZEL_HAZEL_H__
|
||||||
|
|
||||||
#include "pch.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
|
#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
|
#define GLFW_INCLUDE_NONE
|
||||||
#include "GLFW/glfw3.h"
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
#include "glad/glad.h"
|
#include "stb_image.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <math.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#include "log.h"
|
||||||
#define DLLEXPORT __declspec(dllexport)
|
#include "glhelper.h"
|
||||||
#else
|
#include "dllexport.h"
|
||||||
#define DLLEXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#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";
|
||||||
|
}
|
||||||
|
}
|
93
src/hazel.c
93
src/hazel.c
|
@ -1,37 +1,82 @@
|
||||||
#include "hazel/hazel.h"
|
#include "hazel/hazel.h"
|
||||||
|
|
||||||
void Hazel_RunExampleWindow() {
|
Hazel_GameLoopFunc gameLoopCallback = NULL;
|
||||||
GLFWwindow* window;
|
Hazel_BeforeGameStartFunc beforeGameStartCallback = NULL;
|
||||||
|
Hazel_BeforeGameQuitFunc beforeGameQuitCallback = NULL;
|
||||||
|
|
||||||
/* Initialize the library */
|
void Hazel_Init(const char* title, int w, int h) {
|
||||||
if (!glfwInit())
|
Hazel_InitWindow(title, w, h);
|
||||||
return;
|
Hazel_RenderInit(w, h);
|
||||||
|
|
||||||
/* 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 */
|
void Hazel_Quit() {
|
||||||
glfwMakeContextCurrent(window);
|
Hazel_RenderQuit();
|
||||||
|
glfwTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
/* Use Glad to load OpenGL */
|
int Hazel_ShouldClose() {
|
||||||
gladLoadGL();
|
return glfwWindowShouldClose(window);
|
||||||
|
}
|
||||||
|
|
||||||
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 */
|
void Hazel_RegistGameFuncs(Hazel_BeforeGameStartFunc before, Hazel_GameLoopFunc doing, Hazel_BeforeGameQuitFunc after) {
|
||||||
glfwSwapBuffers(window);
|
beforeGameStartCallback = before;
|
||||||
|
gameLoopCallback = doing;
|
||||||
|
beforeGameQuitCallback = after;
|
||||||
|
}
|
||||||
|
|
||||||
/* Poll for and process events */
|
void Hazel_Run() {
|
||||||
|
if (beforeGameStartCallback) {
|
||||||
|
beforeGameStartCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!Hazel_ShouldClose()) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
|
if (gameLoopCallback) {
|
||||||
|
gameLoopCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwTerminate();
|
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