Qt removed.

master
Jeremy Hu 2017-02-11 10:46:26 +09:30
parent 44bc0b4f5d
commit f5e0ca5b05
17 changed files with 1526 additions and 74 deletions

43
CMakeLists.txt Normal file
View File

@ -0,0 +1,43 @@
cmake_minimum_required(VERSION 2.8)
project(dust3d)
file(GLOB_RECURSE sources
src/glw_osx.m
src/glw_internal.h
src/glw_style.h
src/glw.c
src/glw.h
src/dmemory.h
src/dmemory.c
src/3dstruct.h
src/array.h
src/array.c
src/dict.h
src/dict.c
src/bmesh.h
src/bmesh.c
src/matrix.h
src/matrix.c
src/subdivide.h
src/subdivide.c
src/vector3d.h
src/vector3d.c
src/convexhull.h
src/convexhull.c
src/draw.h
src/draw.c
src/editor.c
)
IF(APPLE)
add_executable(dust3d MACOSX_BUNDLE ${sources})
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIRS})
target_link_libraries(dust3d ${OPENGL_LIBRARIES})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework AppKit -framework Quartz")
set_target_properties(dust3d PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/src/Info.plist)
install(TARGETS dust3d
DESTINATION ".")
ENDIF (APPLE)

View File

@ -10,25 +10,6 @@ I was inspired by Jimmy Gunawan's blogs of monster generation, here is the first
of 3D Articulated Shapes](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.357.7134&rep=rep1&type=pdf)(Authors: Zhongping Ji, Ligang Liu, Yigang Wang). I started to think of monster model generation for game development from years ago, thanks for this paper, Dust3D is achievable now.
From my initial thought, Dust3D should be a tool like [Makehuman](http://www.makehuman.org), with more versatile features, not only can make human, but also be able to **generate monsters automatically**.
Build
============
*Generate Xcode Project*
```
$ cd build
$ qmake -spec macx-xcode
```
*Generate VC Project*
```
$ cd build
$ qmake -tp vc
```
*Generate Makefile*
```
$ cd build
$ qmake
$ make
```
TODO & Progress
==============
- [x] Drawing Primitives (Dec 15, 2016 ~ Dec 17, 2016)
@ -83,7 +64,10 @@ This todo already done in the B-Mesh algorithm implementation.
**Feb 8, 2017:**
There are lots of changes to the UI part of Dust3D, though not commit yet because of many things have not been finalize.
I removed the Qt, the counterpart of the build system is CMake, and instead of using Qt based OpenGL windows, I am using my own implemented OpenGL support library. I considered using the most popular [Dear ImGui](https://github.com/ocornut/imgui) library, but I really want remove the C++ from the codebase. It's a good start of the skeleton editor UI!
<img src="screenshot/dust3d_imgui.png" width="280" height="266">
<img src="screenshot/dust3d_imgui.png" width="280" height="266">
**Feb 11, 2017:**
Qt removed, so C++ removed, but Objective-C imported for just support the OpenGL environment on OSX.
<img src="screenshot/dust3d_glw_preview.png" width="278" height="167">
- [ ] Render rigid animation
- [ ] png exporter for isometric 2.5D game

View File

@ -1,38 +0,0 @@
TARGET = dust3d
TEMPLATE = app
QT += widgets opengl
CONFIG += debug
VPATH += ../src
INCLUDEPATH += ../src
SOURCES += main.cpp \
mainwindow.cpp \
render.cpp \
vector3d.c \
draw.cpp \
array.c \
bmesh.c \
matrix.c \
convexhull.c \
dict.c \
osutil.cpp \
subdivide.c \
skinnedmesh.c \
dmemory.c
HEADERS += mainwindow.h \
render.h \
vector3d.h \
draw.h \
array.h \
bmesh.h \
matrix.h \
convexhull.h \
dict.h \
3dstruct.h \
osutil.h \
subdivide.h \
skinnedmesh.h \
dmemory.h

30
src/Info.plist Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 dust3d. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -11,7 +11,6 @@
#include "matrix.h"
#include "convexhull.h"
#include "subdivide.h"
#include "draw.h"
#define BMESH_MAX_PARENT_BALL_DEPTH 1000
#define BMESH_INTVAL_DIST_DIV 10
@ -547,10 +546,6 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
for (i = 0; i < arrayGetLength(ballPtrArray); ++i) {
bmeshBall *ballItem = *((bmeshBall **)arrayGetItem(ballPtrArray, i));
ballItem->convexHullCount++;
drawDebugPrintf("convexHullCount:%d", ballItem->convexHullCount);
if (ballItem->convexHullCount == 1) {
drawDebugPoint(&ballItem->position, ballItem->index);
}
}
arrayDestroy(ballPtrArray);
@ -727,7 +722,7 @@ static void bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace,
&childFace);
bmeshAddQuadToModel(bm, &childFace);
drawQuad(&childFace);
//drawQuad(&childFace);
}
}
else if (1 == ball->convexHullCount && !ball->meshGenerated) {

View File

@ -6,7 +6,6 @@
#include "convexhull.h"
#include "array.h"
#include "dict.h"
#include "draw.h"
//
// Implement Gift wrapping method which describled in http://dccg.upc.edu/people/vera/wp-content/uploads/2014/11/GA2014-ConvexHulls3D-Roger-Hernando.pdf

View File

@ -1,9 +1,8 @@
#include <QtGui>
#include <QtOpenGL>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include "draw.h"
static GLUquadricObj *quadricId = 0;
@ -88,8 +87,6 @@ int drawCylinder(vec3 *topOrigin, vec3 *bottomOrigin, float radius, int slices,
}
int drawGrid(float size, float step) {
glDisable(GL_LIGHTING);
// x z plane
glBegin(GL_LINES);
for (GLfloat i = -size; i <= size; i += step) {
@ -105,8 +102,6 @@ int drawGrid(float size, float step) {
}
}
glEnd();
glEnable(GL_LIGHTING);
return 0;
}
@ -115,7 +110,8 @@ int drawPrintf(int x, int y, const char *fmt, ...) {
char text[1024];
va_start(args, fmt);
vsnprintf(text, sizeof(text), fmt, args);
return drawText(x, y, text);
//return drawText(x, y, text);
return 0;
}
static const float drawDebugColors[][4] = {

View File

@ -12,6 +12,10 @@
extern "C" {
#endif
#ifndef M_PI
#define M_PI 3.14159265
#endif
int drawInit(void);
int drawSphere(vec3 *origin, float radius, int slices, int stacks);
void drawTriangle(triangle *poly);

229
src/editor.c Normal file
View File

@ -0,0 +1,229 @@
#ifdef __APPLE__
#include <OpenGL/glu.h>
#elif defined(_WIN32)
#include <windows.h>
#include <GL/glu.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "glw.h"
#include "glw_style.h"
#include "draw.h"
#include "bmesh.h"
#define GEN_ID __LINE__
#define ED_MODE_EDIT 0
#define ED_MODE_ANIMATION 1
#define ED_BACKGROUND_COLOR 0xe4e2e4
#define ED_SIDEBAR_WIDTH 400
#define ED_SPACING 10
#define ED_TOPBAR_HEIGHT 100
#define ED_TOOLBAR_HEIGHT 50
#define ED_GL_BACKGROUND_COLOR GLW_BACKGROUND_COLOR
typedef struct editor {
glwWin *win;
float cameraAngleX;
float cameraAngleY;
float cameraDistance;
int newImId;
int showBoneChecked;
int width;
int height;
int mode;
int glLeft;
int glTop;
int glWidth;
int glHeight;
int mouseX;
int mouseY;
bmesh *bm;
} editor;
#include "../data/bmesh_test_2.h"
static void display(glwWin *win) {
editor *ed = glwGetUserData(win);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, ed->width, ed->height, 0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
{
char *list[] = {"Open..", "New..", "Save As..", 0};
glwImButtonGroup(win, GEN_ID, 100, 30, 300, list, -1);
}
{
char *titles[] = {"Library", "Property", 0};
glwImTabBox(win, GEN_ID, ED_SPACING / 2, ED_TOPBAR_HEIGHT, ED_SIDEBAR_WIDTH,
ed->height - ED_TOPBAR_HEIGHT - ED_SPACING / 2,
titles, 0);
}
{
int x = ED_SPACING / 2 + ED_SIDEBAR_WIDTH + ED_SPACING;
int y = ED_TOPBAR_HEIGHT;
int width = ed->width - ED_SIDEBAR_WIDTH - ED_SPACING / 2 - ED_SPACING - ED_SPACING / 2;
int height = ed->height - ED_TOPBAR_HEIGHT - ED_SPACING / 2;
char *titles[] = {"Edit View", "Animation View", 0};
ed->mode = glwImTabBox(win, GEN_ID,
x, y, width, height,
titles, ed->mode);
if (ED_MODE_EDIT == ed->mode) {
int glWinY = glwImNextY(win);
int bottomY = y + height - ED_TOOLBAR_HEIGHT;
glwImBottomBar(win, GEN_ID, x, bottomY, width, ED_TOOLBAR_HEIGHT);
ed->showBoneChecked = glwImCheck(win, GEN_ID, x + ED_SPACING + ED_SPACING,
bottomY + (ED_TOOLBAR_HEIGHT - glwImLineHeight(win)) / 2 + 2,
"Show Bone",
ed->showBoneChecked);
ed->glLeft = x + 1;
ed->glTop = glWinY;
ed->glWidth = width - 3;
ed->glHeight = bottomY - glWinY;
if (0 == ed->bm) {
bmeshBall ball;
bmeshBone bone;
unsigned int i;
ed->bm = bmeshCreate();
for (i = 0; i < sizeof(bmeshTestBalls) / sizeof(bmeshTestBalls[0]); ++i) {
memset(&ball, 0, sizeof(ball));
ball.position.x = bmeshTestBalls[i][1];
ball.position.y = bmeshTestBalls[i][2];
ball.position.z = bmeshTestBalls[i][3];
ball.radius = bmeshTestBalls[i][4];
ball.type = bmeshTestBalls[i][5];
bmeshAddBall(ed->bm, &ball);
}
for (i = 0; i < sizeof(bmeshTestBones) / sizeof(bmeshTestBones[0]); ++i) {
memset(&bone, 0, sizeof(bone));
bone.firstBallIndex = bmeshTestBones[i][0];
bone.secondBallIndex = bmeshTestBones[i][1];
bmeshAddBone(ed->bm, &bone);
}
bmeshGenerate(ed->bm);
}
glEnable(GL_SCISSOR_TEST);
glScissor(ed->glLeft, ED_SPACING / 2 + ED_TOOLBAR_HEIGHT + 1,
ed->glWidth, ed->glHeight);
glPushMatrix();
glTranslatef(x + 1, glWinY, 0);
glColor3f(glwR(ED_GL_BACKGROUND_COLOR),
glwG(ED_GL_BACKGROUND_COLOR),
glwB(ED_GL_BACKGROUND_COLOR));
glRecti(0, 0, ed->glWidth, ed->glHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (float)ed->glWidth / ed->glHeight, 1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(0, 0, -ed->cameraDistance);
glRotatef(ed->cameraAngleX, 1, 0, 0);
glRotatef(ed->cameraAngleY, 0, 1, 0);
drawGrid(10, 1);
glEnable(GL_LIGHTING);
glEnable(GL_CULL_FACE);
bmeshDraw(ed->bm);
glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
glPopMatrix();
glPopMatrix();
glDisable(GL_SCISSOR_TEST);
}
}
}
static void reshape(glwWin *win, int width, int height) {
editor *ed = glwGetUserData(win);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHT0);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
ed->width = width;
ed->height = height;
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
//glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(glwR(ED_BACKGROUND_COLOR),
glwG(ED_BACKGROUND_COLOR),
glwB(ED_BACKGROUND_COLOR), 1);
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
}
static void mouse(glwWin *win, int button, int state,
int x, int y){
editor *ed = glwGetUserData(win);
if (!glwPointTest(x, y, ed->glLeft, ed->glTop,
ed->glWidth, ed->glHeight, 0)) {
return;
}
if (GLW_DOWN == state) {
ed->mouseX = x;
ed->mouseY = y;
}
}
static void motion(glwWin *win, int x, int y) {
editor *ed = glwGetUserData(win);
if (!glwPointTest(x, y, ed->glLeft, ed->glTop,
ed->glWidth, ed->glHeight, 0)) {
return;
}
ed->cameraAngleY += (x - ed->mouseX);
ed->cameraAngleX += (y - ed->mouseY);
ed->mouseX = x;
ed->mouseY = y;
}
int main(int argc, char *argv[]) {
editor ed;
glwInit();
memset(&ed, 0, sizeof(ed));
ed.cameraAngleX = 30;
ed.cameraAngleY = -312;
ed.cameraDistance = 14.4;
ed.win = glwCreateWindow(0, 0, 0, 0);
glwSetUserData(ed.win, &ed);
glwReshapeFunc(ed.win, reshape);
glwDisplayFunc(ed.win, display);
glwMouseFunc(ed.win, mouse);
glwMotionFunc(ed.win, motion);
glwMainLoop();
return 0;
}

690
src/glw.c Normal file
View File

@ -0,0 +1,690 @@
#include <OpenGL/gl.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "glw_internal.h"
#include "glw_style.h"
#ifndef M_PI
#define M_PI 3.14159265
#endif
void glwDrawSystemText(glwWin *win, int x, int y, char *text) {
int vleft, vwidth;
float tleft, twidth;
glwSystemFontTexture *systemFontTexture = glwGetSystemFontTexture(win);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, systemFontTexture->texId);
for (vleft = 0; *text; vleft += vwidth, text++) {
int idx = (*text) - GLW_SYSTEM_FONT_BEGIN_CHAR;
if (idx < 0 || idx > GLW_SYSTEM_FONT_CHAR_NUM) {
continue;
}
tleft = (float)systemFontTexture->lefts[idx] /
systemFontTexture->size.width;
vwidth = systemFontTexture->widths[idx];
twidth = (float)vwidth / systemFontTexture->originSize.width;
glBegin(GL_QUADS);
glTexCoord2f(tleft, 0);
glVertex2i(x + vleft, y);
glTexCoord2f(tleft + twidth, 0);
glVertex2i(x + vleft + vwidth, y);
glTexCoord2f(tleft + twidth, 1);
glVertex2i(x + vleft + vwidth, y + systemFontTexture->originSize.height);
glTexCoord2f(tleft, 1);
glVertex2i(x + vleft, y + systemFontTexture->originSize.height);
glEnd();
}
glDisable(GL_TEXTURE_2D);
}
void glwMouseEvent(glwWin *win, int button, int state, int x, int y) {
glwImGui *imGUI = glwGetImGUI(win);
imGUI->mouseButton = button;
imGUI->mouseState = state;
imGUI->mouseX = x;
imGUI->mouseY = y;
}
int glwPointTest(int x, int y, int left, int top, int width, int height,
int allowOffset) {
int right = left + width - 1 + allowOffset;
int bottom = top + height - 1 + allowOffset;
left -= allowOffset;
top -= allowOffset;
return x >= left && x <= right && y >= top && y <= bottom;
}
void glwInitSystemFontTexture(glwWin *win) {
char asciiTable[GLW_SYSTEM_FONT_CHAR_NUM + 1];
int i;
GLuint texture = 0;
glwFont *font;
int pixelsWide = 0;
int pixelsHigh = 0;
float scaleX, scaleY;
glwSystemFontTexture *systemFontTexture = glwGetSystemFontTexture(win);
for (i = 0; i <= GLW_SYSTEM_FONT_CHAR_NUM; ++i) {
asciiTable[i] = GLW_SYSTEM_FONT_BEGIN_CHAR + i;
}
asciiTable[GLW_SYSTEM_FONT_CHAR_NUM] = '\0';
font = glwCreateFont(GLW_SYSTEM_FONT_NAME, GLW_SYSTEM_FONT_WEIGHT,
GLW_SYSTEM_FONT_SIZE, 0);
systemFontTexture->lefts[0] = 0;
systemFontTexture->size.width = 0;
systemFontTexture->size.height = 0;
for (i = 0; i < GLW_SYSTEM_FONT_CHAR_NUM; ++i) {
char ch[2] = {asciiTable[i], '\0'};
glwSize chSize = glwMeasureText(ch, font);
if (chSize.height > systemFontTexture->size.height) {
systemFontTexture->size.height = chSize.height;
}
systemFontTexture->size.width += chSize.width;
systemFontTexture->widths[i] = chSize.width;
if (i > 0) {
systemFontTexture->lefts[i] = (float)(systemFontTexture->lefts[i - 1] +
systemFontTexture->widths[i - 1]);
}
}
systemFontTexture->originSize = systemFontTexture->size;
for (i = 0; i < GLW_SYSTEM_FONT_CHAR_NUM; ++i) {
char ch[2] = {asciiTable[i], '\0'};
glwSize chSize = {systemFontTexture->widths[i],
systemFontTexture->originSize.height};
unsigned char *rgba = glwRenderTextToRGBA(ch, font, chSize,
&pixelsWide, &pixelsHigh);
if (0 == i) {
scaleX = (float)pixelsWide / chSize.width;
scaleY = (float)pixelsHigh / chSize.height;
systemFontTexture->size.width *= scaleX;
systemFontTexture->size.height *= scaleY;
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, 4,
(GLsizei)(systemFontTexture->size.width),
(GLsizei)(systemFontTexture->size.height), 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
systemFontTexture->lefts[i] *= scaleX;
glTexSubImage2D(GL_TEXTURE_2D, 0,
systemFontTexture->lefts[i], 0,
(GLsizei)pixelsWide,
(GLsizei)pixelsHigh,
GL_RGBA, GL_UNSIGNED_BYTE, rgba);
free(rgba);
}
systemFontTexture->texId = (int)texture;
glwDestroyFont(font);
}
static glwVec2 glwRoundedCorners[GLW_SMALL_ROUNDED_CORNER_SLICES] = {{0}};
static void createRoundedCorners(glwVec2 *arr, int num) {
float slice = M_PI / 2 / num;
int i;
float a = 0;
for (i = 0; i < num; a += slice, ++i) {
arr[i].x = cosf(a);
arr[i].y = sinf(a);
}
}
void glwInitPrimitives(void) {
createRoundedCorners(glwRoundedCorners, GLW_SMALL_ROUNDED_CORNER_SLICES);
}
static void glwDrawRightTopVertexs(float left, float top, float right,
float bottom, float radius) {
int i;
for (i = GLW_SMALL_ROUNDED_CORNER_SLICES - 1; i >= 0; --i) {
glVertex2f(right - radius + radius * glwRoundedCorners[i].x,
top + radius - radius * glwRoundedCorners[i].y);
}
}
static void glwDrawRightBottomVertexs(float left, float top, float right,
float bottom, float radius) {
int i;
for (i = 0; i < GLW_SMALL_ROUNDED_CORNER_SLICES; ++i) {
glVertex2f(right - radius + radius * glwRoundedCorners[i].x,
bottom - radius + radius * glwRoundedCorners[i].y);
}
}
static void glwDrawLeftBottomVertexs(float left, float top, float right,
float bottom, float radius) {
int i;
for (i = GLW_SMALL_ROUNDED_CORNER_SLICES - 1; i >= 0; --i) {
glVertex2f(left + radius - radius * glwRoundedCorners[i].x,
bottom - radius + radius * glwRoundedCorners[i].y);
}
}
static void glwDrawLeftTopVertexs(float left, float top, float right,
float bottom, float radius) {
int i;
for (i = 0; i < GLW_SMALL_ROUNDED_CORNER_SLICES; ++i) {
glVertex2f(left + radius - radius * glwRoundedCorners[i].x,
top + radius - radius * glwRoundedCorners[i].y);
}
}
void glwDrawCheckSymbol(int x, int y, int width, int height,
unsigned int color) {
glColor3f(glwR(color), glwG(color), glwB(color));
glLineWidth(2);
glBegin(GL_LINE_STRIP);
glVertex2f(x + width * 0.15, y + height * 0.3);
glVertex2f(x + width * 0.45, y + height * 0.65);
glVertex2f(x + width * 1.05, y - height * 0.05);
glEnd();
glLineWidth(1);
}
void glwDrawDropdownArrow(int x, int y, int width, int height,
unsigned int color) {
glColor3f(glwR(color), glwG(color), glwB(color));
glBegin(GL_TRIANGLES);
glVertex2f(x, y);
glVertex2f(x + width, y);
glVertex2f(x + width * 0.5, y + height);
glEnd();
}
void glwDrawVLine(int x, int y, int width, int height,
unsigned int color) {
glColor3f(glwR(color), glwG(color), glwB(color));
glLineWidth(width);
glBegin(GL_LINES);
glVertex2f(x, y);
glVertex2f(x, y + height - 1);
glEnd();
glLineWidth(1);
}
void glwDrawHLine(int x, int y, int width, int height,
unsigned int color) {
glColor3f(glwR(color), glwG(color), glwB(color));
glLineWidth(height);
glBegin(GL_LINES);
glVertex2f(x, y);
glVertex2f(x + width - 1, y);
glEnd();
glLineWidth(1);
}
void glwDrawRoundedRectBorder(float x, float y, float width, float height,
float radius, unsigned int color) {
float left = x;
float top = y;
float bottom = y + height - 1;
float right = x + width - 1;
glDisable(GL_TEXTURE_2D);
glColor3f(glwR(color), glwG(color), glwB(color));
glBegin(GL_LINE_LOOP);
glVertex2f(left, top + radius);
glwDrawLeftTopVertexs(left, top, right, bottom, radius);
glVertex2f(left + radius, top);
glVertex2f(right - radius, top);
glwDrawRightTopVertexs(left, top, right, bottom, radius);
glVertex2f(right, top + radius);
glVertex2f(right, bottom - radius);
glwDrawRightBottomVertexs(left, top, right, bottom, radius);
glVertex2f(right - radius, bottom);
glVertex2f(left + radius, bottom);
glwDrawLeftBottomVertexs(left, top, right, bottom, radius);
glVertex2f(left, bottom - radius);
glEnd();
}
void glwDrawTopRoundedRectBorder(float x, float y, float width, float height,
float radius, unsigned int color) {
float left = x;
float top = y;
float bottom = y + height - 1;
float right = x + width - 1;
glDisable(GL_TEXTURE_2D);
glColor3f(glwR(color), glwG(color), glwB(color));
glBegin(GL_LINE_LOOP);
glVertex2f(left, top + radius);
glwDrawLeftTopVertexs(left, top, right, bottom, radius);
glVertex2f(left + radius, top);
glVertex2f(right - radius, top);
glwDrawRightTopVertexs(left, top, right, bottom, radius);
glVertex2f(right, top + radius);
glVertex2f(right, bottom);
glVertex2f(left, bottom);
glEnd();
}
void glwDrawLeftRoundedRectGradientFill(float x, float y,
float width, float height,
float radius, unsigned int topColor, unsigned int bottomColor) {
float left = x;
float top = y;
float bottom = y + height - 1;
float right = x + width - 1;
int i;
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUAD_STRIP);
for (i = 0; i < GLW_SMALL_ROUNDED_CORNER_SLICES; ++i) {
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(left + radius - radius * glwRoundedCorners[i].x,
bottom - radius + radius * glwRoundedCorners[i].y);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(left + radius - radius * glwRoundedCorners[i].x,
top + radius - radius * glwRoundedCorners[i].y);
}
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(right, bottom);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(right, top);
glEnd();
}
void glwDrawTopRoundedRectGradientFill(float x, float y,
float width, float height,
float radius, unsigned int topColor, unsigned int bottomColor) {
float left = x;
float top = y;
float bottom = y + height - 1;
float right = x + width - 1;
int i;
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUAD_STRIP);
for (i = 0; i < GLW_SMALL_ROUNDED_CORNER_SLICES; ++i) {
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(left + radius - radius * glwRoundedCorners[i].x,
bottom);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(left + radius - radius * glwRoundedCorners[i].x,
top + radius - radius * glwRoundedCorners[i].y);
}
for (i = GLW_SMALL_ROUNDED_CORNER_SLICES - 1; i >= 0; --i) {
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(right - radius + radius * glwRoundedCorners[i].x,
bottom);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(right - radius + radius * glwRoundedCorners[i].x,
top + radius - radius * glwRoundedCorners[i].y);
}
glEnd();
}
void glwDrawRectGradientFill(float x, float y,
float width, float height,
unsigned int topColor, unsigned int bottomColor) {
float left = x;
float top = y;
float bottom = y + height - 1;
float right = x + width - 1;
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUAD_STRIP);
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(left, bottom);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(left, top);
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(right, bottom);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(right, top);
glEnd();
}
void glwDrawRightRoundedRectGradientFill(float x, float y,
float width, float height,
float radius, unsigned int topColor, unsigned int bottomColor) {
float left = x;
float top = y;
float bottom = y + height - 1;
float right = x + width - 1;
int i;
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUAD_STRIP);
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(left, bottom);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(left, top);
for (i = GLW_SMALL_ROUNDED_CORNER_SLICES - 1; i >= 0; --i) {
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(right - radius + radius * glwRoundedCorners[i].x,
bottom - radius + radius * glwRoundedCorners[i].y);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(right - radius + radius * glwRoundedCorners[i].x,
top + radius - radius * glwRoundedCorners[i].y);
}
glEnd();
}
void glwDrawRoundedRectGradientFill(float x, float y, float width, float height,
float radius, unsigned int topColor, unsigned int bottomColor) {
float left = x;
float top = y;
float bottom = y + height - 1;
float right = x + width - 1;
int i;
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUAD_STRIP);
for (i = 0; i < GLW_SMALL_ROUNDED_CORNER_SLICES; ++i) {
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(left + radius - radius * glwRoundedCorners[i].x,
bottom - radius + radius * glwRoundedCorners[i].y);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(left + radius - radius * glwRoundedCorners[i].x,
top + radius - radius * glwRoundedCorners[i].y);
}
for (i = GLW_SMALL_ROUNDED_CORNER_SLICES - 1; i >= 0; --i) {
glColor3f(glwR(bottomColor), glwG(bottomColor), glwB(bottomColor));
glVertex2f(right - radius + radius * glwRoundedCorners[i].x,
bottom - radius + radius * glwRoundedCorners[i].y);
glColor3f(glwR(topColor), glwG(topColor), glwB(topColor));
glVertex2f(right - radius + radius * glwRoundedCorners[i].x,
top + radius - radius * glwRoundedCorners[i].y);
}
glEnd();
}
void glwDrawButtonBackground(float x, float y, float width, float height,
glwCtrlState state) {
switch (state)
{
case GLW_CTRL_STATE_PRESS:
glwDrawRoundedRectGradientFill(x, y, width, height,
GLW_BUTTON_CORNER_RADIUS,
GLW_FILL_GRADIENT_COLOR_1_H, GLW_FILL_GRADIENT_COLOR_2_H);
break;
case GLW_CTRL_STATE_NORMAL:
default:
glwDrawRoundedRectGradientFill(x, y, width, height,
GLW_BUTTON_CORNER_RADIUS,
GLW_FILL_GRADIENT_COLOR_1, GLW_FILL_GRADIENT_COLOR_2);
break;
}
glwDrawRoundedRectBorder(x, y, width, height,
GLW_BUTTON_CORNER_RADIUS, GLW_BORDER_COLOR_2);
}
glwSize glwMeasureSystemText(glwWin *win, char *text) {
glwSystemFontTexture *systemFontTexture = glwGetSystemFontTexture(win);
glwSize size = {0, systemFontTexture->originSize.height};
for (; *text; text++) {
int idx = (*text) - GLW_SYSTEM_FONT_BEGIN_CHAR;
if (idx < 0 || idx > GLW_SYSTEM_FONT_CHAR_NUM) {
continue;
}
size.width += systemFontTexture->widths[idx];
}
return size;
}
static void glwImGUIActiveIdCheck(glwImGui *imGUI, int id, int x, int y,
int width, int height) {
if (GLW_DOWN == imGUI->mouseState) {
if (!imGUI->activeId) {
int hit = glwPointTest(imGUI->mouseX, imGUI->mouseY, x, y,
width, height, 0);
if (hit) {
imGUI->activeId = id;
}
}
} else if (GLW_UP == imGUI->mouseState) {
if (imGUI->activeId == id) {
imGUI->activeId = 0;
}
}
}
int glwImButton(glwWin *win, int id, int x, int y, char *text) {
glwImGui *imGUI = glwGetImGUI(win);
glwSize textSize = glwMeasureSystemText(win, text);
int width = textSize.width * (1 + GLW_HOR_AUTO_MARGIN * 2);
int height = textSize.height * (1 + GLW_VER_AUTO_MARGIN * 2);
glwImGUIActiveIdCheck(imGUI, id, x, y, width, height);
glwDrawButtonBackground(x, y, width, height,
imGUI->activeId == id ? GLW_CTRL_STATE_PRESS : GLW_CTRL_STATE_NORMAL);
glwDrawSystemText(win, x + textSize.width * GLW_HOR_AUTO_MARGIN,
y + textSize.height * GLW_VER_AUTO_MARGIN,
text);
imGUI->nextX = x + width;
imGUI->nextY = y;
return imGUI->activeId == id;
}
int glwImDropdownBox(glwWin *win, int id, int x, int y, char *text) {
glwImGui *imGUI = glwGetImGUI(win);
glwSize textSize = glwMeasureSystemText(win, text);
int arrowHeight = textSize.height * 0.3;
int arrowWidth = arrowHeight * 2;
int width = textSize.width * (1 + GLW_HOR_AUTO_MARGIN * 2) + arrowWidth * 3;
int height = textSize.height * (1 + GLW_VER_AUTO_MARGIN * 2);
glwImGUIActiveIdCheck(imGUI, id, x, y, width, height);
glwDrawButtonBackground(x, y, width, height,
imGUI->activeId == id ? GLW_CTRL_STATE_PRESS : GLW_CTRL_STATE_NORMAL);
glwDrawSystemText(win, x + textSize.width * (GLW_HOR_AUTO_MARGIN),
y + textSize.height * (GLW_VER_AUTO_MARGIN),
text);
glwDrawDropdownArrow(x + width - textSize.width * GLW_HOR_AUTO_MARGIN -
arrowWidth,
y + (height - arrowHeight) / 2, arrowWidth, arrowHeight, 0);
imGUI->nextX = x + width;
imGUI->nextY = y;
return imGUI->activeId == id;
}
int glwImCheck(glwWin *win, int id, int x, int y, char *text, int checked) {
glwImGui *imGUI = glwGetImGUI(win);
glwSize textSize = glwMeasureSystemText(win, text);
int height = textSize.height;
int boxWidth = height;
int width = boxWidth + textSize.height * (1 + GLW_HOR_AUTO_MARGIN * 2) +
textSize.width;
int oldActiveId = imGUI->activeId;
glwImGUIActiveIdCheck(imGUI, id, x, y, width, height);
glwDrawButtonBackground(x, y, boxWidth, height,
(imGUI->activeId == id || checked) ?
GLW_CTRL_STATE_PRESS : GLW_CTRL_STATE_NORMAL);
glwDrawSystemText(win, x + textSize.height * GLW_HOR_AUTO_MARGIN + boxWidth,
y, text);
if (checked) {
glwDrawCheckSymbol(x, y, boxWidth, height, GLW_CHECK_COLOR);
}
imGUI->nextX = x + width;
imGUI->nextY = y;
return (imGUI->activeId == id && oldActiveId != id) ? !checked : checked;
}
static int glwCalcListMaxWidth(glwWin *win, char **list, int *height,
int *len) {
int i;
int itemWidth = 0;
int maxItemWidth = 0;
for (i = 0; list[i]; ++i) {
glwSize textSize = glwMeasureSystemText(win, list[i]);
itemWidth = textSize.width * (1 + GLW_HOR_AUTO_MARGIN * 2);
if (itemWidth > maxItemWidth) {
maxItemWidth = itemWidth;
}
if (height && !(*height)) {
*height = textSize.height * (1 + GLW_VER_AUTO_MARGIN * 2);
}
if (len) {
++(*len);
}
}
return maxItemWidth;
}
int glwImButtonGroup(glwWin *win, int id, int x, int y, int parentWidth,
char **list, int sel) {
glwImGui *imGUI = glwGetImGUI(win);
int width = 0;
int height = 0;
int left = 0;
int i;
int listLen = 0;
int offset;
int maxItemWidth = 0;
maxItemWidth = glwCalcListMaxWidth(win, list, &height, &listLen);
width = maxItemWidth * listLen;
left = listLen > 1 ? x + (parentWidth - width) / 2 :
x + maxItemWidth * GLW_HOR_AUTO_MARGIN;
glwImGUIActiveIdCheck(imGUI, id, left, y, width, height);
glwDrawRoundedRectGradientFill(left, y, width, height,
GLW_BUTTON_CORNER_RADIUS,
GLW_FILL_GRADIENT_COLOR_1, GLW_FILL_GRADIENT_COLOR_2);
for (i = 0, offset = left; list[i]; ++i) {
glwSize textSize = glwMeasureSystemText(win, list[i]);
if (imGUI->activeId == id) {
int hit = glwPointTest(imGUI->mouseX, imGUI->mouseY, offset, y,
maxItemWidth, height, 0);
if (hit) {
sel = i;
}
}
if (sel == i) {
if (1 == listLen) {
glwDrawRoundedRectGradientFill(left, y, width, height,
GLW_BUTTON_CORNER_RADIUS,
GLW_FILL_GRADIENT_COLOR_1_H, GLW_FILL_GRADIENT_COLOR_2_H);
} else {
if (0 == i) {
glwDrawLeftRoundedRectGradientFill(offset, y,
maxItemWidth, height,
GLW_BUTTON_CORNER_RADIUS,
GLW_FILL_GRADIENT_COLOR_1_H, GLW_FILL_GRADIENT_COLOR_2_H);
} else if (listLen - 1 == i) {
glwDrawRightRoundedRectGradientFill(offset, y,
maxItemWidth, height,
GLW_BUTTON_CORNER_RADIUS,
GLW_FILL_GRADIENT_COLOR_1_H, GLW_FILL_GRADIENT_COLOR_2_H);
} else {
glwDrawRectGradientFill(offset, y,
maxItemWidth, height,
GLW_FILL_GRADIENT_COLOR_1_H, GLW_FILL_GRADIENT_COLOR_2_H);
}
}
}
if (0 != i) {
glwDrawVLine(offset, y, 1, height, GLW_BORDER_COLOR_2);
}
glwDrawSystemText(win, offset + (maxItemWidth - textSize.width) / 2,
y + height * 0.1, list[i]);
offset += maxItemWidth;
}
imGUI->nextX = offset;
imGUI->nextY = y;
glwDrawRoundedRectBorder(left, y, width, height,
GLW_BUTTON_CORNER_RADIUS, GLW_BORDER_COLOR_2);
return sel;
}
int glwImTabBox(glwWin *win, int id, int x, int y, int width, int height,
char **list, int sel) {
glwImGui *imGUI = glwGetImGUI(win);
int tabWidth = 0;
int tabHeight = 0;
int left = 0;
int i;
int listLen = 0;
int offset;
int maxItemWidth = 0;
maxItemWidth = glwCalcListMaxWidth(win, list, &tabHeight, &listLen);
tabWidth = maxItemWidth * listLen;
left = x + maxItemWidth * GLW_HOR_AUTO_MARGIN / 2;
imGUI->nextX = x;
imGUI->nextY = y + tabHeight;
glwImGUIActiveIdCheck(imGUI, id, left, y, tabWidth, tabHeight);
for (i = 0, offset = left; list[i]; ++i) {
glwSize textSize = glwMeasureSystemText(win, list[i]);
if (imGUI->activeId == id) {
int hit = glwPointTest(imGUI->mouseX, imGUI->mouseY, offset, y,
maxItemWidth, tabHeight, 0);
if (hit) {
sel = i;
}
}
if (sel == i) {
glwDrawTopRoundedRectGradientFill(offset, y,
maxItemWidth, tabHeight,
GLW_BUTTON_CORNER_RADIUS,
GLW_TAB_FILL_GRADIENT_COLOR_1, GLW_TAB_FILL_GRADIENT_COLOR_2);
glwDrawTopRoundedRectBorder(offset, y,
maxItemWidth, tabHeight,
GLW_BUTTON_CORNER_RADIUS, GLW_BORDER_COLOR_1);
}
glwDrawSystemText(win, offset + (maxItemWidth - textSize.width) / 2,
y + tabHeight * GLW_VER_AUTO_MARGIN, list[i]);
offset += maxItemWidth;
}
glwDrawRectGradientFill(x + 1, y + tabHeight,
width - 2, height - tabHeight - 2,
GLW_BACKGROUND_COLOR, GLW_BACKGROUND_COLOR);
glwDrawHLine(x, y + tabHeight - 1, width, 1, GLW_BORDER_COLOR_1);
glwDrawHLine(x, y + height - 1, width, 1, GLW_BORDER_COLOR_1);
glwDrawVLine(x, y + tabHeight, 1, height - tabHeight,
GLW_BORDER_COLOR_1);
glwDrawVLine(x + width - 1, y + tabHeight, 1, height - tabHeight,
GLW_BORDER_COLOR_1);
return sel;
}
int glwImPanel(glwWin *win, int id, int x, int y, int width, int height) {
glwDrawRectGradientFill(x, y, width, height,
GLW_PANEL_FILL_COLOR, GLW_PANEL_FILL_COLOR);
glwDrawRoundedRectBorder(x, y, width, height,
GLW_BUTTON_CORNER_RADIUS, GLW_BORDER_COLOR_1);
return 0;
}
int glwImToolBar(glwWin *win, int id, int x, int y, int width, int height) {
glwImGui *imGUI = glwGetImGUI(win);
glwDrawRectGradientFill(x + 1, y + 1, width - 2, height - 2,
GLW_TOOLBAR_BACKGROUND_COLOR, GLW_TOOLBAR_BACKGROUND_COLOR);
glwDrawHLine(x, y + height - 1, width, 1, GLW_BORDER_COLOR_1);
imGUI->nextX = x;
imGUI->nextY = y + height;
return 0;
}
int glwImBottomBar(glwWin *win, int id, int x, int y, int width, int height) {
glwImGui *imGUI = glwGetImGUI(win);
glwDrawRectGradientFill(x + 1, y + 1, width - 2, height - 2,
GLW_TOOLBAR_BACKGROUND_COLOR, GLW_TOOLBAR_BACKGROUND_COLOR);
glwDrawHLine(x, y, width, 1, GLW_BORDER_COLOR_1);
imGUI->nextX = x;
imGUI->nextY = y - height;
return 0;
}
int glwImNextX(glwWin *win) {
glwImGui *imGUI = glwGetImGUI(win);
return imGUI->nextX;
}
int glwImNextY(glwWin *win) {
glwImGui *imGUI = glwGetImGUI(win);
return imGUI->nextY;
}
int glwImLineHeight(glwWin *win) {
glwSystemFontTexture *systemFontTexture = glwGetSystemFontTexture(win);
return systemFontTexture->originSize.height * (1 + GLW_VER_AUTO_MARGIN * 2);
}

70
src/glw.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef GLW_H
#define GLW_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct glwSize {
int width;
int height;
} glwSize;
typedef struct glwVec2 {
float x;
float y;
} glwVec2;
typedef struct glwWin glwWin;
typedef struct glwFont glwFont;
#define GLW_LEFT_BUTTON 1
#define GLW_MIDDLE_BUTTON 2
#define GLW_RIGHT_BUTTON 3
#define GLW_DOWN 1
#define GLW_UP 2
void glwInit(void);
void glwMainLoop(void);
glwWin *glwCreateWindow(int x, int y, int width, int height);
glwWin *glwCreateSubWindow(glwWin *parent, int x, int y, int width, int height);
void glwSetUserData(glwWin *win, void *userData);
void *glwGetUserData(glwWin *win);
void glwDestroyWindow(glwWin *win);
void glwSetWindowTitle(glwWin *win, char *name);
void glwPositionWindow(glwWin *win, int x, int y);
void glwReshapeWindow(glwWin *win, int width, int height);
void glwDisplayFunc(glwWin *win, void (*func)(glwWin *win));
void glwReshapeFunc(glwWin *win, void (*func)(glwWin *win, int width,
int height));
void glwKeyboardFunc(glwWin *win, void (*func)(glwWin *win, unsigned char key,
int x, int y));
void glwMouseFunc(glwWin *win, void (*func)(glwWin *win, int button, int state,
int x, int y));
void glwMotionFunc(glwWin *win, void (*func)(glwWin *win, int x, int y));
void glwPassiveMotionFunc(glwWin *win, void (*func)(glwWin *win, int x, int y));
#define glwR(rgb) ((float)(((rgb) >> 16) & 0xff) / 255)
#define glwG(rgb) ((float)(((rgb) >> 8) & 0xff) / 255)
#define glwB(rgb) ((float)(((rgb)) & 0xff) / 255)
int glwImButton(glwWin *win, int id, int x, int y, char *text);
int glwImCheck(glwWin *win, int id, int x, int y, char *text, int checked);
int glwImDropdownBox(glwWin *win, int id, int x, int y, char *text);
int glwImButtonGroup(glwWin *win, int id, int x, int y, int parentWidth,
char **list, int sel);
int glwImPanel(glwWin *win, int id, int x, int y, int width, int height);
int glwImTabBox(glwWin *win, int id, int x, int y, int width, int height,
char **list, int sel);
int glwImToolBar(glwWin *win, int id, int x, int y, int width, int height);
int glwImBottomBar(glwWin *win, int id, int x, int y, int width, int height);
int glwImNextX(glwWin *win);
int glwImNextY(glwWin *win);
int glwImLineHeight(glwWin *win);
int glwPointTest(int x, int y, int left, int top, int width, int height,
int allowOffset);
#ifdef __cplusplus
}
#endif
#endif

54
src/glw_internal.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef GLW_INTERNAL_H
#define GLW_INTERNAL_H
#include "glw.h"
#include "glw_style.h"
#define GLW_SYSTEM_FONT_BEGIN_CHAR ' '
#define GLW_SYSTEM_FONT_END_CHAR '~'
#define GLW_SYSTEM_FONT_CHAR_NUM (GLW_SYSTEM_FONT_END_CHAR - GLW_SYSTEM_FONT_BEGIN_CHAR + 1)
#define GLW_TEXT_ALIGN_LEFT 0
#define GLW_TEXT_ALIGN_CENTER 1
#define GLW_TEXT_ALIGN_RIGHT 2
typedef enum glwCtrlState {
GLW_CTRL_STATE_NORMAL,
GLW_CTRL_STATE_PRESS,
} glwCtrlState;
typedef struct glwSystemFontTexture {
int texId;
glwSize size;
glwSize originSize;
float lefts[GLW_SYSTEM_FONT_CHAR_NUM];
int widths[GLW_SYSTEM_FONT_CHAR_NUM];
} glwSystemFontTexture;
typedef struct glwImGui {
int mouseButton;
int mouseState;
int mouseX;
int mouseY;
int activeId;
int nextX;
int nextY;
} glwImGui;
glwSize glwMeasureText(char *text, glwFont *font);
unsigned char *glwRenderTextToRGBA(char *text, glwFont *font, glwSize size,
int *pixelsWide, int *pixelsHigh);
void glwDrawText(int x, int y, char *text, glwFont *font);
void glwDrawSystemText(glwWin *win, int x, int y, char *text);
glwSize glwMeasureSystemText(glwWin *win, char *text);
void glwInitSystemFontTexture(glwWin *win);
void glwInitPrimitives(void);
glwSystemFontTexture *glwGetSystemFontTexture(glwWin *win);
void glwDestroyFont(glwFont *font);
glwFont *glwCreateFont(char *name, int weight, int size, int bold);
void glwDestroyFont(glwFont *font);
void glwDrawButtonBackground(float x, float y, float width, float height,
glwCtrlState state);
void glwMouseEvent(glwWin *win, int button, int state, int x, int y);
glwImGui *glwGetImGUI(glwWin *win);
#endif

345
src/glw_osx.m Normal file
View File

@ -0,0 +1,345 @@
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#import <OpenGL/gl.h>
#include "glw_internal.h"
@interface GLView : NSOpenGLView <NSWindowDelegate> {
CVDisplayLinkRef displayLink;
@public
void (*onReshape)(glwWin *win, int width, int height);
void (*onDisplay)(glwWin *win);
void (*onMouse)(glwWin *win, int button, int state, int x, int y);
void (*onMotion)(glwWin *win, int x, int y);
void (*onPassiveMotion)(glwWin *win, int x, int y);
void *userData;
int pendingReshape;
int viewWidth;
int viewHeight;
float scaleX;
float scaleY;
glwSystemFontTexture systemFontTexture;
glwImGui imGUI;
}
- (CVReturn)getFrameForTime:(const CVTimeStamp *)outputTime;
- (void)drawFrame;
@end
static CVReturn onDisplayLinkCallback(CVDisplayLinkRef displayLink,
const CVTimeStamp *now, const CVTimeStamp *outputTime,
CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext)
{
CVReturn result = [(GLView *)displayLinkContext getFrameForTime:outputTime];
return result;
}
glwSystemFontTexture *glwGetSystemFontTexture(glwWin *win) {
GLView *view = ((NSWindow *)win).contentView;
return &view->systemFontTexture;
}
@implementation GLView
- (id)initWithFrame:(NSRect)frameRect {
NSOpenGLPixelFormatAttribute attribs[] = {NSOpenGLPFAMultisample,
NSOpenGLPFASampleBuffers, 1,
NSOpenGLPFASamples, 0,
NSOpenGLPFAAccelerated,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAColorSize, 32,
NSOpenGLPFADepthSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
0};
NSOpenGLPixelFormat *windowedPixelFormat = [[NSOpenGLPixelFormat alloc]
initWithAttributes:attribs];
self = [super initWithFrame:frameRect pixelFormat:windowedPixelFormat];
[windowedPixelFormat release];
[self setWantsBestResolutionOpenGLSurface:YES];
return self;
}
- (void) prepareOpenGL {
[super prepareOpenGL];
GLint vblSynch = 1;
[[self openGLContext] setValues:&vblSynch
forParameter:NSOpenGLCPSwapInterval];
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
CVDisplayLinkSetOutputCallback(displayLink, onDisplayLinkCallback, self);
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink,
[[self openGLContext] CGLContextObj],
[[self pixelFormat] CGLPixelFormatObj]);
CVDisplayLinkStart(displayLink);
}
- (void)drawFrame {
@autoreleasepool {
NSOpenGLContext *currentContext = [self openGLContext];
[currentContext makeCurrentContext];
CGLLockContext([currentContext CGLContextObj]);
if (self->pendingReshape) {
if (self->onReshape) {
self->pendingReshape = 0;
if (!self->systemFontTexture.texId) {
glwInitSystemFontTexture((glwWin *)self.window);
}
self->onReshape((glwWin *)self.window, self->viewWidth,
self->viewHeight);
}
}
if (self->onDisplay) {
self->onDisplay((glwWin *)self.window);
}
CGLFlushDrawable([[self openGLContext] CGLContextObj]);
CGLUnlockContext([currentContext CGLContextObj]);
}
}
- (CVReturn)getFrameForTime:(const CVTimeStamp *)outputTime {
[self drawFrame];
return kCVReturnSuccess;
}
- (void)dealloc {
CVDisplayLinkRelease(displayLink);
[super dealloc];
}
- (BOOL)acceptsFirstResponder {
return YES;
}
- (void)reshape {
NSRect bounds = [self bounds];
NSRect backingBounds = [self convertRectToBacking:[self bounds]];
viewWidth = (int)backingBounds.size.width;
viewHeight = (int)backingBounds.size.height;
self->scaleX = (float)viewWidth / bounds.size.width;
self->scaleY = (float)viewHeight / bounds.size.height;
self->pendingReshape = 1;
[self drawFrame];
}
- (void)resumeDisplayRenderer {
NSOpenGLContext *currentContext = [self openGLContext];
[currentContext makeCurrentContext];
CGLLockContext([currentContext CGLContextObj]);
CVDisplayLinkStart(displayLink);
CGLUnlockContext([currentContext CGLContextObj]);
}
- (void)haltDisplayRenderer {
NSOpenGLContext *currentContext = [self openGLContext];
[currentContext makeCurrentContext];
CGLLockContext([currentContext CGLContextObj]);
CVDisplayLinkStop(displayLink);
CGLUnlockContext([currentContext CGLContextObj]);
}
- (void)mouseMoved:(NSEvent*)event {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
int x = loc.x * self->scaleX;
int y = loc.y * self->scaleY;
if (GLW_DOWN == self->imGUI.mouseState) {
if (self->onMotion) {
self->onMotion((glwWin *)self.window, x, y);
}
} else {
if (self->onPassiveMotion) {
self->onPassiveMotion((glwWin *)self.window, x, y);
}
}
}
- (void)mouseDown:(NSEvent*)event {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
int x = loc.x * self->scaleX;
int y = loc.y * self->scaleY;
glwMouseEvent((glwWin *)self.window, GLW_LEFT_BUTTON, GLW_DOWN, x, y);
if (self->onMouse) {
self->onMouse((glwWin *)self.window, GLW_LEFT_BUTTON, GLW_DOWN, x, y);
}
}
- (void)mouseDragged:(NSEvent *)event {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
int x = loc.x * self->scaleX;
int y = loc.y * self->scaleY;
if (GLW_DOWN == self->imGUI.mouseState) {
if (GLW_DOWN == self->imGUI.mouseState) {
if (self->onMotion) {
self->onMotion((glwWin *)self.window, x, y);
}
} else {
if (self->onPassiveMotion) {
self->onPassiveMotion((glwWin *)self.window, x, y);
}
}
} else {
glwMouseEvent((glwWin *)self.window, GLW_LEFT_BUTTON, GLW_DOWN, x, y);
if (self->onMouse) {
self->onMouse((glwWin *)self.window, GLW_LEFT_BUTTON, GLW_DOWN, x, y);
}
}
}
- (BOOL)isFlipped {
return YES;
}
- (void)mouseUp:(NSEvent*)event {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
int x = loc.x * self->scaleX;
int y = loc.y * self->scaleY;
glwMouseEvent((glwWin *)self.window, GLW_LEFT_BUTTON, GLW_UP, x, y);
if (self->onMouse) {
self->onMouse((glwWin *)self.window, GLW_LEFT_BUTTON, GLW_UP, x, y);
}
}
@end
glwImGui *glwGetImGUI(glwWin *win) {
GLView *view = ((NSWindow *)win).contentView;
return &view->imGUI;
}
glwFont *glwCreateFont(char *name, int weight, int size, int bold) {
NSString *fontFamily = [NSString stringWithCString:name
encoding:NSMacOSRomanStringEncoding];
NSFont *font = [[[NSFontManager sharedFontManager] fontWithFamily:fontFamily
traits:(bold ? NSBoldFontMask : NSUnboldFontMask) weight:weight size:size] retain];
return (glwFont *)font;
}
glwSize glwMeasureText(char *text, glwFont *font) {
NSString *aString = [NSString stringWithCString:text
encoding:NSMacOSRomanStringEncoding];
NSSize frameSize = [aString sizeWithAttributes:
[NSDictionary dictionaryWithObject:(NSFont *)font forKey:NSFontAttributeName]];
glwSize size = {frameSize.width, frameSize.height};
return size;
}
void glwInit(void) {
[NSApplication sharedApplication];
glwInitPrimitives();
}
void glwMainLoop(void) {
@autoreleasepool {
[NSApp run];
}
}
void glwSetUserData(glwWin *win, void *userData) {
GLView *view = ((NSWindow *)win).contentView;
view->userData = userData;
}
void *glwGetUserData(glwWin *win) {
GLView *view = ((NSWindow *)win).contentView;
return view->userData;
}
glwWin *glwCreateWindow(int x, int y, int width, int height) {
NSUInteger windowStyle = NSTitledWindowMask | NSClosableWindowMask |
NSResizableWindowMask | NSMiniaturizableWindowMask;
NSRect fullRect = [[NSScreen mainScreen] visibleFrame];
if (0 == width || 0 == height) {
width = fullRect.size.width;
height = fullRect.size.height;
}
NSRect viewRect = NSMakeRect(0, 0, width, height);
NSRect windowRect = NSMakeRect(x, y, width, height);
NSWindow *window = [[NSWindow alloc] initWithContentRect:windowRect
styleMask:windowStyle
backing:NSBackingStoreBuffered
defer:NO];
GLView *view = [[GLView alloc] initWithFrame:viewRect];
view->onReshape = 0;
view->onDisplay = 0;
view->onMouse = 0;
view->userData = 0;
view->pendingReshape = 0;
view->viewWidth = width;
view->viewHeight = height;
view->systemFontTexture.texId = 0;
memset(&view->imGUI, 0, sizeof(view->imGUI));
view->scaleX = 1;
view->scaleY = 1;
view->onPassiveMotion = 0;
view->onMotion = 0;
[window setAcceptsMouseMovedEvents:YES];
[window setContentView:view];
[window setDelegate:view];
[window orderFrontRegardless];
return (glwWin *)window;
}
void glwDisplayFunc(glwWin *win, void (*func)(glwWin *win)) {
GLView *view = ((NSWindow *)win).contentView;
view->onDisplay = func;
}
void glwReshapeFunc(glwWin *win, void (*func)(glwWin *win, int width,
int height)) {
GLView *view = ((NSWindow *)win).contentView;
view->onReshape = func;
}
void glwMouseFunc(glwWin *win, void (*func)(glwWin *win, int button, int state,
int x, int y)) {
GLView *view = ((NSWindow *)win).contentView;
view->onMouse = func;
}
void glwMotionFunc(glwWin *win,
void (*func)(glwWin *win, int x, int y)) {
GLView *view = ((NSWindow *)win).contentView;
view->onMotion = func;
}
void glwPassiveMotionFunc(glwWin *win,
void (*func)(glwWin *win, int x, int y)) {
GLView *view = ((NSWindow *)win).contentView;
view->onPassiveMotion = func;
}
unsigned char *glwRenderTextToRGBA(char *text, glwFont *font, glwSize size,
int *pixelsWide, int *pixelsHigh) {
NSString *aString = [NSString stringWithCString:text encoding:NSMacOSRomanStringEncoding];
NSSize frameSize = NSMakeSize(size.width, size.height);
NSImage *image = [[NSImage alloc] initWithSize:frameSize];
unsigned char *rgba = 0;
int rgbaBytes = 0;
[image lockFocus];
[aString drawAtPoint:NSMakePoint(0, 0) withAttributes:
[NSDictionary dictionaryWithObject:(NSFont *)font forKey:NSFontAttributeName]];
[image unlockFocus];
NSBitmapImageRep *bitmap = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
*pixelsWide = [bitmap pixelsWide];
*pixelsHigh = [bitmap pixelsHigh];
rgbaBytes = 4 * (*pixelsWide) * (*pixelsHigh);
rgba = malloc(rgbaBytes);
memcpy(rgba, [bitmap bitmapData], rgbaBytes);
[image release];
return rgba;
}
void glwDestroyFont(glwFont *font) {
NSFont *nsFont = (NSFont *)font;
[nsFont release];
}

37
src/glw_style.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef GLW_STYLE_H
#define GLW_STYLE_H
#define GLW_SYSTEM_FONT_NAME "Helvetica"
#define GLW_SYSTEM_FONT_WEIGHT 5
#define GLW_SYSTEM_FONT_SIZE 20
#define GLW_SMALL_ROUNDED_CORNER_SLICES 5
#define GLW_BORDER_COLOR_1 0xa2a2a2
#define GLW_BORDER_COLOR_2 0x616161
#define GLW_FILL_GRADIENT_COLOR_1 0xffffff
#define GLW_FILL_GRADIENT_COLOR_2 0xc6c4c5
#define GLW_FILL_GRADIENT_COLOR_1_H 0x3795fa
#define GLW_FILL_GRADIENT_COLOR_2_H 0x333333
#define GLW_BUTTON_CORNER_RADIUS 5
#define GLW_CHECK_COLOR 0x000000
#define GLW_TAB_FILL_GRADIENT_COLOR_1 0xffffff
#define GLW_TAB_FILL_GRADIENT_COLOR_2 0xc6c4c5
#define GLW_TAB_FILL_GRADIENT_COLOR_1_H 0x3795fa
#define GLW_TAB_FILL_GRADIENT_COLOR_2_H 0x333333
#define GLW_PANEL_FILL_COLOR 0xe2e2e2
#define GLW_HOR_AUTO_MARGIN 0.4
#define GLW_VER_AUTO_MARGIN 0.15
#define GLW_BACKGROUND_COLOR 0xfcfcfc
#define GLW_TOOLBAR_BACKGROUND_COLOR 0xf5f5f5
#endif

View File

@ -13,9 +13,14 @@ typedef struct skinnedMeshVertex {
} skinnedMeshVertex;
typedef struct skinnedMeshBone {
vec3 translation;
vec3 position;
vec3 rotation;
matrix toRoot;
} skinnedMeshBone;
typedef struct skinnedMesh skinnedMesh;
skinnedMesh *skinnedMeshCreate(void);
void skinnedMeshAddBone();
#endif

View File

@ -1,5 +1,6 @@
#include "osutil.h"
#include <QDateTime>
#include <QGLWidget>
#include "osutil.h"
long long osGetMilliseconds(void) {
return (long long)QDateTime::currentMSecsSinceEpoch();

View File

@ -5,8 +5,16 @@
extern "C" {
#endif
#include <math.h>
long long osGetMilliseconds(void);
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define unsued(param) (void)param
#ifdef __cplusplus
}
#endif