Browse Source

adding imgui

master
cinnaboot 9 years ago
parent
commit
ebe1212d6d
  1. 2
      ext/aixlog
  2. 31
      src/Makefile
  3. 457
      src/gooey.h
  4. 26
      src/hexgame.cpp
  5. 13
      src/renderer.h
  6. 4061
      src/stb_truetype.h

2
ext/aixlog

@ -1 +1 @@
Subproject commit d4e8ab4f1fe0e44d8246b37c349f566b356636f6
Subproject commit abca7539315c902e10c06bb363c19a0e1111bc78

31
src/Makefile

@ -1,14 +1,35 @@
CXXFLAGS = -std=c++11 -g -Wall
INCLUDES = -I../ext/aixlog/include
CXX = g++
CXXFLAGS = -std=c++11 -g -Wall -I/usr/include/SDL2 -I../ext/aixlog/include
# IMGUI
IMGUI_DIR = ../ext/imgui
# TODO: incorporate imgui into project files and not use gl3w
# can also remove -ldl from LDFLAGS then
CC = gcc
CFLAGS = -Wall -I$(IMGUI_DIR)/examples/libs/gl3w
OBJECTS = $(IMGUI_DIR)/examples/libs/gl3w/GL/gl3w.o
CXXFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/examples/sdl_opengl3_example -I$(IMGUI_DIR)/examples/libs/gl3w
OBJECTS += $(IMGUI_DIR)/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.o
OBJECTS += $(IMGUI_DIR)/imgui.o $(IMGUI_DIR)/imgui_demo.o $(IMGUI_DIR)/imgui_draw.o
# libGLEW needs to be >= 2.0.0 to use opengl core context
# don't know a good way to require this in make without forcing a specific version
LDFLAGS = -lSDL2 -lGLEW -lGL
all:
g++ $(CXXFLAGS) $(INCLUDES) -o hexgame hexgame.cpp $(LDFLAGS)
# TODO: only needed for gl3w, remove later
LDFLAGS += -ldl
all: $(OBJECTS)
$(CXX) $(CXXFLAGS) -o hexgame hexgame.cpp $(LDFLAGS) $(OBJECTS)
mkdir -p ../bin
mv hexgame ../bin
.PHONY: clean
clean:
rm ../bin/hexgame
rm ../bin/hexgame $(OBJECTS)

457
src/gooey.h

@ -2,440 +2,77 @@
#ifndef GOOEY_H
#define GOOEY_H
#include <string>
#include <sstream>
#include <string.h> // for strlen
#include <assert.h>
#include <math.h> // for round
#include <GL/glew.h>
#include <SDL2/SDL_opengl.h>
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
#include <SDL2/SDL.h>
#include "imgui.h"
#include "examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h"
#include "hexgame.h"
using std::string;
using std::stringstream;
using std::lround;
struct bitmap_info
{
int32 w;
int32 h;
int32 buffer_size;
uint8 *bitmap_data;
};
struct button
{
bool selected;
uint32 color;
uint32 current_color;
v4i coords; // x0,y0 top left, x1,y1 bottom right
char *text;
HexDrawMode mode;
};
// TODO: heap globals
uint8 *font_filedata;
bitmap_info test_bitmap;
stbtt_aligned_quad *line_buffer;
button *button_array;
uint32 button_count = 0;
uint32 MAX_BUTTONS = 128;
// TODO: stack globals
stbtt_bakedchar font_chardata[96]; // ASCII 32..126 is 95 glyphs
GLuint texture_atlas;
float font_height = 24;
v2i font_atlas_dims = v2i(512, 512);
v4i gooey_extents = {};
// forward declarations
inline void setProjectionMatrix(int w, int h);
void debugLog(string error);
// TODO: move file i/o to asset system
void *
readEntireFile(char *filename)
{
void *buffer = 0;
#if defined _WIN32
stringstream ss;
HANDLE filehandle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (filehandle != INVALID_HANDLE_VALUE)
{
LARGE_INTEGER filesize;
if (GetFileSizeEx(filehandle, &filesize))
{
buffer = VirtualAlloc(0, filesize.QuadPart, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
if (buffer)
{
assert(filesize.QuadPart <= 0xFFFFFFFF); // don't read files larger than 4gb
uint32 filesize32 = (uint32) filesize.QuadPart;
if (ReadFile(filehandle, buffer, filesize32, NULL, NULL))
{
// success
}
else
{
DWORD win_err = GetLastError();
ss << "error reading file " << filename << " . error code: " << win_err
<< ". file:" << __FILE__ << ", line: " << __LINE__ - 3;
debugLog(ss.str());
ss.str("");
CloseHandle(filehandle);
VirtualFree(buffer, 0, MEM_RELEASE);
}
}
else
{
ss << "error allocating memory for " << filename
<< ". file:" << __FILE__ << ", line: " << __LINE__ - 3;
debugLog(ss.str());
ss.str("");
CloseHandle(filehandle);
}
}
else
{
ss << "failed to get filesize of " << filename
<< ". file:" << __FILE__ << ", line: " << __LINE__ - 3;
debugLog(ss.str());
ss.str("");
CloseHandle(filehandle);
}
}
else
{
ss << "failed to open " << filename
<< ". file:" << __FILE__ << ", line: " << __LINE__ - 3;
debugLog(ss.str());
ss.str("");
}
#else // TODO: other platforms IO
return NULL;
#endif
return buffer;
}
v2f
setTextLine(stbtt_aligned_quad *buffer, char *lineText)
{
// NOTE: not accounting for font metrics at all
v2f lineDims = {};
if (buffer && lineText)
{
float x = 0, y = 0;
int i = 0;
while (*lineText)
{
stbtt_GetBakedQuad(font_chardata, test_bitmap.w, test_bitmap.h,
*lineText - 32, &x, &y, &buffer[i], 1);
stbtt_aligned_quad q = buffer[i];
lineDims.x = q.x1 + font_chardata[i].xadvance;
if (lineDims.y > q.y0)
{
lineDims.y = -1 * q.y0;
}
lineText++;
i++;
}
}
return lineDims;
}
// Xoff, Yoff are offsets in screen coords from bottom left
void
renderTextLine(stbtt_aligned_quad *buffer, int32 numQuads, float Xoff, float Yoff,
v2i screen_dims)
{
int w = screen_dims.x, h = screen_dims.y;
w = (w == 0) ? 1 : w; // don't divide by zero
h = (h == 0) ? 1 : h;
// stb_truetype uses top-down coordinates, so we reverse our projection matrix
// when rendering the text
glMatrixMode(GL_PROJECTION);
real32 a = 2.0f / (real32) w;
real32 b = 2.0f / (real32) h;
real32 matrix[16] = {
a, 0, 0, 0,
0, -b, 0, 0,
0, 0, 1, 0,
-1, -1, 0, 1,
};
glLoadMatrixf(matrix);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_atlas);
glColor4f(0,0,0,1);
glBegin(GL_QUADS);
stbtt_aligned_quad q;
for (int i = 0; i < numQuads; i++)
{
q = buffer[i];
glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0 + Xoff,q.y0 - Yoff);
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1 + Xoff,q.y0 - Yoff);
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1 + Xoff,q.y1 - Yoff);
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0 + Xoff,q.y1 - Yoff);
}
glEnd();
glDisable(GL_TEXTURE_2D);
// reset normal projection matrix
setProjectionMatrix(screen_dims.x, screen_dims.y);
}
void
addButton(char *text, int32 x, int32 y, HexDrawMode mode)
{
if (button_count >= MAX_BUTTONS)
{
// allocate some more memory?
return;
}
v2f lineDims = setTextLine(line_buffer, text);
gooey_extents.x1 = (gooey_extents.x1 >= lineDims.x) ? gooey_extents.x1 : lround(lineDims.x);
gooey_extents.y0 = (gooey_extents.y0 <= y) ? gooey_extents.y0 : y;
v4i coords = { x, y, lround(lineDims.x), y + lround(lineDims.y) };
button b;
b.selected = false;
b.color = b.current_color = 0xCCCCCCFF;
b.coords = coords;
b.text = text;
b.mode = mode;
button_array[button_count] = b;
button_count++;
}
void
createGooeyControls(v2i screenDims)
{
gooey_extents.x0 = 0;
gooey_extents.y1 = screenDims.y;
gooey_extents.y0 = screenDims.y - (int32) font_height;
int32 x = 10;
int32 y = screenDims.y - (int32) font_height - 5;
addButton("Hex Fill", x, y, FILL);
addButton("Draw Line", x, lround(y - font_height), LINE);
addButton("Cone Fill", x, lround(y - 2*font_height), CONE_FILL);
addButton("Pathfinding", x, lround(y - 3*font_height), PATHFINDING);
}
bool initGooey(SDL_Handles &handles, v2i vp_dims);
void shutdownGooey();
bool gooeyProcessEvent(SDL_Event &event);
void renderGooey(SDL_Handles &handles, HexDrawMode &mode);
bool
InitGooey(v2i screenDims)
initGooey(SDL_Handles &handles, v2i vp_dims)
{
bool retVal = false;
stringstream ss;
// TODO: hard coded fontname loaded at runtime
char *fontname = "LiberationMono-Regular.ttf";
font_filedata = (uint8 *) readEntireFile(fontname);
if (font_filedata)
{
test_bitmap.w = font_atlas_dims.x;
test_bitmap.h = font_atlas_dims.y;
test_bitmap.bitmap_data = (uint8 *) VirtualAlloc(0, test_bitmap.w * test_bitmap.h,
MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
if (test_bitmap.bitmap_data)
{
int bake_result = stbtt_BakeFontBitmap(font_filedata, 0, font_height,
test_bitmap.bitmap_data, test_bitmap.w, test_bitmap.h, 32, 96,
font_chardata
);
if (bake_result !=0)
{
glGenTextures(1, &texture_atlas);
glBindTexture(GL_TEXTURE_2D, texture_atlas);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, test_bitmap.w, test_bitmap.h, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, test_bitmap.bitmap_data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// TODO: get screen width / font metrics width for memory allocation
line_buffer = (stbtt_aligned_quad *) VirtualAlloc(0, sizeof(stbtt_aligned_quad)*128, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
// TODO: probably a better way to dynamically allocate memory for an
// amount of 'button' objects we don't know the count of
button_array = (button *) VirtualAlloc(0,
sizeof(button) * MAX_BUTTONS,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE
);
if (line_buffer)
{
retVal = true;
createGooeyControls(screenDims);
}
else
{
ss << "error allocating memory for " << fontname
<< ". file:" << __FILE__ << ", line: " << __LINE__ - 3;
debugLog(ss.str());
ss.str("");
retVal = false;
}
}
else
{
retVal = false;
}
}
else
{
ss << "error allocating memory for " << fontname
<< ". file:" << __FILE__ << ", line: " << __LINE__ - 3;
debugLog(ss.str());
ss.str("");
retVal = false;
}
}
else
{
// file read error
return retVal;
}
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui_ImplSdlGL3_Init(handles.window);
io.DisplaySize.x = vp_dims.x;
io.DisplaySize.y = vp_dims.y;
ImGui::StyleColorsDark();
return retVal;
return true;
}
// TODO: global
struct
{
real32 R = 90.0f/255.0f;
real32 G = 90.0f/255.0f;
real32 B = 90.0f/255.0f;
} G_COLORS;
void
renderGooey(v2i screenDims)
shutdownGooey()
{
real32 x0 = (real32) gooey_extents.x0;
real32 y0 = (real32) gooey_extents.y0;
real32 x1 = (real32) gooey_extents.x1;
real32 y1 = (real32) gooey_extents.y1;
glColor4f(G_COLORS.R, G_COLORS.G, G_COLORS.B, 1);
glBegin(GL_QUADS);
glVertex2f(x0, y0);
glVertex2f(x1, y0);
glVertex2f(x1, y1);
glVertex2f(x0, y1);
glEnd();
for (uint32 i = 0; i < button_count; i++)
{
button b = button_array[i];
// render colored background of button
glColor4ub(
GLubyte((b.current_color & 0xFF000000) >> 24),
GLubyte((b.current_color & 0x00FF0000) >> 16),
GLubyte((b.current_color & 0x0000FF00) >> 8),
GLubyte((b.current_color & 0x000000FF))
);
glBegin(GL_QUADS);
glVertex2i(b.coords.x0, b.coords.y0);
glVertex2i(b.coords.x1, b.coords.y0);
glVertex2i(b.coords.x1, b.coords.y1);
glVertex2i(b.coords.x0, b.coords.y1);
glEnd();
setTextLine(line_buffer, b.text);
renderTextLine(line_buffer, (int32) strlen(b.text), (float) b.coords.x0,
(float) b.coords.y0, screenDims);
}
ImGui_ImplSdlGL3_Shutdown();
}
bool
gooeyHitTest(v2i screenCoords, v4i extents = gooey_extents)
{
if (screenCoords.x >= extents.x0 &&
screenCoords.y >= extents.y0 &&
screenCoords.x <= extents.x1 &&
screenCoords.y <= extents.y1)
{
return true;
}
return false;
}
HexDrawMode
gooeyPressButton(v2i screenCoords)
gooeyProcessEvent(SDL_Event &event)
{
// operate as a modal dialog
button *b;
HexDrawMode retVal = NONE;
for (uint32 i = 0; i < button_count; i++)
{
b = &button_array[i];
if (gooeyHitTest(screenCoords, b->coords))
{
b->selected = true;
b->current_color = 0xFFFFFFFF;
retVal = b->mode;
for (uint32 j = 0; j < button_count; j++)
{
if (i != j)
{
b = &button_array[j];
b->selected = false;
b->current_color = b->color;
}
}
break;
}
}
return retVal;
ImGui_ImplSdlGL3_ProcessEvent(&event);
return ImGui::GetIO().WantCaptureMouse;
}
void
freeGooey()
renderGooey(SDL_Handles &handles, HexDrawMode &mode)
{
if (font_filedata)
{
VirtualFree(font_filedata, 0, MEM_RELEASE);
}
ImGui_ImplSdlGL3_NewFrame(handles.window);
#if 0
ImGuiWindowFlags window_flags = 0;
window_flags |= ImGuiWindowFlags_NoTitleBar;
window_flags |= ImGuiWindowFlags_NoScrollbar;
window_flags |= ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoResize;
window_flags |= ImGuiWindowFlags_NoCollapse;
bool show_window;
ImGui::Begin("", &show_window, window_flags);
#endif
if (test_bitmap.bitmap_data)
{
VirtualFree(test_bitmap.bitmap_data, 0, MEM_RELEASE);
}
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
1000.0f / ImGui::GetIO().Framerate,
ImGui::GetIO().Framerate);
if (line_buffer)
{
VirtualFree(line_buffer, 0, MEM_RELEASE);
}
if (ImGui::Button("None"))
mode = NONE;
if (ImGui::Button("Fill"))
mode = FILL;
if (ImGui::Button("Line"))
mode = LINE;
if (ImGui::Button("Cone Fill"))
mode = CONE_FILL;
if (button_array)
{
VirtualFree(button_array, 0, MEM_RELEASE);
}
ImGui::Render();
}
#endif // GOOEY_H

26
src/hexgame.cpp

@ -12,6 +12,7 @@
#include "hexgame.h"
#include "hexlib.h"
#include "renderer.h"
#include "gooey.h"
using std::vector;
@ -404,6 +405,11 @@ enterLoop(SDL_Handles &handles)
while (SDL_PollEvent(&e))
{
// let gooey have event
// TODO: need to check for both io.WantCaptureKeyboard and io.WantCaptureMouse
// to fix bug with 'ESC' not passing through while in imgui
bool gooey_wants = gooeyProcessEvent(e);
switch (e.type)
{
case SDL_QUIT:
@ -414,14 +420,21 @@ enterLoop(SDL_Handles &handles)
quit = true;
break;
case SDL_MOUSEBUTTONDOWN:
if (!gooey_wants)
{
isSelecting = true;
handleMouseDown(e.button);
}
break;
case SDL_MOUSEBUTTONUP:
if (!gooey_wants)
{
isSelecting = false;
handleMouseUp(e.button);
}
break;
case SDL_MOUSEMOTION:
if (!gooey_wants)
handleMouseMove(e.motion);
break;
default:
@ -429,7 +442,10 @@ enterLoop(SDL_Handles &handles)
}
}
// TODO: move loop to main() and condense all these SDL event functions?
// something like a large processSDLEvents()
renderFrame(hexInfoArray);
renderGooey(handles, globalDrawMode);
SDL_GL_SwapWindow(handles.window);
}
@ -439,8 +455,7 @@ enterLoop(SDL_Handles &handles)
bool
cleanUp(SDL_Handles &handles)
{
// TODO: make a generic cleanup function that can free other types of SDL objects too
//freeGooey();
shutdownGooey();
freeBuffers(); // renderer.h
for (SDL_Surface *surface : handles.texSurfaces)
SDL_FreeSurface(surface);
@ -482,7 +497,12 @@ int main(int argc, char* argv[])
return 1;
}
// TODO: rewrite gooey
if (!initGooey(handles, viewportDims))
{
LOG(ERROR) << "Fooey, No Gooey!\n";
return 1;
}
enterLoop(handles);
cleanUp(handles);

13
src/renderer.h

@ -4,7 +4,11 @@
#include <vector>
#include <GL/glew.h>
// TODO: decide on extension library
//#include <GL/glew.h>
#include <GL/gl3w.h>
#include <SDL2/SDL.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
@ -132,11 +136,18 @@ initRenderer(SDL_Handles &handles, v2i vpDims)
// glewExperimental is only needed in GLEW <= 1.13.0
// we can require version 2.0.0+
//glewExperimental = true; // Needed for core profile
#if 0
GLenum err = glewInit();
if (err != GLEW_OK) {
LOG(ERROR) << "Failed to initilize GLEW" << glewGetErrorString(err) << "\n";
return false;
}
#endif
// TODO: remove for glew?
#if 1
gl3wInit();
#endif
LOG(INFO) << "opengl vendor: " << glGetString(GL_VENDOR) << "\n";
LOG(INFO)<< "opengl renderer: " << glGetString(GL_RENDERER) << "\n";

4061
src/stb_truetype.h

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save