"Blank" window
This commit is contained in:
parent
0665b12d6c
commit
28088760b9
9 changed files with 1073 additions and 28 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
||||||
editor
|
demo
|
||||||
*.o
|
*.o
|
||||||
fd-*.h
|
fd-*.h
|
||||||
imgui.ini
|
imgui.ini
|
||||||
|
|
|
@ -46,9 +46,7 @@ flags = [
|
||||||
'c++',
|
'c++',
|
||||||
'-I','.',
|
'-I','.',
|
||||||
'-I','imgui',
|
'-I','imgui',
|
||||||
'-I','imguifs',
|
|
||||||
'-I','glm/glm',
|
'-I','glm/glm',
|
||||||
'-I','picojson',
|
|
||||||
'-I','/usr/include/SDL2'
|
'-I','/usr/include/SDL2'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
39
Makefile
39
Makefile
|
@ -1,36 +1,29 @@
|
||||||
CXXFLAGS += $(shell sdl2-config --cflags) -std=c++14 -Wall
|
CXXFLAGS += $(shell sdl2-config --cflags) -std=c++14 -Wall
|
||||||
CFLAGS += $(shell sdl2-config --cflags)
|
CFLAGS += $(shell sdl2-config --cflags)
|
||||||
CPPFLAGS += -I. -Iimgui -Iimguifs -Iglm -Ipicojson \
|
CPPFLAGS += -I. -Iimgui -Iglm \
|
||||||
-DREAL_BUILD -DGLM_ENABLE_EXPERIMENTAL
|
-DREAL_BUILD -DGLM_ENABLE_EXPERIMENTAL
|
||||||
LIBS += $(shell sdl2-config --libs) -lGL -lGLEW -ldl
|
LIBS += $(shell sdl2-config --libs) -lGL -lGLEW -ldl
|
||||||
|
|
||||||
FILEDUMPS = \
|
FILEDUMPS =
|
||||||
fd-raymarcher.glsl.h
|
|
||||||
|
|
||||||
IMGUI = imgui.o imgui_demo.o imgui_draw.o imguifs.o
|
IMGUI = imgui.o imgui_demo.o imgui_draw.o
|
||||||
EDITOR = \
|
DEMO = \
|
||||||
editor.o \
|
main.o \
|
||||||
imgui_impl_sdl.o \
|
imgui_impl_sdl.o \
|
||||||
utilities.o \
|
utilities.o
|
||||||
project.o \
|
|
||||||
\
|
|
||||||
mg-none.o \
|
|
||||||
mg-fragment.o \
|
|
||||||
\
|
|
||||||
gfx-raymarcher.o
|
|
||||||
|
|
||||||
EDITOR_DEPS = $(EDITOR:%.o=.%.d)
|
DEMO_DEPS = $(DEMO:%.o=.%.d)
|
||||||
|
|
||||||
|
|
||||||
editor: $(EDITOR) $(IMGUI)
|
demo: $(DEMO) $(IMGUI)
|
||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o editor \
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o demo \
|
||||||
$(EDITOR) $(IMGUI) $(LIBS)
|
$(DEMO) $(IMGUI) $(LIBS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(IMGUI) $(EDITOR) $(FILEDUMPS) editor externals.hh.gch
|
rm -f $(IMGUI) $(DEMO) $(FILEDUMPS) demo externals.hh.gch
|
||||||
|
|
||||||
fullclean: clean
|
fullclean: clean
|
||||||
rm -f $(EDITOR_DEPS)
|
rm -f $(DEMO_DEPS)
|
||||||
|
|
||||||
.PHONY: clean fullclean
|
.PHONY: clean fullclean
|
||||||
|
|
||||||
|
@ -48,13 +41,9 @@ imgui_demo.o: imgui/imgui_demo.cpp
|
||||||
imgui_draw.o: imgui/imgui_draw.cpp
|
imgui_draw.o: imgui/imgui_draw.cpp
|
||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
imguifs.o: imguifs/imguifilesystem.cpp imguifs/dirent_portable.h imguifs/imguifilesystem.h
|
-include $(DEMO_DEPS)
|
||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -include /usr/include/stdlib.h -c -o $@ $<
|
|
||||||
|
|
||||||
|
$(DEMO): %.o: %.cc externals.hh.gch | $(FILEDUMPS)
|
||||||
-include $(EDITOR_DEPS)
|
|
||||||
|
|
||||||
$(EDITOR): %.o: %.cc externals.hh.gch | $(FILEDUMPS)
|
|
||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -M -MF $(@:%.o=.%.d) -MT $@ $<
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -M -MF $(@:%.o=.%.d) -MT $@ $<
|
||||||
|
|
||||||
|
|
32
externals.hh
Normal file
32
externals.hh
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// C
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// System (C)
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// Misc (C)
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
// C++ std
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
// ImGui
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
// GLM
|
||||||
|
#include <glm/mat3x3.hpp>
|
||||||
|
#include <glm/gtx/euler_angles.hpp>
|
||||||
|
|
||||||
|
// Silly decoration macros I use everywhere
|
||||||
|
#define __rd__
|
||||||
|
#define __wr__
|
||||||
|
#define __rw__
|
282
imgui_impl_sdl.cc
Normal file
282
imgui_impl_sdl.cc
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
// ImGui SDL2 binding with OpenGL
|
||||||
|
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||||
|
|
||||||
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
|
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||||
|
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||||
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
|
#include "externals.hh"
|
||||||
|
#include "imgui_impl_sdl.h"
|
||||||
|
|
||||||
|
// Data
|
||||||
|
static double g_Time = 0.0f;
|
||||||
|
static bool g_MousePressed[3] = { false, false, false };
|
||||||
|
static float g_MouseWheel = 0.0f;
|
||||||
|
static GLuint g_FontTexture = 0;
|
||||||
|
|
||||||
|
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||||
|
// If text or lines are blurry when integrating ImGui in your engine:
|
||||||
|
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||||
|
void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
|
||||||
|
{
|
||||||
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||||
|
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||||
|
if (fb_width == 0 || fb_height == 0)
|
||||||
|
return;
|
||||||
|
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||||
|
|
||||||
|
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
|
||||||
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
|
||||||
|
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||||
|
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||||
|
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context
|
||||||
|
|
||||||
|
// Setup viewport, orthographic projection matrix
|
||||||
|
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
// Render command lists
|
||||||
|
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
||||||
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
|
{
|
||||||
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
|
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
|
||||||
|
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
||||||
|
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos)));
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, uv)));
|
||||||
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, col)));
|
||||||
|
|
||||||
|
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||||
|
{
|
||||||
|
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||||
|
if (pcmd->UserCallback)
|
||||||
|
{
|
||||||
|
pcmd->UserCallback(cmd_list, pcmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||||
|
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
||||||
|
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
|
||||||
|
}
|
||||||
|
idx_buffer += pcmd->ElemCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef OFFSETOF
|
||||||
|
|
||||||
|
// Restore modified state
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPopMatrix();
|
||||||
|
glPopAttrib();
|
||||||
|
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||||
|
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* ImGui_ImplSdl_GetClipboardText(void*)
|
||||||
|
{
|
||||||
|
return SDL_GetClipboardText();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplSdl_SetClipboardText(void*, const char* text)
|
||||||
|
{
|
||||||
|
SDL_SetClipboardText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
case SDL_MOUSEWHEEL:
|
||||||
|
{
|
||||||
|
if (event->wheel.y > 0)
|
||||||
|
g_MouseWheel = 1;
|
||||||
|
if (event->wheel.y < 0)
|
||||||
|
g_MouseWheel = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
{
|
||||||
|
if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;
|
||||||
|
if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;
|
||||||
|
if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_TEXTINPUT:
|
||||||
|
{
|
||||||
|
io.AddInputCharactersUTF8(event->text.text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
case SDL_KEYUP:
|
||||||
|
{
|
||||||
|
int key = event->key.keysym.sym & ~SDLK_SCANCODE_MASK;
|
||||||
|
io.KeysDown[key] = (event->type == SDL_KEYDOWN);
|
||||||
|
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
|
||||||
|
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
|
||||||
|
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
|
||||||
|
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplSdl_CreateDeviceObjects()
|
||||||
|
{
|
||||||
|
// Build texture atlas
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
unsigned char* pixels;
|
||||||
|
int width, height;
|
||||||
|
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
|
||||||
|
|
||||||
|
// Upload texture to graphics system
|
||||||
|
GLint last_texture;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
glGenTextures(1, &g_FontTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels);
|
||||||
|
|
||||||
|
// Store our identifier
|
||||||
|
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||||
|
|
||||||
|
// Restore state
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplSdl_InvalidateDeviceObjects()
|
||||||
|
{
|
||||||
|
if (g_FontTexture)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &g_FontTexture);
|
||||||
|
ImGui::GetIO().Fonts->TexID = 0;
|
||||||
|
g_FontTexture = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplSdl_Init(SDL_Window* window)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||||
|
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
|
||||||
|
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
|
||||||
|
io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
|
||||||
|
io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
|
||||||
|
io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
|
||||||
|
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
|
||||||
|
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
|
||||||
|
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
|
||||||
|
io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE;
|
||||||
|
io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE;
|
||||||
|
io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN;
|
||||||
|
io.KeyMap[ImGuiKey_Escape] = SDLK_ESCAPE;
|
||||||
|
io.KeyMap[ImGuiKey_A] = SDLK_a;
|
||||||
|
io.KeyMap[ImGuiKey_C] = SDLK_c;
|
||||||
|
io.KeyMap[ImGuiKey_V] = SDLK_v;
|
||||||
|
io.KeyMap[ImGuiKey_X] = SDLK_x;
|
||||||
|
io.KeyMap[ImGuiKey_Y] = SDLK_y;
|
||||||
|
io.KeyMap[ImGuiKey_Z] = SDLK_z;
|
||||||
|
|
||||||
|
io.RenderDrawListsFn = ImGui_ImplSdl_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
|
||||||
|
io.SetClipboardTextFn = ImGui_ImplSdl_SetClipboardText;
|
||||||
|
io.GetClipboardTextFn = ImGui_ImplSdl_GetClipboardText;
|
||||||
|
io.ClipboardUserData = NULL;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
SDL_SysWMinfo wmInfo;
|
||||||
|
SDL_VERSION(&wmInfo.version);
|
||||||
|
SDL_GetWindowWMInfo(window, &wmInfo);
|
||||||
|
io.ImeWindowHandle = wmInfo.info.win.window;
|
||||||
|
#else
|
||||||
|
(void)window;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplSdl_Shutdown()
|
||||||
|
{
|
||||||
|
ImGui_ImplSdl_InvalidateDeviceObjects();
|
||||||
|
ImGui::Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplSdl_NewFrame(SDL_Window *window ,
|
||||||
|
bool mouseLock,ImVec2 const& mousePos)
|
||||||
|
{
|
||||||
|
if (!g_FontTexture)
|
||||||
|
ImGui_ImplSdl_CreateDeviceObjects();
|
||||||
|
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
|
int w, h;
|
||||||
|
int display_w, display_h;
|
||||||
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
|
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
|
||||||
|
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||||
|
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
|
||||||
|
|
||||||
|
// Setup time step
|
||||||
|
Uint32 time = SDL_GetTicks();
|
||||||
|
double current_time = time / 1000.0;
|
||||||
|
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
|
||||||
|
g_Time = current_time;
|
||||||
|
|
||||||
|
// Setup inputs
|
||||||
|
// (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent())
|
||||||
|
int mx, my;
|
||||||
|
Uint32 mouseMask = SDL_GetMouseState(&mx, &my);
|
||||||
|
if ( mouseLock ) {
|
||||||
|
io.MousePos = mousePos;
|
||||||
|
} else {
|
||||||
|
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS)
|
||||||
|
io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||||
|
else
|
||||||
|
io.MousePos = ImVec2(-1,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||||
|
io.MouseDown[1] = g_MousePressed[1] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
|
||||||
|
io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
|
||||||
|
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
|
||||||
|
|
||||||
|
io.MouseWheel = g_MouseWheel;
|
||||||
|
g_MouseWheel = 0.0f;
|
||||||
|
|
||||||
|
// Hide OS mouse cursor if ImGui is drawing it
|
||||||
|
SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1);
|
||||||
|
|
||||||
|
// Start the frame
|
||||||
|
ImGui::NewFrame();
|
||||||
|
}
|
20
imgui_impl_sdl.h
Normal file
20
imgui_impl_sdl.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// ImGui SDL2 binding with OpenGL
|
||||||
|
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||||
|
|
||||||
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
|
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||||
|
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||||
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
|
struct SDL_Window;
|
||||||
|
typedef union SDL_Event SDL_Event;
|
||||||
|
|
||||||
|
IMGUI_API bool ImGui_ImplSdl_Init(SDL_Window* window);
|
||||||
|
IMGUI_API void ImGui_ImplSdl_Shutdown();
|
||||||
|
IMGUI_API void ImGui_ImplSdl_NewFrame(SDL_Window* window,
|
||||||
|
bool mouseLock,ImVec2 const& mousePos);
|
||||||
|
IMGUI_API bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event);
|
||||||
|
|
||||||
|
// Use if you want to reset your rendering device without losing ImGui state.
|
||||||
|
IMGUI_API void ImGui_ImplSdl_InvalidateDeviceObjects();
|
||||||
|
IMGUI_API bool ImGui_ImplSdl_CreateDeviceObjects();
|
179
main.cc
Normal file
179
main.cc
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
#include "externals.hh"
|
||||||
|
|
||||||
|
#include "imgui_impl_sdl.h"
|
||||||
|
#include "utilities.hh"
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_Main ===================================================================*/
|
||||||
|
|
||||||
|
struct T_Main
|
||||||
|
{
|
||||||
|
T_Main( );
|
||||||
|
~T_Main( );
|
||||||
|
|
||||||
|
void mainLoop( );
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string projectFile;
|
||||||
|
SDL_Window * window;
|
||||||
|
SDL_GLContext gl;
|
||||||
|
T_FilesWatcher watcher;
|
||||||
|
std::string loadError;
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
bool capture = false;
|
||||||
|
ImVec2 mouseInitial;
|
||||||
|
ImVec2 mouseMove;
|
||||||
|
|
||||||
|
void startIteration( );
|
||||||
|
void handleCapture( );
|
||||||
|
void makeUI( );
|
||||||
|
void render( );
|
||||||
|
};
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
T_Main::T_Main( )
|
||||||
|
{
|
||||||
|
SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER );
|
||||||
|
|
||||||
|
// Setup window
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER , 1 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE , 24 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE , 8 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION , 2 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION , 2 );
|
||||||
|
SDL_DisplayMode current;
|
||||||
|
SDL_GetCurrentDisplayMode( 0 , ¤t );
|
||||||
|
window = SDL_CreateWindow( "DEMO",
|
||||||
|
SDL_WINDOWPOS_CENTERED , SDL_WINDOWPOS_CENTERED ,
|
||||||
|
1280 , 720 ,
|
||||||
|
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
|
||||||
|
gl = SDL_GL_CreateContext( window );
|
||||||
|
glewInit();
|
||||||
|
ImGui_ImplSdl_Init( window );
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_Main::mainLoop( )
|
||||||
|
{
|
||||||
|
while ( !done ) {
|
||||||
|
startIteration( );
|
||||||
|
if ( !done ) {
|
||||||
|
handleCapture( );
|
||||||
|
makeUI( );
|
||||||
|
watcher.check( );
|
||||||
|
render( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T_Main::~T_Main( )
|
||||||
|
{
|
||||||
|
ImGui_ImplSdl_Shutdown( );
|
||||||
|
SDL_GL_DeleteContext( gl );
|
||||||
|
SDL_DestroyWindow( window );
|
||||||
|
SDL_Quit( );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void T_Main::startIteration( )
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
mouseMove = ImVec2( );
|
||||||
|
while ( SDL_PollEvent( &event ) ) {
|
||||||
|
ImGui_ImplSdl_ProcessEvent( &event );
|
||||||
|
if ( event.type == SDL_QUIT ) {
|
||||||
|
done = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( capture && event.type == SDL_MOUSEMOTION ) {
|
||||||
|
mouseMove.x += event.motion.xrel;
|
||||||
|
mouseMove.y += event.motion.yrel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplSdl_NewFrame( window , capture , mouseInitial );
|
||||||
|
ImGui::GetIO( ).MouseDrawCursor = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_Main::handleCapture( )
|
||||||
|
{
|
||||||
|
auto const& io( ImGui::GetIO( ) );
|
||||||
|
const bool lmb( ImGui::IsMouseDown( 0 ) );
|
||||||
|
const bool mb( lmb || ImGui::IsMouseDown( 1 ) );
|
||||||
|
const bool appCanGrab( !( ImGui::IsMouseHoveringAnyWindow( )
|
||||||
|
|| io.WantCaptureMouse
|
||||||
|
|| io.WantCaptureKeyboard ) );
|
||||||
|
const bool shift( io.KeyShift );
|
||||||
|
const bool ctrl( io.KeyCtrl );
|
||||||
|
|
||||||
|
if ( capture && !mb ) {
|
||||||
|
capture = false;
|
||||||
|
ImGui::CaptureMouseFromApp( false );
|
||||||
|
SDL_SetRelativeMouseMode( SDL_FALSE );
|
||||||
|
SDL_WarpMouseInWindow( window ,
|
||||||
|
int( mouseInitial.x ) ,
|
||||||
|
int( mouseInitial.y ) );
|
||||||
|
ImGui::SetMouseCursor( ImGuiMouseCursor_Arrow );
|
||||||
|
} else if ( capture ) {
|
||||||
|
ImGui::SetMouseCursor( ImGuiMouseCursor_Move );
|
||||||
|
//project->handleDND( mouseMove , ctrl , shift , lmb );
|
||||||
|
// FIXME: D'n'D
|
||||||
|
} else if ( appCanGrab && mb ) {
|
||||||
|
capture = true;
|
||||||
|
mouseInitial = ImGui::GetMousePos( );
|
||||||
|
ImGui::CaptureMouseFromApp( true );
|
||||||
|
SDL_SetRelativeMouseMode( SDL_TRUE );
|
||||||
|
ImGui::SetMouseCursor( ImGuiMouseCursor_Move );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( appCanGrab || capture ) && io.MouseWheel ) {
|
||||||
|
//project->handleWheel( io.MouseWheel , ctrl , shift );
|
||||||
|
// FIXME wheel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_Main::makeUI( )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_Main::render( )
|
||||||
|
{
|
||||||
|
auto const& dspSize( ImGui::GetIO( ).DisplaySize );
|
||||||
|
glViewport( 0 , 0 , (int) dspSize.x, (int) dspSize.y );
|
||||||
|
glClearColor( 1 , 0 , 1 , 1 );
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
|
||||||
|
// FIXME draw the fuck
|
||||||
|
//project->render( );
|
||||||
|
|
||||||
|
glUseProgram( 0 );
|
||||||
|
ImGui::Render( );
|
||||||
|
SDL_GL_SwapWindow( window );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*============================================================================*/
|
||||||
|
|
||||||
|
int main( int , char** )
|
||||||
|
{
|
||||||
|
T_Main m;
|
||||||
|
m.mainLoop( );
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Frame time history
|
||||||
|
const int nFrameTimes = 200;
|
||||||
|
float frameTimes[ nFrameTimes ];
|
||||||
|
memset( frameTimes , 0 , sizeof( float ) * nFrameTimes );
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
// Update frame time history
|
||||||
|
memmove( frameTimes , &frameTimes[ 1 ] ,
|
||||||
|
( nFrameTimes - 1 ) * sizeof( float ) );
|
||||||
|
frameTimes[ nFrameTimes - 1 ] = 1000.0f / ImGui::GetIO( ).Framerate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
379
utilities.cc
Normal file
379
utilities.cc
Normal file
|
@ -0,0 +1,379 @@
|
||||||
|
#include "externals.hh"
|
||||||
|
#include "utilities.hh"
|
||||||
|
|
||||||
|
|
||||||
|
void disableButton( )
|
||||||
|
{
|
||||||
|
ImGui::PushStyleColor( ImGuiCol_Button , ImColor( .3f , .3f , .3f ) );
|
||||||
|
ImGui::PushStyleColor( ImGuiCol_ButtonHovered , ImColor( .3f , .3f , .3f ) );
|
||||||
|
ImGui::PushStyleColor( ImGuiCol_ButtonActive , ImColor( .3f , .3f , .3f ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void updateAngle(
|
||||||
|
__rw__ float& initial ,
|
||||||
|
__rd__ const float delta
|
||||||
|
)
|
||||||
|
{
|
||||||
|
initial = fmod( initial + delta + 540 , 360 ) - 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
void anglesToMatrix(
|
||||||
|
__rd__ float const* angles ,
|
||||||
|
__wr__ float* matrix )
|
||||||
|
{
|
||||||
|
float c[3] , s[3];
|
||||||
|
for ( int i = 0 ; i < 3 ; i ++ ) {
|
||||||
|
const float a = M_PI * angles[ i ] / 180;
|
||||||
|
c[i] = cos( a );
|
||||||
|
s[i] = sin( a );
|
||||||
|
}
|
||||||
|
matrix[0] = c[1]*c[2];
|
||||||
|
matrix[1] = s[0]*s[1]*c[2] - c[0]*s[2];
|
||||||
|
matrix[2] = s[0]*s[2] + c[0]*s[1]*c[2];
|
||||||
|
matrix[3] = c[1]*s[2];
|
||||||
|
matrix[4] = c[0]*c[2] + s[0]*s[1]*s[2];
|
||||||
|
matrix[5] = c[0]*s[1]*s[2] - s[0]*c[2];
|
||||||
|
matrix[6] = -s[1];
|
||||||
|
matrix[7] = s[0]*c[1];
|
||||||
|
matrix[8] = c[0]*c[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_FilesWatcher ===========================================================*/
|
||||||
|
|
||||||
|
T_FilesWatcher::T_FilesWatcher( )
|
||||||
|
: fd( inotify_init1( O_NONBLOCK ) )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
T_FilesWatcher::T_FilesWatcher( T_FilesWatcher&& other ) noexcept
|
||||||
|
: fd( 0 ) , watched( std::move( other.watched ) )
|
||||||
|
{
|
||||||
|
std::swap( fd , other.fd );
|
||||||
|
other.watched.clear( );
|
||||||
|
for ( T_WatchedFiles* wf : watched ) {
|
||||||
|
if ( wf ) {
|
||||||
|
wf->watcher = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T_FilesWatcher::~T_FilesWatcher( )
|
||||||
|
{
|
||||||
|
if ( fd ) {
|
||||||
|
close( fd );
|
||||||
|
}
|
||||||
|
for ( T_WatchedFiles* wf : watched ) {
|
||||||
|
if ( wf ) {
|
||||||
|
wf->watcher = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_FilesWatcher::check( )
|
||||||
|
{
|
||||||
|
for ( T_WatchedFiles* wf : watched ) {
|
||||||
|
if ( wf ) {
|
||||||
|
wf->triggered = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inotify_event ie;
|
||||||
|
while ( read( fd , &ie , sizeof( ie ) ) == sizeof( ie ) ) {
|
||||||
|
if ( ( ie.mask & ( IN_CLOSE_WRITE | IN_DELETE_SELF ) ) == 0 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( T_WatchedFiles* wf : watched ) {
|
||||||
|
if ( !wf || wf->triggered ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto const& idl( wf->identifiers );
|
||||||
|
if ( find( idl , ie.wd ) != idl.end( ) ) {
|
||||||
|
wf->triggered = true;
|
||||||
|
wf->callback( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*= T_WatchedFiles ===========================================================*/
|
||||||
|
|
||||||
|
T_WatchedFiles::T_WatchedFiles( T_WatchedFiles&& other ) noexcept
|
||||||
|
: watcher( other.watcher ) , callback( other.callback ) ,
|
||||||
|
triggered( other.triggered ) ,
|
||||||
|
identifiers( std::move( other.identifiers ) )
|
||||||
|
{
|
||||||
|
if ( watcher ) {
|
||||||
|
other.watcher = nullptr;
|
||||||
|
*( find( watcher->watched , &other ) ) = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T_WatchedFiles::T_WatchedFiles(
|
||||||
|
__rw__ T_FilesWatcher& watcher ,
|
||||||
|
__rd__ const F_OnFileChanges callback )
|
||||||
|
: watcher( &watcher ) , callback( callback ) , triggered( false )
|
||||||
|
{
|
||||||
|
watcher.watched.push_back( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
T_WatchedFiles::~T_WatchedFiles( )
|
||||||
|
{
|
||||||
|
clear( );
|
||||||
|
if ( watcher ) {
|
||||||
|
watcher->watched.erase( find( watcher->watched , this ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_WatchedFiles::clear( )
|
||||||
|
{
|
||||||
|
if ( watcher ) {
|
||||||
|
const auto fd( watcher->fd );
|
||||||
|
for ( int wd : identifiers ) {
|
||||||
|
inotify_rm_watch( fd , wd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
identifiers.clear( );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_WatchedFiles::watch(
|
||||||
|
__rd__ std::string const& file )
|
||||||
|
{
|
||||||
|
static constexpr auto inFlags( IN_CLOSE_WRITE | IN_DELETE_SELF );
|
||||||
|
if ( watcher ) {
|
||||||
|
const auto wd( inotify_add_watch( watcher->fd ,
|
||||||
|
file.c_str( ) , inFlags ) );
|
||||||
|
if ( wd == -1 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( find( identifiers , wd ) == identifiers.end( ) ) {
|
||||||
|
identifiers.push_back( wd );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_ShaderCode =============================================================*/
|
||||||
|
|
||||||
|
T_ShaderCode::T_ShaderCode(
|
||||||
|
__rd__ const int nparts )
|
||||||
|
: code( nparts , nullptr )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
T_ShaderCode::~T_ShaderCode( )
|
||||||
|
{
|
||||||
|
for ( char* str : code ) {
|
||||||
|
delete[] str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void T_ShaderCode::setPart(
|
||||||
|
__rd__ const int index ,
|
||||||
|
__rd__ char const* const string )
|
||||||
|
{
|
||||||
|
assert( code[ index ] == nullptr );
|
||||||
|
|
||||||
|
const int len( strlen( string ) + 1 );
|
||||||
|
char buffer[ 32 ];
|
||||||
|
const int extraLen( index == 0 ? 0
|
||||||
|
: snprintf( buffer , sizeof( buffer ) ,
|
||||||
|
"\n#line 0 %d\n" , index ) );
|
||||||
|
|
||||||
|
char* const output( new char[ extraLen + len ] );
|
||||||
|
if ( index != 0 ) {
|
||||||
|
memcpy( output , buffer , extraLen );
|
||||||
|
}
|
||||||
|
strcpy( output + extraLen , string );
|
||||||
|
code[ index ] = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_ShaderCode::setPart(
|
||||||
|
__rd__ const int index ,
|
||||||
|
__rd__ void const* const data ,
|
||||||
|
__rd__ const int size )
|
||||||
|
{
|
||||||
|
assert( code[ index ] == nullptr );
|
||||||
|
|
||||||
|
char buffer[ 32 ];
|
||||||
|
const int extraLen( index == 0 ? 0
|
||||||
|
: snprintf( buffer , sizeof( buffer ) ,
|
||||||
|
"\n#line 0 %d\n" , index ) );
|
||||||
|
|
||||||
|
char* const output( new char[ extraLen + size + 1 ] );
|
||||||
|
if ( index != 0 ) {
|
||||||
|
memcpy( output , buffer , extraLen );
|
||||||
|
}
|
||||||
|
memcpy( output + extraLen , data , size );
|
||||||
|
output[ extraLen + size ] = 0;
|
||||||
|
code[ index ] = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_ShaderCode::loadPart(
|
||||||
|
__rd__ const int index ,
|
||||||
|
__rd__ std::string const& source ,
|
||||||
|
__rw__ std::vector< std::string >& errors )
|
||||||
|
{
|
||||||
|
assert( code[ index ] == nullptr );
|
||||||
|
|
||||||
|
FILE * f = fopen( source.c_str( ) , "r" );
|
||||||
|
if ( !f ) {
|
||||||
|
std::string error( "File not found: " );
|
||||||
|
error += source;
|
||||||
|
errors.push_back( error );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[ 32 ];
|
||||||
|
const int extraLen( index == 0 ? 0
|
||||||
|
: snprintf( buffer , sizeof( buffer ) ,
|
||||||
|
"\n#line 0 %d\n" , index ) );
|
||||||
|
|
||||||
|
fseek( f , 0 , SEEK_END );
|
||||||
|
const size_t size( ftell( f ) );
|
||||||
|
fseek( f , 0 , SEEK_SET );
|
||||||
|
|
||||||
|
char* const output( new char[ extraLen + size + 1 ] );
|
||||||
|
if ( index != 0 ) {
|
||||||
|
memcpy( output , buffer , extraLen );
|
||||||
|
}
|
||||||
|
if ( fread( output + extraLen , 1 , size , f ) != size ) {
|
||||||
|
fclose( f );
|
||||||
|
delete[] output;
|
||||||
|
std::string error( "Could not read file: " );
|
||||||
|
error += source;
|
||||||
|
errors.push_back( error );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
output[ extraLen + size ] = 0;
|
||||||
|
fclose( f );
|
||||||
|
code[ index ] = output;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLuint T_ShaderCode::createProgram(
|
||||||
|
__rd__ GLenum type ,
|
||||||
|
__rw__ std::vector< std::string >& errors ) const
|
||||||
|
{
|
||||||
|
GLenum sid = glCreateShaderProgramv( type , code.size( ) , &code[ 0 ] );
|
||||||
|
if ( sid == 0 ) {
|
||||||
|
errors.push_back( "Failed to create GL program" );
|
||||||
|
return sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int infoLogLength;
|
||||||
|
glGetProgramiv( sid , GL_INFO_LOG_LENGTH , &infoLogLength );
|
||||||
|
if ( infoLogLength ) {
|
||||||
|
char buffer[ infoLogLength + 1 ];
|
||||||
|
glGetProgramInfoLog( sid , infoLogLength , nullptr , buffer );
|
||||||
|
char* start( buffer );
|
||||||
|
char* found( strchr( buffer , '\n' ) );
|
||||||
|
while ( found ) {
|
||||||
|
*found = 0;
|
||||||
|
errors.push_back( start );
|
||||||
|
start = found + 1;
|
||||||
|
found = strchr( start , '\n' );
|
||||||
|
}
|
||||||
|
if ( start < &buffer[ infoLogLength - 1 ] ) {
|
||||||
|
errors.push_back( start );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int lnk;
|
||||||
|
glGetProgramiv( sid , GL_LINK_STATUS , &lnk );
|
||||||
|
if ( !lnk ) {
|
||||||
|
glDeleteProgram( sid );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_Camera =================================================================*/
|
||||||
|
|
||||||
|
void T_Camera::handleDND(
|
||||||
|
__rd__ ImVec2 const& move ,
|
||||||
|
__rd__ const bool hasCtrl ,
|
||||||
|
__rd__ const bool hasShift ,
|
||||||
|
__rd__ const bool lmb // Left mouse button
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if ( move.x == 0 || move.y == 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float fdx( move.x * .1f * ( hasCtrl ? 1.f : .1f ) );
|
||||||
|
const float fdy( move.y * .1f * ( hasCtrl ? 1.f : .1f ) );
|
||||||
|
|
||||||
|
if ( lmb && hasShift ) {
|
||||||
|
// Left mouse button, shift - move camera
|
||||||
|
const auto side( glm::normalize( glm::cross( up , dir ) ) );
|
||||||
|
lookAt += .01f * ( side * fdx + up * fdy );
|
||||||
|
} else if ( lmb ) {
|
||||||
|
// Left mouse button, no shift - change yaw/pitch
|
||||||
|
updateAngle( angles.y , fdx );
|
||||||
|
updateAngle( angles.x , fdy );
|
||||||
|
} else {
|
||||||
|
// Right mouse button - change roll
|
||||||
|
updateAngle( angles.z , fdx );
|
||||||
|
}
|
||||||
|
update( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_Camera::handleWheel(
|
||||||
|
__rd__ const float wheel ,
|
||||||
|
__rd__ const bool hasCtrl ,
|
||||||
|
__rd__ const bool hasShift
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const float delta( wheel * ( hasCtrl ? 1.f : .1f) );
|
||||||
|
if ( hasShift ) {
|
||||||
|
fov = std::max( 1.f , std::min( 179.f , fov + delta ) );
|
||||||
|
} else {
|
||||||
|
distance = std::max( .01f , distance - delta );
|
||||||
|
}
|
||||||
|
update( );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void T_Camera::makeUI( )
|
||||||
|
{
|
||||||
|
if ( !ImGui::CollapsingHeader( "Camera" ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool changed[] = {
|
||||||
|
ImGui::DragFloat3( "Look at" , &lookAt.x ) ,
|
||||||
|
ImGui::DragFloat( "Distance" , &distance , .1f ,
|
||||||
|
.1f , 1e8 , "%.1f" ) ,
|
||||||
|
ImGui::DragFloat3( "Angles" , &angles.x , .01f , -180 , 180 ) ,
|
||||||
|
ImGui::DragFloat( "FoV" , &fov , .01f , .01f , 179.9f )
|
||||||
|
};
|
||||||
|
|
||||||
|
for ( unsigned i = 0 ; i < sizeof( changed ) / sizeof( bool ) ; i ++ ) {
|
||||||
|
if ( changed[ i ] ) {
|
||||||
|
update( );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void T_Camera::update( )
|
||||||
|
{
|
||||||
|
anglesToMatrix( &angles.x , &rotMat[ 0 ].x );
|
||||||
|
dir = glm::vec3( 0 , 0 , -distance ) * rotMat;
|
||||||
|
up = glm::vec3( 0 , 1 , 0 ) * rotMat;
|
||||||
|
pos = lookAt - dir;
|
||||||
|
np = 2 * tan( M_PI * ( 180. - fov ) / 360. );
|
||||||
|
}
|
166
utilities.hh
Normal file
166
utilities.hh
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef REAL_BUILD
|
||||||
|
# include "externals.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*= Utilities ================================================================*/
|
||||||
|
|
||||||
|
// Disable next ImGui button(s)
|
||||||
|
void disableButton( );
|
||||||
|
// Re-enable ImGui buttons
|
||||||
|
inline void reenableButtons( )
|
||||||
|
{
|
||||||
|
ImGui::PopStyleColor( 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Add some value to an angle, keeping it in [-180;180]
|
||||||
|
void updateAngle(
|
||||||
|
__rw__ float& initial ,
|
||||||
|
__rd__ const float delta
|
||||||
|
);
|
||||||
|
// Make a rotation matrix from three YPR angles (in degrees)
|
||||||
|
void anglesToMatrix(
|
||||||
|
__rd__ float const* angles ,
|
||||||
|
__wr__ float* matrix );
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Helpers for finding entries in collections
|
||||||
|
template< typename T , typename I >
|
||||||
|
inline auto find(
|
||||||
|
__rd__ T const& collection ,
|
||||||
|
__rd__ I const& item )
|
||||||
|
{
|
||||||
|
return std::find( collection.begin( ) , collection.end( ) , item );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T , typename I >
|
||||||
|
inline auto find(
|
||||||
|
__rw__ T& collection ,
|
||||||
|
__rd__ I const& item )
|
||||||
|
{
|
||||||
|
return std::find( collection.begin( ) , collection.end( ) , item );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_FilesWatcher / T_WatchedFiles ==========================================*/
|
||||||
|
|
||||||
|
struct T_FilesWatcher;
|
||||||
|
struct T_WatchedFiles;
|
||||||
|
using F_OnFileChanges = std::function< void( void ) >;
|
||||||
|
|
||||||
|
struct T_FilesWatcher
|
||||||
|
{
|
||||||
|
friend struct T_WatchedFiles;
|
||||||
|
|
||||||
|
T_FilesWatcher( T_FilesWatcher const& ) = delete;
|
||||||
|
|
||||||
|
T_FilesWatcher( );
|
||||||
|
T_FilesWatcher( T_FilesWatcher&& ) noexcept;
|
||||||
|
~T_FilesWatcher( );
|
||||||
|
|
||||||
|
void check( );
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fd;
|
||||||
|
std::vector< T_WatchedFiles* > watched;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
struct T_WatchedFiles
|
||||||
|
{
|
||||||
|
friend struct T_FilesWatcher;
|
||||||
|
|
||||||
|
T_WatchedFiles( ) = delete;
|
||||||
|
T_WatchedFiles( T_WatchedFiles const& ) = delete;
|
||||||
|
|
||||||
|
T_WatchedFiles( T_WatchedFiles&& ) noexcept;
|
||||||
|
T_WatchedFiles(
|
||||||
|
__rw__ T_FilesWatcher& watcher ,
|
||||||
|
__rd__ const F_OnFileChanges callback );
|
||||||
|
|
||||||
|
~T_WatchedFiles( );
|
||||||
|
|
||||||
|
void clear( );
|
||||||
|
bool watch( __rd__ std::string const& file );
|
||||||
|
|
||||||
|
private:
|
||||||
|
T_FilesWatcher* watcher;
|
||||||
|
const F_OnFileChanges callback;
|
||||||
|
bool triggered;
|
||||||
|
std::vector< int > identifiers;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_ShaderCode =============================================================*/
|
||||||
|
|
||||||
|
struct T_ShaderCode
|
||||||
|
{
|
||||||
|
T_ShaderCode( ) = delete;
|
||||||
|
T_ShaderCode( T_ShaderCode const& ) = delete;
|
||||||
|
T_ShaderCode( T_ShaderCode&& ) = delete;
|
||||||
|
|
||||||
|
explicit T_ShaderCode( __rd__ const int nparts );
|
||||||
|
~T_ShaderCode( );
|
||||||
|
|
||||||
|
void setPart(
|
||||||
|
__rd__ const int index ,
|
||||||
|
__rd__ char const* const string );
|
||||||
|
void setPart(
|
||||||
|
__rd__ const int index ,
|
||||||
|
__rd__ void const* const data ,
|
||||||
|
__rd__ const int size );
|
||||||
|
bool loadPart(
|
||||||
|
__rd__ const int index ,
|
||||||
|
__rd__ std::string const& source ,
|
||||||
|
__rw__ std::vector< std::string >& errors );
|
||||||
|
|
||||||
|
GLuint createProgram(
|
||||||
|
__rd__ GLenum type ,
|
||||||
|
__rw__ std::vector< std::string >& errors ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector< char* > code;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_Camera =================================================================*/
|
||||||
|
|
||||||
|
struct T_Camera
|
||||||
|
{
|
||||||
|
glm::vec3 lookAt;
|
||||||
|
glm::vec3 angles;
|
||||||
|
float distance = 10;
|
||||||
|
float fov = 90;
|
||||||
|
|
||||||
|
// Everything below is updated by update()
|
||||||
|
glm::vec3 dir;
|
||||||
|
glm::vec3 up;
|
||||||
|
glm::vec3 pos;
|
||||||
|
float np;
|
||||||
|
|
||||||
|
T_Camera()
|
||||||
|
{ update( ); }
|
||||||
|
|
||||||
|
void handleDND(
|
||||||
|
__rd__ ImVec2 const& move ,
|
||||||
|
__rd__ const bool hasCtrl ,
|
||||||
|
__rd__ const bool hasShift ,
|
||||||
|
__rd__ const bool lmb // Left mouse button
|
||||||
|
);
|
||||||
|
void handleWheel(
|
||||||
|
__rd__ const float wheel ,
|
||||||
|
__rd__ const bool hasCtrl ,
|
||||||
|
__rd__ const bool hasShift
|
||||||
|
);
|
||||||
|
|
||||||
|
void makeUI( );
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::mat3x3 rotMat;
|
||||||
|
float rotationMatrix[ 9 ];
|
||||||
|
void update( );
|
||||||
|
};
|
Loading…
Reference in a new issue