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. 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**. 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 TODO & Progress
============== ==============
- [x] Drawing Primitives (Dec 15, 2016 ~ Dec 17, 2016) - [x] Drawing Primitives (Dec 15, 2016 ~ Dec 17, 2016)
@ -84,6 +65,9 @@ This todo already done in the B-Mesh algorithm implementation.
There are lots of changes to the UI part of Dust3D, though not commit yet because of many things have not been finalize. 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! 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 - [ ] Render rigid animation
- [ ] png exporter for isometric 2.5D game - [ ] 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 "matrix.h"
#include "convexhull.h" #include "convexhull.h"
#include "subdivide.h" #include "subdivide.h"
#include "draw.h"
#define BMESH_MAX_PARENT_BALL_DEPTH 1000 #define BMESH_MAX_PARENT_BALL_DEPTH 1000
#define BMESH_INTVAL_DIST_DIV 10 #define BMESH_INTVAL_DIST_DIV 10
@ -547,10 +546,6 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
for (i = 0; i < arrayGetLength(ballPtrArray); ++i) { for (i = 0; i < arrayGetLength(ballPtrArray); ++i) {
bmeshBall *ballItem = *((bmeshBall **)arrayGetItem(ballPtrArray, i)); bmeshBall *ballItem = *((bmeshBall **)arrayGetItem(ballPtrArray, i));
ballItem->convexHullCount++; ballItem->convexHullCount++;
drawDebugPrintf("convexHullCount:%d", ballItem->convexHullCount);
if (ballItem->convexHullCount == 1) {
drawDebugPoint(&ballItem->position, ballItem->index);
}
} }
arrayDestroy(ballPtrArray); arrayDestroy(ballPtrArray);
@ -727,7 +722,7 @@ static void bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace, bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace,
&childFace); &childFace);
bmeshAddQuadToModel(bm, &childFace); bmeshAddQuadToModel(bm, &childFace);
drawQuad(&childFace); //drawQuad(&childFace);
} }
} }
else if (1 == ball->convexHullCount && !ball->meshGenerated) { else if (1 == ball->convexHullCount && !ball->meshGenerated) {

View File

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

View File

@ -12,6 +12,10 @@
extern "C" { extern "C" {
#endif #endif
#ifndef M_PI
#define M_PI 3.14159265
#endif
int drawInit(void); int drawInit(void);
int drawSphere(vec3 *origin, float radius, int slices, int stacks); int drawSphere(vec3 *origin, float radius, int slices, int stacks);
void drawTriangle(triangle *poly); 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; } skinnedMeshVertex;
typedef struct skinnedMeshBone { typedef struct skinnedMeshBone {
vec3 translation; vec3 position;
vec3 rotation; vec3 rotation;
matrix toRoot; matrix toRoot;
} skinnedMeshBone; } skinnedMeshBone;
typedef struct skinnedMesh skinnedMesh;
skinnedMesh *skinnedMeshCreate(void);
void skinnedMeshAddBone();
#endif #endif

View File

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

View File

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