This commit is contained in:
bjorn 2017-04-16 16:56:49 -07:00
parent fa339c4b24
commit 0f1acae42a
22 changed files with 3262 additions and 355 deletions

View File

@ -13,13 +13,88 @@ if(UNIX)
endif()
project(lovr)
file(GLOB_RECURSE LOVR_SRC src/*.c)
add_executable(lovr ${LOVR_SRC})
set(LOVR_SRC
src/api/audio.c
src/api/event.c
src/api/filesystem.c
src/api/graphics.c
src/api/headset.c
src/api/math.c
src/api/timer.c
src/api/types/blob.c
src/api/types/controller.c
src/api/types/font.c
src/api/types/mesh.c
src/api/types/model.c
src/api/types/shader.c
src/api/types/skybox.c
src/api/types/source.c
src/api/types/texture.c
src/api/types/transform.c
src/audio/audio.c
src/audio/source.c
src/event/event.c
src/filesystem/blob.c
src/filesystem/filesystem.c
src/graphics/font.c
src/graphics/graphics.c
src/graphics/mesh.c
src/graphics/model.c
src/graphics/shader.c
src/graphics/skybox.c
src/graphics/texture.c
src/headset/headset.c
src/lib/glad/glad.c
src/lib/lua-cjson/fpconv.c
src/lib/lua-cjson/lua_cjson.c
src/lib/lua-cjson/strbuf.c
src/lib/map/map.c
src/lib/stb/stb_image.c
src/lib/stb/stb_vorbis.c
src/lib/vec/vec.c
src/loaders/font.c
src/loaders/model.c
src/loaders/source.c
src/loaders/texture.c
src/lovr.c
src/luax.c
src/main.c
src/math/mat4.c
src/math/quat.c
src/math/transform.c
src/math/vec3.c
src/timer/timer.c
src/util.c
)
# Headset backends
if(EMSCRIPTEN)
set(LOVR_HEADSET src/headset/webvr.c)
else()
set(LOVR_HEADSET src/headset/openvr.c)
endif()
add_executable(lovr ${LOVR_SRC} ${LOVR_HEADSET})
if(EMSCRIPTEN)
set(CMAKE_EXECUTABLE_SUFFIX ".html")
add_definitions(-s USE_ZLIB=1 -s ASSERTIONS=2 -s FULL_ES2=1)
set(ZLIB_FOUND 1)
set(ZLIB_LIBRARIES "-s USE_ZLIB=1")
set(ZLIB_INCLUDE_DIR .)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
# LuaJIT
if(WIN32)
# Lua
if(EMSCRIPTEN)
option(LUA_USE_RELATIVE_LOADLIB OFF)
option(LUA_USE_ULONGJMP OFF)
add_subdirectory(deps/lua lua)
set_target_properties(lua luac liblua_static PROPERTIES EXCLUDE_FROM_ALL 1)
include_directories(deps/lua/src ${CMAKE_BINARY_DIR}/lua)
set(LOVR_LUA liblua)
elseif(WIN32)
add_subdirectory(deps/luajit luajit)
include_directories(deps/luajit/src ${CMAKE_BINARY_DIR}/luajit)
set(LOVR_LUA liblua)
@ -44,7 +119,9 @@ endif()
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "")
set(GLFW_BUILD_TESTS OFF CACHE BOOL "")
set(GLFW_BUILD_DOCS OFF CACHE BOOL "")
if(WIN32)
if(EMSCRIPTEN)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3")
elseif(WIN32)
add_subdirectory(deps/glfw glfw)
include_directories(deps/glfw/include)
set(LOVR_GLFW glfw ${GLFW_LIBRARIES})
@ -65,7 +142,12 @@ set(PHYSFS_ARCHIVE_QPAK OFF CACHE BOOL "")
set(PHYSFS_BUILD_TEST OFF CACHE BOOL "")
set(PHYSFS_BUILD_WX_TEST FALSE CACHE BOOL "")
if(WIN32)
if(EMSCRIPTEN)
option(PHYSFS_ARCHIVE_ZIP OFF)
add_subdirectory(deps/physfs physfs)
include_directories(deps/physfs)
set(LOVR_PHYSFS physfs)
elseif(WIN32)
add_subdirectory(deps/physfs physfs)
include_directories(deps/physfs)
set(LOVR_PHYSFS physfs)
@ -85,7 +167,11 @@ set(ASSIMP_BUILD_COLLADA_IMPORTER ON CACHE BOOL "")
set(ASSIMP_BUILD_OBJ_IMPORTER ON CACHE BOOL "")
set(ASSIMP_BUILD_FBX_IMPORTER ON CACHE BOOL "")
if(WIN32)
if(EMSCRIPTEN)
add_subdirectory(deps/assimp assimp)
include_directories(deps/assimp/include)
set(LOVR_ASSIMP assimp)
elseif(WIN32)
add_subdirectory(deps/assimp assimp)
include_directories(deps/assimp/include)
set(LOVR_ASSIMP assimp)
@ -103,7 +189,7 @@ if (WIN32)
add_subdirectory(deps/openal-soft openal)
include_directories(deps/openal-soft/include)
set(LOVR_OPENAL OpenAL32)
else()
elseif(NOT EMSCRIPTEN)
pkg_search_module(OPENAL REQUIRED openal)
include_directories(${OPENAL_INCLUDE_DIRS})
string(REPLACE ";" " " OPENAL_LDFLAGS_STR "${OPENAL_LDFLAGS}")
@ -112,8 +198,9 @@ else()
endif()
# FreeType
if (WIN32)
if (WIN32 OR EMSCRIPTEN)
set(BUILD_SHARED_LIBS OFF)
set(FREETYPE_NO_DIST TRUE CACHE BOOL "")
add_subdirectory(deps/freetype freetype)
include_directories(deps/freetype/include)
set(LOVR_FREETYPE freetype)
@ -124,26 +211,28 @@ else()
endif()
# openvr
if(NOT DEFINED OPENVR_DIR AND IS_DIRECTORY "${PROJECT_SOURCE_DIR}/deps/openvr")
SET(OPENVR_DIR deps/openvr)
else()
message(FATAL_ERROR "Please specify the location of OpenVR (-DOPENVR_DIR=/path/to/openvr)")
endif()
if(NOT EMSCRIPTEN)
if(NOT DEFINED OPENVR_DIR AND IS_DIRECTORY "${PROJECT_SOURCE_DIR}/deps/openvr")
SET(OPENVR_DIR deps/openvr)
else()
message(FATAL_ERROR "Please specify the location of OpenVR (-DOPENVR_DIR=/path/to/openvr)")
endif()
if(APPLE)
add_definitions(-DOSX -DPOSIX)
elseif(UNIX)
add_definitions(-DLINUX -DPOSIX)
endif()
if(APPLE)
add_definitions(-DOSX -DPOSIX)
elseif(UNIX)
add_definitions(-DLINUX -DPOSIX)
endif()
set(BUILD_SHARED ON CACHE BOOL "")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -fvisibility=hidden")
add_definitions(-DVR_API_PUBLIC)
include_directories(${OPENVR_DIR}/headers)
include_directories(${OPENVR_DIR}/src)
include_directories(${OPENVR_DIR}/src/vrcommon)
add_subdirectory(${OPENVR_DIR}/src openvr_api)
set(LOVR_OPENVR openvr_api)
set(BUILD_SHARED ON CACHE BOOL "")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -fvisibility=hidden")
add_definitions(-DVR_API_PUBLIC)
include_directories(${OPENVR_DIR}/headers)
include_directories(${OPENVR_DIR}/src)
include_directories(${OPENVR_DIR}/src/vrcommon)
add_subdirectory(${OPENVR_DIR}/src openvr_api)
set(LOVR_OPENVR openvr_api)
endif()
set(LOVR_LIB
${LOVR_LUA}

9
build.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
rm -rf build
mkdir build
cd build
emcmake cmake .. && emmake make
mkdir game
echo "function lovr.load()\n print('hi')\nend" > game/main.lua
../package.sh game

3
package.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
python "$EMSCRIPTEN/tools/file_packager.py" game.data --preload "$1"@/ --js-output=game.js

View File

@ -5,10 +5,17 @@ map_int_t ControllerAxes;
map_int_t ControllerButtons;
map_int_t HeadsetEyes;
typedef struct {
lua_State* L;
int ref;
} HeadsetRenderData;
static HeadsetRenderData headsetRenderData;
static void renderHelper(HeadsetEye eye, void* userdata) {
lua_State* L = (lua_State*)userdata;
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_pushvalue(L, 1);
HeadsetRenderData* renderData = userdata;
lua_State* L = renderData->L;
lua_rawgeti(L, LUA_REGISTRYINDEX, renderData->ref);
luax_pushenum(L, &HeadsetEyes, eye);
lua_call(L, 1, 0);
}
@ -212,8 +219,11 @@ int l_lovrHeadsetGetControllerCount(lua_State* L) {
}
int l_lovrHeadsetRenderTo(lua_State* L) {
lua_settop(L, 1);
luaL_checktype(L, 1, LUA_TFUNCTION);
lovrHeadsetRenderTo(renderHelper, L);
headsetRenderData.ref = luaL_ref(L, LUA_REGISTRYINDEX);
headsetRenderData.L = L;
lovrHeadsetRenderTo(renderHelper, &headsetRenderData);
return 0;
}

View File

@ -8,8 +8,6 @@
static AudioState state;
static LPALCRESETDEVICESOFT alcResetDeviceSOFT;
void lovrAudioInit() {
ALCdevice* device = alcOpenDevice(NULL);
if (!device) {
@ -21,6 +19,8 @@ void lovrAudioInit() {
error("Unable to create OpenAL context");
}
#ifndef EMSCRIPTEN
static LPALCRESETDEVICESOFT alcResetDeviceSOFT;
alcResetDeviceSOFT = (LPALCRESETDEVICESOFT) alcGetProcAddress(device, "alcResetDeviceSOFT");
state.isSpatialized = alcIsExtensionPresent(device, "ALC_SOFT_HRTF");
@ -28,6 +28,7 @@ void lovrAudioInit() {
ALCint attrs[3] = { ALC_HRTF_SOFT, ALC_TRUE, 0 };
alcResetDeviceSOFT(device, attrs);
}
#endif
state.device = device;
state.context = context;
@ -107,7 +108,7 @@ int lovrAudioHas(Source* source) {
return index >= 0;
}
int lovrAudioIsSpatialized(Source* source) {
int lovrAudioIsSpatialized() {
return state.isSpatialized;
}

View File

@ -2,7 +2,9 @@
#include "lib/vec/vec.h"
#include <AL/al.h>
#include <AL/alc.h>
#ifndef EMSCRIPTEN
#include <AL/alext.h>
#endif
#pragma once

View File

@ -111,37 +111,42 @@ lovr.handlers = setmetatable({
end
})
function lovr.step()
lovr.event.pump()
for name, a, b, c, d in lovr.event.poll() do
if name == 'quit' and (not lovr.quit or not lovr.quit()) then
return a
end
lovr.handlers[name](a, b, c, d)
end
local dt = lovr.timer.step()
if lovr.audio then
lovr.audio.update()
if lovr.headset and lovr.headset.isPresent() then
lovr.audio.setOrientation(lovr.headset.getOrientation())
lovr.audio.setPosition(lovr.headset.getPosition())
lovr.audio.setVelocity(lovr.headset.getVelocity())
end
end
if lovr.update then lovr.update(dt) end
lovr.graphics.clear()
lovr.graphics.origin()
if lovr.draw then
if lovr.headset and lovr.headset.isPresent() then
lovr.headset.renderTo(lovr.draw)
else
lovr.draw()
end
end
lovr.graphics.present()
lovr.timer.sleep(.001)
end
function lovr.run()
if lovr.load then lovr.load() end
while true do
lovr.event.pump()
for name, a, b, c, d in lovr.event.poll() do
if name == 'quit' and (not lovr.quit or not lovr.quit()) then
return a
end
lovr.handlers[name](a, b, c, d)
end
local dt = lovr.timer.step()
if lovr.audio then
lovr.audio.update()
if lovr.headset and lovr.headset.isPresent() then
lovr.audio.setOrientation(lovr.headset.getOrientation())
lovr.audio.setPosition(lovr.headset.getPosition())
lovr.audio.setVelocity(lovr.headset.getVelocity())
end
end
if lovr.update then lovr.update(dt) end
lovr.graphics.clear()
lovr.graphics.origin()
if lovr.draw then
if lovr.headset and lovr.headset.isPresent() then
lovr.headset.renderTo(lovr.draw)
else
lovr.draw()
end
end
lovr.graphics.present()
lovr.timer.sleep(.001)
local exit = lovr.step()
if exit then return exit end
end
end

View File

@ -272,169 +272,172 @@ unsigned char boot_lua[] = {
0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x65, 0x76, 0x65,
0x6e, 0x74, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x7d,
0x29, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x72, 0x75, 0x6e, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x6c, 0x6f, 0x61,
0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x6c, 0x6f, 0x61, 0x64, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x75, 0x65, 0x20,
0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x61, 0x6d,
0x65, 0x2c, 0x20, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63, 0x2c, 0x20,
0x64, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28, 0x29, 0x20, 0x64,
0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e,
0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x71, 0x75, 0x69, 0x74,
0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x6e, 0x6f, 0x74, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x71, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x72, 0x20,
0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x71, 0x75, 0x69,
0x74, 0x28, 0x29, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b, 0x6e, 0x61, 0x6d,
0x65, 0x5d, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63, 0x2c, 0x20,
0x64, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x74, 0x20,
0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72,
0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69,
0x6f, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29, 0x0a,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74,
0x2e, 0x70, 0x75, 0x6d, 0x70, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x66, 0x6f,
0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x2c, 0x20, 0x62,
0x2c, 0x20, 0x63, 0x2c, 0x20, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c,
0x6c, 0x28, 0x29, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69,
0x66, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x71,
0x75, 0x69, 0x74, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x6e, 0x6f,
0x74, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x71, 0x75, 0x69, 0x74, 0x20,
0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x71, 0x75, 0x69, 0x74, 0x28, 0x29, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x20, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x61, 0x6e,
0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x28,
0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63, 0x2c, 0x20, 0x64, 0x29, 0x0a,
0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x64, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61,
0x75, 0x64, 0x69, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f,
0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x69,
0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74,
0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74,
0x2e, 0x67, 0x65, 0x74, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e,
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e,
0x69, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e,
0x73, 0x65, 0x74, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x4f, 0x72, 0x69, 0x65, 0x6e,
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61,
0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x69,
0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x50, 0x6f, 0x73,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75,
0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x56, 0x65, 0x6c, 0x6f, 0x63,
0x69, 0x74, 0x79, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x56, 0x65, 0x6c, 0x6f,
0x63, 0x69, 0x74, 0x79, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74,
0x65, 0x28, 0x64, 0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x73, 0x2e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x28, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x65, 0x74, 0x2e, 0x69, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e,
0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72,
0x54, 0x6f, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61, 0x77,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x65,
0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x6c,
0x65, 0x65, 0x70, 0x28, 0x2e, 0x30, 0x30, 0x31, 0x29, 0x0a, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65,
0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x20, 0x3d, 0x20, 0x27, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x5c,
0x6e, 0x27, 0x20, 0x2e, 0x2e, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x27, 0x5c, 0x6e, 0x5b, 0x5e,
0x5c, 0x6e, 0x5d, 0x2b, 0x24, 0x27, 0x2c, 0x20, 0x27, 0x27, 0x29, 0x3a,
0x67, 0x73, 0x75, 0x62, 0x28, 0x27, 0x5c, 0x74, 0x27, 0x2c, 0x20, 0x27,
0x27, 0x29, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x27, 0x73, 0x74, 0x61,
0x63, 0x6b, 0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b,
0x27, 0x2c, 0x20, 0x27, 0x5c, 0x6e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x27,
0x29, 0x0a, 0x20, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x6d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x72,
0x65, 0x73, 0x65, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73,
0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x32, 0x37, 0x2c, 0x20, 0x32, 0x35,
0x2c, 0x20, 0x33, 0x35, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65,
0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x32, 0x32, 0x30, 0x2c, 0x20,
0x32, 0x32, 0x30, 0x2c, 0x20, 0x32, 0x32, 0x30, 0x29, 0x0a, 0x20, 0x20,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x3d,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
0x63, 0x73, 0x2e, 0x67, 0x65, 0x74, 0x46, 0x6f, 0x6e, 0x74, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78,
0x65, 0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20,
0x66, 0x6f, 0x6e, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x50, 0x69, 0x78, 0x65,
0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68,
0x20, 0x3d, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x57,
0x69, 0x64, 0x74, 0x68, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x2c, 0x20, 0x2e, 0x35, 0x35, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65,
0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x29, 0x0a, 0x20, 0x20,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x28, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x69,
0x6e, 0x74, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20,
0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x2f, 0x20, 0x32, 0x2c, 0x20,
0x30, 0x2c, 0x20, 0x2d, 0x32, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30,
0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x2e,
0x35, 0x35, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x44, 0x65,
0x6e, 0x73, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x27, 0x6c, 0x65, 0x66, 0x74,
0x27, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x77,
0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x75, 0x65, 0x20, 0x64, 0x6f,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76, 0x65, 0x6e,
0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28, 0x29, 0x20, 0x64, 0x6f, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x61, 0x6d,
0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x71, 0x75, 0x69, 0x74, 0x27, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x28,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e,
0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x65, 0x74, 0x2e, 0x69, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74,
0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x65, 0x74, 0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x54, 0x6f, 0x28,
0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72,
0x65, 0x6e, 0x64, 0x65, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72,
0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x73, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74,
0x2e, 0x67, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74,
0x56, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x74, 0x79, 0x28, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65,
0x74, 0x56, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x74, 0x79, 0x28, 0x29, 0x29,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
0x28, 0x64, 0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
0x2e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
0x2e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61, 0x77,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65,
0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x69, 0x73, 0x50, 0x72, 0x65,
0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x54, 0x6f, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61,
0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64,
0x72, 0x61, 0x77, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73,
0x6c, 0x65, 0x65, 0x70, 0x28, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e,
0x69, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x29,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x2e, 0x30, 0x30, 0x31, 0x20, 0x6f, 0x72,
0x20, 0x2e, 0x31, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65,
0x6e, 0x64, 0x0a, 0x0a, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69,
0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x27, 0x6d, 0x61, 0x69, 0x6e, 0x2e,
0x6c, 0x75, 0x61, 0x27, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20,
0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x27, 0x6d, 0x61,
0x69, 0x6e, 0x27, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a
0x6c, 0x65, 0x65, 0x70, 0x28, 0x2e, 0x30, 0x30, 0x31, 0x29, 0x0a, 0x65,
0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x72, 0x75, 0x6e, 0x28, 0x29, 0x0a,
0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x6c, 0x6f,
0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x75, 0x65,
0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x65, 0x78, 0x69, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x65, 0x78, 0x69, 0x74, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x78, 0x69,
0x74, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x72, 0x72, 0x68, 0x61,
0x6e, 0x64, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x29, 0x0a,
0x20, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x3d, 0x20,
0x27, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x5c, 0x6e, 0x27, 0x20, 0x2e,
0x2e, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x67, 0x73,
0x75, 0x62, 0x28, 0x27, 0x5c, 0x6e, 0x5b, 0x5e, 0x5c, 0x6e, 0x5d, 0x2b,
0x24, 0x27, 0x2c, 0x20, 0x27, 0x27, 0x29, 0x3a, 0x67, 0x73, 0x75, 0x62,
0x28, 0x27, 0x5c, 0x74, 0x27, 0x2c, 0x20, 0x27, 0x27, 0x29, 0x3a, 0x67,
0x73, 0x75, 0x62, 0x28, 0x27, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x74,
0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x27, 0x2c, 0x20, 0x27,
0x5c, 0x6e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x27, 0x29, 0x0a, 0x20, 0x20,
0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x65, 0x74,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x42, 0x61,
0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6f,
0x72, 0x28, 0x32, 0x37, 0x2c, 0x20, 0x32, 0x35, 0x2c, 0x20, 0x33, 0x35,
0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6c,
0x6f, 0x72, 0x28, 0x32, 0x32, 0x30, 0x2c, 0x20, 0x32, 0x32, 0x30, 0x2c,
0x20, 0x32, 0x32, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x67,
0x65, 0x74, 0x46, 0x6f, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x44, 0x65,
0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x6f, 0x6e, 0x74,
0x3a, 0x67, 0x65, 0x74, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e,
0x73, 0x69, 0x74, 0x79, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63,
0x61, 0x6c, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x66,
0x6f, 0x6e, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x57, 0x69, 0x64, 0x74, 0x68,
0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x2e, 0x35,
0x35, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e,
0x73, 0x69, 0x74, 0x79, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72,
0x65, 0x6e, 0x64, 0x65, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x73, 0x2e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70,
0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x6d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x2d, 0x77, 0x69, 0x64,
0x74, 0x68, 0x20, 0x2f, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x2d,
0x32, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c,
0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x2e, 0x35, 0x35, 0x20, 0x2a,
0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74,
0x79, 0x2c, 0x20, 0x27, 0x6c, 0x65, 0x66, 0x74, 0x27, 0x29, 0x0a, 0x20,
0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65,
0x20, 0x74, 0x72, 0x75, 0x65, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e,
0x70, 0x75, 0x6d, 0x70, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
0x6f, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f,
0x6c, 0x6c, 0x28, 0x29, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d,
0x20, 0x27, 0x71, 0x75, 0x69, 0x74, 0x27, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x73, 0x2e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x69,
0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x72,
0x65, 0x6e, 0x64, 0x65, 0x72, 0x54, 0x6f, 0x28, 0x72, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x6c, 0x65, 0x65, 0x70,
0x28, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x69, 0x73, 0x50, 0x72,
0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x29, 0x20, 0x61, 0x6e, 0x64,
0x20, 0x2e, 0x30, 0x30, 0x31, 0x20, 0x6f, 0x72, 0x20, 0x2e, 0x31, 0x29,
0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a,
0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c,
0x65, 0x28, 0x27, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x27,
0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x71,
0x75, 0x69, 0x72, 0x65, 0x28, 0x27, 0x6d, 0x61, 0x69, 0x6e, 0x27, 0x29,
0x0a, 0x65, 0x6e, 0x64, 0x0a
};
unsigned int boot_lua_len = 5241;
unsigned int boot_lua_len = 5273;

View File

@ -78,6 +78,8 @@ int lovrFilesystemGetAppdataDirectory(char* dest, unsigned int size) {
wcstombs(dest, appData, size);
CoTaskMemFree(appData);
return 0;
#elif EMSCRIPTEN
return 0;
#else
#error "This platform is missing an implementation for lovrFilesystemGetAppdataDirectory"
#endif
@ -96,6 +98,8 @@ int lovrFilesystemGetExecutablePath(char* dest, unsigned int size) {
}
#elif _WIN32
return !GetModuleFileName(NULL, dest, size);
#elif EMSCRIPTEN
return 1;
#else
#error "This platform is missing an implementation for lovrFilesystemGetExecutablePath"
#endif
@ -213,7 +217,7 @@ int lovrFilesystemSetIdentity(const char* identity) {
snprintf(state.savePathFull, LOVR_PATH_MAX, "%s%s%s", state.savePathFull, sep, state.savePathRelative);
PHYSFS_mkdir(state.savePathRelative);
if (!PHYSFS_setWriteDir(state.savePathFull)) {
error("Could not set write directory");
//error("Could not set write directory");
}
PHYSFS_mount(state.savePathFull, NULL, 0);

View File

@ -51,8 +51,11 @@ Font* lovrFontCreate(FontData* fontData) {
TextureData* textureData = lovrTextureDataGetBlank(font->atlas.width, font->atlas.height, 0x0, FORMAT_RG);
font->texture = lovrTextureCreate(textureData);
lovrTextureSetWrap(font->texture, WRAP_CLAMP, WRAP_CLAMP);
int swizzle[4] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
if (GLAD_GL_VERSION_3_0) {
int swizzle[4] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
}
return font;
}
@ -289,7 +292,11 @@ void lovrFontAddGlyph(Font* font, Glyph* glyph) {
// Paste glyph into texture
lovrGraphicsBindTexture(font->texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, GL_RG, GL_UNSIGNED_BYTE, glyph->data);
if (GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_texture_rg || GLAD_GL_EXT_texture_rg) {
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, GL_RG, GL_UNSIGNED_BYTE, glyph->data);
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, glyph->data);
}
// Advance atlas cursor
atlas->x += glyph->w + atlas->padding;

View File

@ -7,6 +7,7 @@
#include "util.h"
#define _USE_MATH_DEFINES
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
static GraphicsState state;
@ -23,11 +24,15 @@ static void onCloseWindow(GLFWwindow* window) {
// Base
void lovrGraphicsInit() {
#ifdef EMSCRIPTEN
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, 4);
#endif
state.window = glfwCreateWindow(800, 600, "Window", NULL, NULL);
@ -39,23 +44,32 @@ void lovrGraphicsInit() {
glfwMakeContextCurrent(state.window);
glfwSetWindowCloseCallback(state.window, onCloseWindow);
#ifdef EMSCRIPTEN
gladLoadGLES2Loader((GLADloadproc) glfwGetProcAddress);
#else
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
#endif
glfwSetTime(0);
glfwSwapInterval(0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_MULTISAMPLE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
if (GLAD_GL_VERSION_3_0) {
glfwSwapInterval(0);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_MULTISAMPLE);
}
// Allocations
state.activeFont = NULL;
state.defaultFont = NULL;
state.activeTexture = NULL;
glGenBuffers(1, &state.shapeBuffer);
glGenBuffers(1, &state.shapeIndexBuffer);
glGenVertexArrays(1, &state.shapeArray);
if (GLAD_GL_VERSION_3_0) {
glGenVertexArrays(1, &state.shapeArray);
}
vec_init(&state.shapeData);
vec_init(&state.shapeIndices);
for (int i = 0; i < MAX_CANVASES; i++) {
@ -71,11 +85,17 @@ void lovrGraphicsInit() {
state.defaultTexture = lovrTextureCreate(lovrTextureDataGetBlank(1, 1, 0xff, FORMAT_RGBA));
// System Limits
float pointSizes[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizes);
state.maxPointSize = pointSizes[1];
if (GLAD_GL_VERSION_2_0) {
float pointSizes[2];
glGetFloatv(GL_POINT_SIZE_RANGE, pointSizes);
state.maxPointSize = pointSizes[1];
glGetIntegerv(GL_MAX_SAMPLES, &state.maxTextureMSAA);
} else {
state.maxPointSize = 1.f;
state.maxTextureMSAA = 1;
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &state.maxTextureSize);
glGetIntegerv(GL_MAX_SAMPLES, &state.maxTextureMSAA);
// State
state.depthTest = -1;
@ -99,7 +119,9 @@ void lovrGraphicsDestroy() {
lovrRelease(&state.defaultTexture->ref);
glDeleteBuffers(1, &state.shapeBuffer);
glDeleteBuffers(1, &state.shapeIndexBuffer);
glDeleteVertexArrays(1, &state.shapeArray);
if (GLAD_GL_VERSION_3_0) {
glDeleteVertexArrays(1, &state.shapeArray);
}
vec_deinit(&state.shapeData);
vec_deinit(&state.shapeIndices);
}
@ -199,13 +221,21 @@ void lovrGraphicsSetBlendMode(BlendMode mode, BlendAlphaMode alphaMode) {
break;
case BLEND_LIGHTEN:
glBlendEquation(GL_MAX);
glBlendFuncSeparate(srcRGB, GL_ZERO, GL_ONE, GL_ZERO);
if (GLAD_GL_VERSION_2_0 || GLAD_GL_EXT_blend_minmax) {
glBlendEquation(GL_MAX);
glBlendFuncSeparate(srcRGB, GL_ZERO, GL_ONE, GL_ZERO);
} else {
error("The lighten blend mode is not supported on this platform.");
}
break;
case BLEND_DARKEN:
glBlendEquation(GL_MIN);
glBlendFuncSeparate(srcRGB, GL_ZERO, GL_ONE, GL_ZERO);
if (GLAD_GL_VERSION_2_0 || GLAD_GL_EXT_blend_minmax) {
glBlendEquation(GL_MIN);
glBlendFuncSeparate(srcRGB, GL_ZERO, GL_ONE, GL_ZERO);
} else {
error("The darken blend mode is not supported on this platform.");
}
break;
case BLEND_SCREEN:
@ -361,8 +391,10 @@ float lovrGraphicsGetPointSize() {
}
void lovrGraphicsSetPointSize(float size) {
state.pointSize = size;
glPointSize(size);
if (GLAD_GL_VERSION_2_0) {
state.pointSize = size;
glPointSize(size);
}
}
int lovrGraphicsIsCullingEnabled() {
@ -408,21 +440,21 @@ int lovrGraphicsIsWireframe() {
}
void lovrGraphicsSetWireframe(int wireframe) {
if (state.isWireframe != wireframe) {
if (GLAD_GL_VERSION_3_0 && state.isWireframe != wireframe) {
state.isWireframe = wireframe;
glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL);
}
}
int lovrGraphicsGetWidth() {
int width;
glfwGetFramebufferSize(state.window, &width, NULL);
int width, height;
glfwGetFramebufferSize(state.window, &width, &height);
return width;
}
int lovrGraphicsGetHeight() {
int height;
glfwGetFramebufferSize(state.window, NULL, &height);
int width, height;
glfwGetFramebufferSize(state.window, &width, &height);
return height;
}
@ -515,7 +547,9 @@ void lovrGraphicsDrawPrimitive(GLenum mode, int hasNormals, int hasTexCoords, in
int strideBytes = stride * sizeof(float);
lovrGraphicsPrepare();
glBindVertexArray(state.shapeArray);
if (GLAD_GL_VERSION_3_0) {
glBindVertexArray(state.shapeArray);
}
glBindBuffer(GL_ARRAY_BUFFER, state.shapeBuffer);
glBufferData(GL_ARRAY_BUFFER, state.shapeData.length * sizeof(float), state.shapeData.data, GL_STREAM_DRAW);
glEnableVertexAttribArray(LOVR_SHADER_POSITION);
@ -544,7 +578,9 @@ void lovrGraphicsDrawPrimitive(GLenum mode, int hasNormals, int hasTexCoords, in
glDrawArrays(mode, 0, state.shapeData.length / stride);
}
glBindVertexArray(0);
if (GLAD_GL_VERSION_3_0) {
glBindVertexArray(0);
}
}
void lovrGraphicsPoints(float* points, int count) {

View File

@ -4,7 +4,7 @@
static void lovrMeshBindAttributes(Mesh* mesh) {
Shader* shader = lovrGraphicsGetShader();
if (!shader || (shader == mesh->lastShader && !mesh->attributesDirty)) {
if (!shader || (shader == mesh->lastShader && !mesh->attributesDirty && GLAD_GL_VERSION_3_0)) {
return;
}
@ -20,8 +20,12 @@ static void lovrMeshBindAttributes(Mesh* mesh) {
if (location >= 0 && (mesh->enabledAttributes & (1 << i))) {
glEnableVertexAttribArray(location);
if (attribute.type == MESH_INT) {
glVertexAttribIPointer(location, attribute.count, attribute.type, mesh->stride, (void*) offset);
if (attribute.type == MESH_INT ) {
if (GLAD_GL_ES_VERSION_2_0) {
error("Integer attributes are not supported on this platform.");
} else {
glVertexAttribIPointer(location, attribute.count, attribute.type, mesh->stride, (void*) offset);
}
} else {
glVertexAttribPointer(location, attribute.count, attribute.type, GL_FALSE, mesh->stride, (void*) offset);
}
@ -65,6 +69,7 @@ Mesh* lovrMeshCreate(int count, MeshFormat* format, MeshDrawMode drawMode, MeshU
return NULL;
}
mesh->data = NULL;
mesh->count = count;
mesh->stride = stride;
mesh->enabledAttributes = ~0;
@ -83,9 +88,15 @@ Mesh* lovrMeshCreate(int count, MeshFormat* format, MeshDrawMode drawMode, MeshU
glGenBuffers(1, &mesh->vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
glBufferData(GL_ARRAY_BUFFER, mesh->count * mesh->stride, NULL, mesh->usage);
glGenVertexArrays(1, &mesh->vao);
if (GLAD_GL_VERSION_3_0) {
glGenVertexArrays(1, &mesh->vao);
}
glGenBuffers(1, &mesh->ibo);
if (!GLAD_GL_VERSION_3_0 && !GL_ARB_map_buffer_range) {
mesh->data = malloc(mesh->count * mesh->stride);
}
return mesh;
}
@ -95,9 +106,12 @@ void lovrMeshDestroy(const Ref* ref) {
lovrRelease(&mesh->texture->ref);
}
glDeleteBuffers(1, &mesh->vbo);
glDeleteVertexArrays(1, &mesh->vao);
if (GLAD_GL_VERSION_3_0) {
glDeleteVertexArrays(1, &mesh->vao);
}
vec_deinit(&mesh->map);
vec_deinit(&mesh->format);
free(mesh->data);
free(mesh);
}
@ -113,7 +127,10 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform) {
lovrGraphicsBindTexture(mesh->texture);
lovrGraphicsPrepare();
glBindVertexArray(mesh->vao);
if (GLAD_GL_VERSION_3_0) {
glBindVertexArray(mesh->vao);
}
lovrMeshBindAttributes(mesh);
int start, count;
@ -245,6 +262,12 @@ void lovrMeshSetTexture(Mesh* mesh, Texture* texture) {
}
void* lovrMeshMap(Mesh* mesh, int start, int count) {
if (!GLAD_GL_VERSION_3_0 && !GLAD_GL_ARB_map_buffer_range) {
mesh->isMapped = 1;
mesh->mapStart = start;
mesh->mapCount = count;
return (char*) mesh->data + start * mesh->stride;
}
// Unmap because the mapped ranges aren't necessarily the same. Could be improved.
if (mesh->isMapped && (mesh->mapStart != start || mesh->mapCount != count)) {
@ -260,6 +283,16 @@ void* lovrMeshMap(Mesh* mesh, int start, int count) {
}
void lovrMeshUnmap(Mesh* mesh) {
if (!GLAD_GL_VERSION_3_0 && !GLAD_GL_ARB_map_buffer_range) {
mesh->isMapped = 0;
int start = mesh->mapStart * mesh->stride;
int count = mesh->mapCount * mesh->stride;
char* data = (char*) mesh->data + count;
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
glBufferSubData(GL_ARRAY_BUFFER, start, count, data);
return;
}
if (mesh->isMapped) {
mesh->isMapped = 0;
glUnmapBuffer(GL_ARRAY_BUFFER);

View File

@ -35,6 +35,7 @@ typedef vec_t(MeshAttribute) MeshFormat;
typedef struct {
Ref ref;
void* data;
int count;
int stride;
int enabledAttributes;

View File

@ -4,22 +4,37 @@
#include <stdlib.h>
const char* lovrShaderVertexPrefix = ""
#ifdef EMSCRIPTEN
"#version 100 \n"
"precision mediump float; \n"
"attribute vec3 lovrPosition; \n"
"attribute vec3 lovrNormal; \n"
"attribute vec2 lovrTexCoord; \n"
"varying vec2 texCoord; \n"
#else
"#version 150 \n"
"uniform mat4 lovrTransform; \n"
"uniform mat4 lovrProjection; \n"
"in vec3 lovrPosition; \n"
"in vec3 lovrNormal; \n"
"in vec2 lovrTexCoord; \n"
"out vec2 texCoord; \n"
#endif
"uniform mat4 lovrTransform; \n"
"uniform mat4 lovrProjection; \n"
"";
const char* lovrShaderFragmentPrefix = ""
#ifdef EMSCRIPTEN
"#version 100 \n"
"precision mediump float; \n"
"varying vec2 texCoord; \n"
#else
"#version 150 \n"
"uniform vec4 lovrColor; \n"
"uniform sampler2D lovrTexture; \n"
"in vec2 texCoord; \n"
"in vec4 gl_FragCoord; \n"
"out vec4 lovrFragColor; \n"
#endif
"uniform vec4 lovrColor; \n"
"uniform sampler2D lovrTexture; \n"
"";
const char* lovrShaderVertexSuffix = ""
@ -31,7 +46,11 @@ const char* lovrShaderVertexSuffix = ""
const char* lovrShaderFragmentSuffix = ""
"void main() { \n"
#ifdef EMSCRIPTEN
" gl_FragColor = color(lovrColor, lovrTexture, texCoord); \n"
#else
" lovrFragColor = color(lovrColor, lovrTexture, texCoord); \n"
#endif
"}"
"";
@ -43,12 +62,20 @@ const char* lovrDefaultVertexShader = ""
const char* lovrDefaultFragmentShader = ""
"vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) { \n"
#ifdef EMSCRIPTEN
" return graphicsColor * texture2D(image, uv); \n"
#else
" return graphicsColor * texture(image, uv); \n"
#endif
"}"
"";
const char* lovrSkyboxVertexShader = ""
#ifdef EMSCRIPTEN
"varying vec3 texturePosition; \n"
#else
"out vec3 texturePosition; \n"
#endif
"vec4 position(mat4 projection, mat4 transform, vec4 vertex) { \n"
" texturePosition = vertex.xyz; \n"
" return projection * transform * vertex; \n"
@ -56,11 +83,19 @@ const char* lovrSkyboxVertexShader = ""
"";
const char* lovrSkyboxFragmentShader = ""
#ifdef EMSCRIPTEN
"varying vec3 texturePosition; \n"
"uniform samplerCube cube; \n"
"vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) { \n"
" return graphicsColor * textureCube(cube, texturePosition); \n"
"}"
#else
"in vec3 texturePosition; \n"
"uniform samplerCube cube; \n"
"vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) { \n"
" return graphicsColor * texture(cube, texturePosition); \n"
"}"
#endif
"";
const char* lovrNoopVertexShader = ""

View File

@ -3,11 +3,24 @@
#include "math/mat4.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
static GLenum getGLFormat(TextureFormat format) {
switch (format) {
case FORMAT_RED: return GL_RED;
case FORMAT_RG: return GL_RG;
case FORMAT_RED:
if (GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_texture_rg || GLAD_GL_EXT_texture_rg) {
return GL_RED;
} else {
return GL_LUMINANCE;
}
case FORMAT_RG:
if (GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_texture_rg || GLAD_GL_EXT_texture_rg) {
return GL_RG;
} else {
return GL_LUMINANCE_ALPHA;
}
case FORMAT_RGB: return GL_RGB;
case FORMAT_RGBA: return GL_RGBA;
}
@ -177,6 +190,10 @@ void lovrTextureGetWrap(Texture* texture, WrapMode* horizontal, WrapMode* vertic
}
void lovrTextureSetWrap(Texture* texture, WrapMode horizontal, WrapMode vertical) {
if (GLAD_GL_ES_VERSION_2_0) {
horizontal = vertical = WRAP_CLAMP;
}
texture->wrapHorizontal = horizontal;
texture->wrapVertical = vertical;
lovrGraphicsBindTexture(texture);

View File

@ -1,5 +1,4 @@
#include "headset/headset.h"
#include "headset/openvr.h"
#include "event/event.h"
void lovrControllerDestroy(const Ref* ref) {

141
src/headset/webvr.c Normal file
View File

@ -0,0 +1,141 @@
#include "headset/headset.h"
#include "graphics/graphics.h"
#include <emscripten.h>
#include <emscripten/vr.h>
static headsetRenderCallback renderCallback;
static void onRequestAnimationFrame(void* userdata) {
lovrGraphicsSetBackgroundColor(1, 0, 0, 1);
lovrGraphicsClear(1, 1);
printf("Yay rendering!\n");
int width = emscripten_vr_get_display_width();
int height = emscripten_vr_get_display_height();
glViewport(0, 0, width, height);
renderCallback(EYE_LEFT, userdata);
glViewport(width, 0, width, height);
renderCallback(EYE_RIGHT, userdata);
}
void lovrHeadsetInit() {
emscripten_vr_init();
}
void lovrHeadsetDestroy() {
//
}
void lovrHeadsetPoll() {
//
}
int lovrHeadsetIsPresent() {
return emscripten_vr_is_present();
}
const char* lovrHeadsetGetType() {
return "WebVR";
}
int lovrHeadsetIsMirrored() {
return 0;
}
void lovrHeadsetSetMirrored(int mirror) {
//
}
void lovrHeadsetGetDisplayDimensions(int* width, int* height) {
*width = *height = 0;
}
void lovrHeadsetGetClipDistance(float* near, float* far) {
*near = *far = 0;
}
void lovrHeadsetSetClipDistance(float near, float far) {
//
}
float lovrHeadsetGetBoundsWidth() {
return 0;
}
float lovrHeadsetGetBoundsDepth() {
return 0;
}
void lovrHeadsetGetBoundsGeometry(float* geometry) {
geometry = NULL;
}
char lovrHeadsetIsBoundsVisible() {
return 0;
}
void lovrHeadsetSetBoundsVisible(char visible) {
//
}
void lovrHeadsetGetPosition(float* x, float* y, float* z) {
*x = *y = *z = 0;
}
void lovrHeadsetGetEyePosition(HeadsetEye eye, float* x, float* y, float* z) {
*x = *y = *z = 0;
}
void lovrHeadsetGetOrientation(float* angle, float* x, float* y, float* z) {
*angle = *x = *y = *z = 0;
}
void lovrHeadsetGetVelocity(float* x, float* y, float* z) {
*x = *y = *z = 0;
}
void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z) {
*x = *y = *z = 0;
}
vec_controller_t* lovrHeadsetGetControllers() {
return NULL;
}
int lovrHeadsetControllerIsPresent(Controller* controller) {
return 0;
}
void lovrHeadsetControllerGetPosition(Controller* controller, float* x, float* y, float* z) {
*x = *y = *z = 0;
}
void lovrHeadsetControllerGetOrientation(Controller* controller, float* angle, float* x, float* y, float* z) {
*angle = *x = *y = *z = 0;
}
float lovrHeadsetControllerGetAxis(Controller* controller, ControllerAxis axis) {
return 0;
}
int lovrHeadsetControllerIsDown(Controller* controller, ControllerButton button) {
return 0;
}
void lovrHeadsetControllerVibrate(Controller* controller, float duration) {
//
}
ModelData* lovrHeadsetControllerNewModelData(Controller* controller) {
return NULL;
}
TextureData* lovrHeadsetControllerNewTextureData(Controller* controller) {
return NULL;
}
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata) {
renderCallback = callback;
emscripten_vr_set_render_callback(onRequestAnimationFrame, userdata);
}

View File

@ -1,4 +1,6 @@
GL_ARB_vertex_array_object
GL_ARB_framebuffer_object
GL_ARB_map_buffer_range
GL_ARB_texture_rg
GL_EXT_texture_rg
GL_EXT_blend_minmax
GL_OES_texture_npot

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,8 @@
#ifdef _WIN32
#define APIENTRY __stdcall
#elif EMSCRIPTEN
#define GLFW_INCLUDE_ES2
#endif
#include "lib/glad/glad.h"

View File

@ -104,6 +104,39 @@ void lovrDestroy(int exitCode) {
exit(exitCode);
}
#ifdef EMSCRIPTEN
#include <emscripten.h>
static void emscriptenLoop(void* arg) {
lua_State* L = arg;
// lovr.step
lua_getglobal(L, "lovr");
if (lua_isnil(L, -1)) {
return;
}
lua_getfield(L, -1, "step");
if (lua_isnil(L, -1)) {
return;
}
lua_call(L, 0, 0);
}
void lovrRun(lua_State* L) {
// lovr.load
lua_getglobal(L, "lovr");
if (!lua_isnil(L, -1)) {
lua_getfield(L, -1, "load");
if (!lua_isnil(L, -1)) {
lua_call(L, 0, 0);
}
}
emscripten_set_main_loop_arg(emscriptenLoop, (void*) L, 0, 1);
}
#else
void lovrRun(lua_State* L) {
lua_pushcfunction(L, getStackTrace);
@ -129,3 +162,4 @@ void lovrRun(lua_State* L) {
lovrDestroy(exitCode);
}
#endif