complete rewrite
This commit is contained in:
parent
b60e3a0ef6
commit
8a717a2b2e
41 changed files with 2625 additions and 1255 deletions
298
client/gl.c
298
client/gl.c
|
|
@ -1,298 +0,0 @@
|
|||
#include <af_common.h>
|
||||
|
||||
#define SHADOW_WIDTH 1024
|
||||
#define SHADOW_HEIGHT 1024
|
||||
|
||||
double gl_cam_lr = 0;
|
||||
double gl_cam_ud = 0;
|
||||
double gl_cam_x;
|
||||
double gl_cam_y;
|
||||
double gl_cam_z;
|
||||
|
||||
int gl_scene = AF_SCENE_MAIN;
|
||||
|
||||
GLuint gl_shadow;
|
||||
|
||||
static GLuint shadow_texture;
|
||||
|
||||
gl_scene_t gl_scenes[] = {
|
||||
{gl_main_changed, gl_main_init, gl_main_draw, gl_main_after}, /**/
|
||||
{NULL, NULL, NULL, NULL} /**/
|
||||
};
|
||||
|
||||
static char gl_status[256];
|
||||
|
||||
void gl_resize(int width, int height) {
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
void gl_init(void) {
|
||||
GLfloat lightamb[] = {0.25, 0.25, 0.25, 1.0};
|
||||
GLfloat lightcol[] = {1.0, 1.0, 1.0, 1.0};
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_NORMALIZE);
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, lightamb);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightcol);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, lightcol);
|
||||
|
||||
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
|
||||
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
gl_font_init();
|
||||
|
||||
gl_status[0] = 0;
|
||||
|
||||
glGenTextures(1, &shadow_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
if(gl_shader(&gl_shadow, DATAROOTDIR "/assaultfish/shadow.vs", DATAROOTDIR "/assaultfish/shadow.fs")) {
|
||||
glUseProgram(gl_shadow);
|
||||
glUniform1i(glGetUniformLocation(gl_shadow, "texture"), 1);
|
||||
glUniform1i(glGetUniformLocation(gl_shadow, "texture_in"), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void gl_cube(double x, double y, double z, double xs, double ys, double zs, double xr, double yr, double zr) {
|
||||
int i;
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, z);
|
||||
glScalef(xs, ys, zs);
|
||||
glRotatef(xr, 1, 0, 0);
|
||||
glRotatef(yr, 0, 1, 0);
|
||||
glRotatef(zr, 0, 0, 1);
|
||||
for(i = 0; i < 6; i++) {
|
||||
glBegin(GL_QUADS);
|
||||
glNormal3f(0, 0, 1);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3f(-0.5, 0.5, 0.5);
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex3f(-0.5, -0.5, 0.5);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex3f(0.5, -0.5, 0.5);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex3f(0.5, 0.5, 0.5);
|
||||
glEnd();
|
||||
|
||||
if(i == 3) {
|
||||
glRotatef(90, 1, 0, 0);
|
||||
} else if(i == 4) {
|
||||
glRotatef(180, 1, 0, 0);
|
||||
} else {
|
||||
glRotatef(90, 0, 1, 0);
|
||||
}
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
static void gl_common(void) {
|
||||
char buf1[128];
|
||||
char buf2[128];
|
||||
int l;
|
||||
gl_util_begin_2d();
|
||||
|
||||
glColor4f(0, 0, 0, 0.5);
|
||||
sprintf(buf1, "AssaultFish %s", AF_VERSION);
|
||||
sprintf(buf2, "%s", AF_COPYRIGHT);
|
||||
|
||||
l = gl_font_width(buf1);
|
||||
if(l < gl_font_width(buf2)) l = gl_font_width(buf2);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(MwGetInteger(opengl, MwNwidth) - l, MwGetInteger(opengl, MwNheight) - gl_font_height(buf1) - gl_font_height(buf2));
|
||||
glVertex2f(MwGetInteger(opengl, MwNwidth) - l, MwGetInteger(opengl, MwNheight));
|
||||
glVertex2f(MwGetInteger(opengl, MwNwidth), MwGetInteger(opengl, MwNheight));
|
||||
glVertex2f(MwGetInteger(opengl, MwNwidth), MwGetInteger(opengl, MwNheight) - gl_font_height(buf1) - gl_font_height(buf2));
|
||||
glEnd();
|
||||
|
||||
glColor3f(1, 1, 1);
|
||||
|
||||
gl_font_text(buf1, MwGetInteger(opengl, MwNwidth) - gl_font_width(buf1), MwGetInteger(opengl, MwNheight) - gl_font_height(buf1) - gl_font_height(buf2), 1);
|
||||
|
||||
gl_font_text(buf2, MwGetInteger(opengl, MwNwidth) - gl_font_width(buf2), MwGetInteger(opengl, MwNheight) - gl_font_height(buf2), 1);
|
||||
|
||||
gl_font_text(gl_status, 0, 0, 1);
|
||||
|
||||
gl_util_end_2d();
|
||||
}
|
||||
|
||||
static void scene(void) {
|
||||
if(gl_scenes[gl_scene].draw != NULL) gl_scenes[gl_scene].draw();
|
||||
}
|
||||
|
||||
void gl_render(void) {
|
||||
GLfloat lightpos[4] = {2.5, 5, -2.5, 1};
|
||||
GLint viewport[4];
|
||||
GLdouble modelview[16];
|
||||
GLdouble modelview2[16];
|
||||
|
||||
if(gl_scenes[gl_scene].init != NULL) gl_scenes[gl_scene].init();
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glGetIntegerv(GL_VIEWPORT, &viewport[0]);
|
||||
|
||||
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
gluPerspective(60, (double)SHADOW_WIDTH / SHADOW_HEIGHT, 0.01, 100.0);
|
||||
gluLookAt(lightpos[0], lightpos[1], lightpos[2], 0, 0, 0, 0, 1, 0);
|
||||
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, &modelview[0]);
|
||||
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
scene();
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_texture);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(60, (double)MwGetInteger(opengl, MwNwidth) / MwGetInteger(opengl, MwNheight), 0.01, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
gluLookAt(gl_cam_x, gl_cam_y, gl_cam_z, gl_cam_x + cos(gl_cam_lr / 180.0 * M_PI), gl_cam_y + sin(gl_cam_ud / 180.0 * M_PI), gl_cam_z + sin(gl_cam_lr / 180.0 * M_PI), 0, 1, 0);
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, &modelview2[0]);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslated(0.5, 0.5, 0.5);
|
||||
glScaled(0.5, 0.5, 0.5);
|
||||
glMultMatrixd(modelview);
|
||||
glMultMatrixd(modelview2);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_texture);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
|
||||
|
||||
scene();
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
gl_common();
|
||||
|
||||
if(gl_scenes[gl_scene].after != NULL) gl_scenes[gl_scene].after();
|
||||
}
|
||||
|
||||
void gl_scene_change(void) {
|
||||
if(gl_scenes[gl_scene].changed != NULL) gl_scenes[gl_scene].changed();
|
||||
|
||||
gl_status[0] = 0;
|
||||
}
|
||||
|
||||
void gl_set_status(const char* status) {
|
||||
strcpy(gl_status, status);
|
||||
}
|
||||
|
||||
static void cross(double* out, double v00, double v01, double v02, double v10, double v11, double v12) {
|
||||
out[0] = v01 * v12 - v02 * v11;
|
||||
out[1] = v02 * v10 - v00 * v12;
|
||||
out[2] = v00 * v11 - v01 * v10;
|
||||
}
|
||||
|
||||
/*
|
||||
* v0-v2
|
||||
* | /
|
||||
* v1/
|
||||
*/
|
||||
void gl_calc_normal3(double* out, double v00, double v01, double v02, double v10, double v11, double v12, double v20, double v21, double v22) {
|
||||
double v[3];
|
||||
double l = 0;
|
||||
int i;
|
||||
|
||||
cross(&v[0], /**/
|
||||
v10 - v00, v11 - v01, v12 - v02, /**/
|
||||
v20 - v00, v21 - v01, v22 - v02 /**/
|
||||
);
|
||||
|
||||
l = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||
|
||||
for(i = 0; i < 3; i++) {
|
||||
out[i] = v[i] / l;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* v0-v3
|
||||
* | |
|
||||
* v1-v2
|
||||
*/
|
||||
void gl_calc_normal4(double* out, double v00, double v01, double v02, double v10, double v11, double v12, double v20, double v21, double v22, double v30, double v31, double v32) {
|
||||
double v0[3];
|
||||
double v1[3];
|
||||
int i;
|
||||
double l = 0;
|
||||
|
||||
gl_calc_normal3(&v0[0], v00, v01, v02, v10, v11, v12, v30, v31, v32);
|
||||
gl_calc_normal3(&v1[0], v10, v11, v12, v20, v21, v22, v30, v31, v32);
|
||||
|
||||
for(i = 0; i < 3; i++) {
|
||||
out[i] = v0[i] + v1[i];
|
||||
}
|
||||
|
||||
l = sqrt(out[0] * out[0] + out[1] * out[1] + out[2] * out[2]);
|
||||
|
||||
for(i = 0; i < 3; i++) {
|
||||
out[i] = out[i] / l;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
#include <af_common.h>
|
||||
|
||||
#include <stb_image.h>
|
||||
|
||||
static GLuint font_atlas;
|
||||
static int font_width = 0, font_height = 0;
|
||||
|
||||
void gl_font_init(void) {
|
||||
unsigned int ch;
|
||||
unsigned char* data = stbi_load(DATAROOTDIR "/assaultfish/font.png", &font_width, &font_height, &ch, 4);
|
||||
|
||||
glGenTextures(1, &font_atlas);
|
||||
glBindTexture(GL_TEXTURE_2D, font_atlas);
|
||||
if(data != NULL) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, font_width, font_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
free(data);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void gl_font_text(const char* text, int x, int y, double scale) {
|
||||
int i;
|
||||
int gw = font_width / 16 * scale, gh = font_height / 16 * scale;
|
||||
int is = glIsEnabled(GL_TEXTURE_2D) ? 1 : 0;
|
||||
|
||||
gl_util_begin_2d();
|
||||
|
||||
if(!is) glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, font_atlas);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
for(i = 0; text[i] != 0; i++) {
|
||||
double bx = 1.0 / 16 * (text[i] % 16), by = 1.0 / 16 * (text[i] / 16);
|
||||
|
||||
glTexCoord2f(bx, by);
|
||||
glVertex2f(i * gw + x, y);
|
||||
glTexCoord2f(bx + 1.0 / 16, by);
|
||||
glVertex2f(i * gw + x + gw, y);
|
||||
glTexCoord2f(bx + 1.0 / 16, by + 1.0 / 16);
|
||||
glVertex2f(i * gw + x + gw, y + gh);
|
||||
glTexCoord2f(bx, by + 1.0 / 16);
|
||||
glVertex2f(i * gw + x, y + gh);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
if(!is) glDisable(GL_TEXTURE_2D);
|
||||
|
||||
gl_util_end_2d();
|
||||
}
|
||||
|
||||
int gl_font_width(const char* text) {
|
||||
return font_width / 16 * strlen(text);
|
||||
}
|
||||
|
||||
int gl_font_height(const char* text) {
|
||||
return font_height / 16;
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
#include <af_common.h>
|
||||
|
||||
#include <stb_image.h>
|
||||
|
||||
static double rad;
|
||||
|
||||
void gl_main_changed(void) {
|
||||
rad = 0;
|
||||
}
|
||||
|
||||
void gl_main_init(void) {
|
||||
gl_cam_x = 0;
|
||||
gl_cam_y = 0;
|
||||
gl_cam_z = -1;
|
||||
|
||||
gl_cam_lr = 90;
|
||||
gl_cam_ud = 0;
|
||||
}
|
||||
|
||||
void gl_main_draw(void) {
|
||||
int i;
|
||||
|
||||
glUniform1f(glGetUniformLocation(gl_shadow, "solid_color"), 1);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(rad, 1, 0, 0);
|
||||
glRotatef(rad, 0, 1, 0);
|
||||
glRotatef(rad, 0, 0, 1);
|
||||
for(i = 0; i < 8; i++) {
|
||||
int c = (i % 2) == 0 ? 1 : 0;
|
||||
double n[3];
|
||||
double u = 0.3;
|
||||
|
||||
gl_calc_normal3(&n[0], 0, u * 1.4, 0, -u, 0, u, u, 0, u);
|
||||
|
||||
glColor3f(c ? 0.75 : 0, 0, c ? 0 : 0.75);
|
||||
glBegin(GL_TRIANGLES);
|
||||
|
||||
glNormal3f(n[0], n[1], n[2]);
|
||||
glVertex3f(0, u * 1.4, 0);
|
||||
glVertex3f(-u, 0, u);
|
||||
glVertex3f(u, 0, u);
|
||||
glEnd();
|
||||
glRotatef(90, 0, 1, 0);
|
||||
if(i == 3) {
|
||||
glRotatef(180, 0, 0, 1);
|
||||
glRotatef(90, 0, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glColor3f(1, 1, 1);
|
||||
glBegin(GL_QUADS);
|
||||
glNormal3f(0, 1, 0);
|
||||
glVertex3f(-5, -1, -5);
|
||||
glVertex3f(-5, -1, 5);
|
||||
glVertex3f(5, -1, 5);
|
||||
glVertex3f(5, -1, -5);
|
||||
glEnd();
|
||||
|
||||
glUniform1f(glGetUniformLocation(gl_shadow, "solid_color"), 0);
|
||||
}
|
||||
|
||||
void gl_main_after(void) {
|
||||
rad += 60.0 / (1000.0 / AF_WAIT_MS);
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
#include <af_common.h>
|
||||
|
||||
static void err(const char* path, GLuint shader) {
|
||||
GLint len, ret;
|
||||
char* e;
|
||||
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
|
||||
|
||||
e = malloc(len);
|
||||
e[len] = 0;
|
||||
|
||||
glGetShaderInfoLog(shader, len, &ret, e);
|
||||
|
||||
fprintf(stderr, "%s: %s\n", path, e);
|
||||
|
||||
free(e);
|
||||
}
|
||||
|
||||
int gl_shader(GLuint* r, const char* vs, const char* fs) {
|
||||
GLuint vsi;
|
||||
GLuint fsi;
|
||||
FILE* f;
|
||||
int vsl = 0;
|
||||
int fsl = 0;
|
||||
char* vss;
|
||||
char* fss;
|
||||
GLint st;
|
||||
|
||||
if((f = fopen(vs, "rb")) != NULL) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
vsl = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
vss = malloc(vsl + 1);
|
||||
fread(vss, vsl, 1, f);
|
||||
vss[vsl] = 0;
|
||||
|
||||
fclose(f);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((f = fopen(fs, "rb")) != NULL) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
fsl = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
fss = malloc(fsl + 1);
|
||||
fread(fss, fsl, 1, f);
|
||||
fss[fsl] = 0;
|
||||
|
||||
fclose(f);
|
||||
} else {
|
||||
free(vss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
vsi = glCreateShader(GL_VERTEX_SHADER);
|
||||
fsi = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
glShaderSource(vsi, 1, (const GLchar**)&vss, NULL);
|
||||
glShaderSource(fsi, 1, (const GLchar**)&fss, NULL);
|
||||
|
||||
glCompileShader(vsi);
|
||||
glGetShaderiv(vsi, GL_COMPILE_STATUS, &st);
|
||||
if(!st) {
|
||||
err(vs, vsi);
|
||||
|
||||
glDeleteShader(vsi);
|
||||
glDeleteShader(fsi);
|
||||
free(vss);
|
||||
free(fss);
|
||||
return 0;
|
||||
}
|
||||
|
||||
glCompileShader(fsi);
|
||||
glGetShaderiv(fsi, GL_COMPILE_STATUS, &st);
|
||||
if(!st) {
|
||||
err(fs, fsi);
|
||||
|
||||
glDeleteShader(vsi);
|
||||
glDeleteShader(fsi);
|
||||
free(vss);
|
||||
free(fss);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(vss);
|
||||
free(fss);
|
||||
|
||||
*r = glCreateProgram();
|
||||
|
||||
glAttachShader(*r, vsi);
|
||||
glAttachShader(*r, fsi);
|
||||
|
||||
glDeleteShader(vsi);
|
||||
glDeleteShader(fsi);
|
||||
|
||||
glLinkProgram(*r);
|
||||
glGetProgramiv(*r, GL_LINK_STATUS, &st);
|
||||
if(!st) {
|
||||
glDeleteProgram(*r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#include <af_common.h>
|
||||
|
||||
void gl_util_begin_2d(void) {
|
||||
glUseProgram(0);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0, MwGetInteger(opengl, MwNwidth), MwGetInteger(opengl, MwNheight), 0, -1, 1);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
void gl_util_end_2d(void) {
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glUseProgram(gl_shadow);
|
||||
}
|
||||
103
client/main.c
103
client/main.c
|
|
@ -1,103 +0,0 @@
|
|||
#include <af_common.h>
|
||||
|
||||
MwWidget root, window, opengl;
|
||||
|
||||
static const MwRect sizes[] = {
|
||||
{0, 0, 640, 480},
|
||||
{0, 0, 800, 600},
|
||||
{0, 0, 1024, 768},
|
||||
{0, 0, 1280, 1024},
|
||||
};
|
||||
|
||||
static void resize(MwWidget handle, void* user, void* client) {
|
||||
int ww = MwGetInteger(window, MwNwidth);
|
||||
int wh = MwGetInteger(window, MwNheight);
|
||||
|
||||
MwVaApply(opengl,
|
||||
MwNwidth, ww,
|
||||
MwNheight, wh,
|
||||
NULL);
|
||||
|
||||
gl_resize(ww, wh);
|
||||
}
|
||||
|
||||
static void tick(MwWidget handle, void* user, void* client) {
|
||||
net_poll();
|
||||
|
||||
gl_render();
|
||||
|
||||
MwOpenGLSwapBuffer(opengl);
|
||||
}
|
||||
|
||||
static void* gl_load(const char* name) {
|
||||
return MwOpenGLGetProcAddress(opengl, name);
|
||||
}
|
||||
|
||||
void scene_change(int scene) {
|
||||
gl_scene = scene;
|
||||
|
||||
gl_scene_change();
|
||||
ui_scene_change();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MwSizeHints sh;
|
||||
MwRect rc;
|
||||
int i;
|
||||
|
||||
MwLibraryInit();
|
||||
|
||||
root = MwVaCreateWidget(NULL, "root", NULL, 0, 0, 0, 0,
|
||||
MwNwaitMS, AF_WAIT_MS,
|
||||
MwNbitmapFont, 0,
|
||||
MwNmodernLook, 1,
|
||||
NULL);
|
||||
|
||||
window = MwVaCreateWidget(MwWindowClass, "main", root, 0, 0, 640, 480,
|
||||
MwNtitle, "AssaultFish",
|
||||
NULL);
|
||||
|
||||
MwGetScreenSize(window, &rc);
|
||||
|
||||
for(i = sizeof(sizes) / sizeof(sizes[0]) - 1; i >= 0; i--) {
|
||||
if(sizes[i].width < rc.width && sizes[i].height < rc.height) {
|
||||
sh.min_width = sh.max_width = sizes[i].width;
|
||||
sh.min_height = sh.max_height = sizes[i].height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 1; i < argc; i++) {
|
||||
if(strcmp(argv[i], "--width") == 0 && (i + 1) < argc) {
|
||||
sh.min_width = sh.max_width = atoi(argv[i + 1]);
|
||||
} else if(strcmp(argv[i], "--height") == 0 && (i + 1) < argc) {
|
||||
sh.min_height = sh.max_height = atoi(argv[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
MwVaApply(window,
|
||||
MwNsizeHints, &sh,
|
||||
MwNx, (rc.width - sh.max_width) / 2,
|
||||
MwNy, (rc.height - sh.max_height) / 2,
|
||||
MwNwidth, sh.max_width,
|
||||
MwNheight, sh.max_height,
|
||||
NULL);
|
||||
|
||||
opengl = MwCreateWidget(MwOpenGLClass, "opengl", window, 0, 0, sh.max_width, sh.max_height);
|
||||
|
||||
MwOpenGLMakeCurrent(opengl);
|
||||
|
||||
gladLoadGLLoader(gl_load);
|
||||
|
||||
resize(window, NULL, NULL);
|
||||
|
||||
gl_init();
|
||||
ui_init();
|
||||
|
||||
scene_change(AF_SCENE_MAIN);
|
||||
|
||||
MwAddUserHandler(window, MwNresizeHandler, resize, NULL);
|
||||
MwAddUserHandler(root, MwNtickHandler, tick, NULL);
|
||||
|
||||
MwLoop(root);
|
||||
}
|
||||
107
client/net.c
107
client/net.c
|
|
@ -1,107 +0,0 @@
|
|||
#include <af_common.h>
|
||||
|
||||
static fishsoup_client_t* client = NULL;
|
||||
|
||||
enum OPAQUE_STATES {
|
||||
OPAQUE_WAITING_HELLO = 0,
|
||||
OPAQUE_JOINING
|
||||
};
|
||||
|
||||
typedef struct opaque {
|
||||
char username[256];
|
||||
int state;
|
||||
} opaque_t;
|
||||
|
||||
static void net_return(MwWidget handle, void* user, void* client) {
|
||||
scene_change(AF_SCENE_MAIN);
|
||||
}
|
||||
|
||||
static void on_packet(fishsoup_client_t* self, fishsoup_packet_t* pkt) {
|
||||
opaque_t* o = self->user;
|
||||
|
||||
if(pkt->header.type == AF_PACKET_HELLO && pkt->header.length == sizeof(af_packet_hello_t) && o->state == OPAQUE_WAITING_HELLO) {
|
||||
af_packet_hello_t* p_hello = pkt->data;
|
||||
unsigned char mj, mi, pt;
|
||||
|
||||
af_common_version(&mj, &mi, &pt);
|
||||
|
||||
af_common_log_info("HELLO packet: Server version %hhu.%hhu.%hhu\n", p_hello->major, p_hello->minor, p_hello->patch);
|
||||
|
||||
if(mj == p_hello->major && mi >= p_hello->minor && (mi == p_hello->minor ? (pt >= p_hello->patch) : (1))) {
|
||||
fishsoup_packet_t p;
|
||||
af_packet_join_t p_join;
|
||||
|
||||
af_common_log_info("Server version is compatible with this client\n");
|
||||
|
||||
p.header.type = AF_PACKET_JOIN;
|
||||
p.header.length = sizeof(p_join);
|
||||
p.data = &p_join;
|
||||
|
||||
memcpy(p_join.username, o->username, 256);
|
||||
|
||||
fishsoup_packet_send(self->fd, &p);
|
||||
|
||||
o->state = OPAQUE_JOINING;
|
||||
|
||||
gl_set_status("Joining");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
af_common_log_info("Server version is incompatible with this client\n");
|
||||
MwAddUserHandler(ui_message("Server version is incompatible with this client"), MwNactivateHandler, net_return, NULL);
|
||||
fishsoup_client_destroy(self);
|
||||
client = NULL;
|
||||
} else if(pkt->header.type == AF_PACKET_OK && pkt->header.length == sizeof(af_packet_ok_t) && o->state == OPAQUE_JOINING) {
|
||||
af_packet_ok_t* p_ok = pkt->data;
|
||||
|
||||
af_common_log_info("OK Packet: Joined successfully\n");
|
||||
|
||||
gl_set_status("Downloading data");
|
||||
} else if(pkt->header.type == AF_PACKET_ERROR && pkt->header.length == sizeof(af_packet_error_t) && o->state == OPAQUE_JOINING) {
|
||||
af_packet_error_t* p_error = pkt->data;
|
||||
|
||||
af_common_log_info("ERROR Packet: Failed to join\n");
|
||||
|
||||
fishsoup_client_destroy(self);
|
||||
client = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void on_disconnect(fishsoup_client_t* self) {
|
||||
free(self->user);
|
||||
}
|
||||
|
||||
void net_connect(const char* username, const char* hostname, int port) {
|
||||
opaque_t* o;
|
||||
|
||||
scene_change(AF_SCENE_CONNECTING);
|
||||
client = fishsoup_client(hostname, port == 0 ? AF_DEFAULT_PORT : port);
|
||||
if(client == NULL) {
|
||||
MwAddUserHandler(ui_message("Failed to connect"), MwNactivateHandler, net_return, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
o = client->user = malloc(sizeof(opaque_t));
|
||||
o->state = OPAQUE_WAITING_HELLO;
|
||||
memset(o->username, 0, 256);
|
||||
memcpy(o->username, username, strlen(username));
|
||||
|
||||
fishsoup_client_on_packet(client, on_packet);
|
||||
fishsoup_client_on_disconnect(client, on_disconnect);
|
||||
|
||||
gl_set_status("Waiting for server to be ready");
|
||||
}
|
||||
|
||||
void net_poll(void) {
|
||||
int ret;
|
||||
if(client == NULL) return;
|
||||
|
||||
while(client != NULL && (ret = fishsoup_client_poll(client)) > 0);
|
||||
if(ret < 0) {
|
||||
MwAddUserHandler(ui_message("Connection destroyed"), MwNactivateHandler, net_return, NULL);
|
||||
fishsoup_client_destroy(client);
|
||||
client = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
125
client/ui.c
125
client/ui.c
|
|
@ -1,125 +0,0 @@
|
|||
#include <af_common.h>
|
||||
|
||||
MwWidget ui_notice(int width, int height) {
|
||||
if(width == 0 && height == 0) {
|
||||
width = 400;
|
||||
height = 300;
|
||||
}
|
||||
|
||||
return MwVaCreateWidget(MwFrameClass, "notice", window, (MwGetInteger(window, MwNwidth) - width) / 2, (MwGetInteger(window, MwNheight) - height) / 2, width, height,
|
||||
MwNhasBorder, 1,
|
||||
MwNinverted, 0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void ui_notice_destroy(MwWidget widget) {
|
||||
MwDestroyWidget(widget);
|
||||
}
|
||||
|
||||
static void ui_login_join(MwWidget handle, void* user, void* client) {
|
||||
char* username = MwStringDuplicate(MwGetText(MwGetVoid(user, "VusernameEntry"), MwNtext));
|
||||
char* hostname = MwStringDuplicate(MwGetText(MwGetVoid(user, "VhostnameEntry"), MwNtext));
|
||||
int port = atoi(MwGetText(MwGetVoid(user, "VportEntry"), MwNtext));
|
||||
|
||||
MwLLDestroyPixmap(MwGetVoid(user, MwNpixmap));
|
||||
ui_notice_destroy(user);
|
||||
|
||||
net_connect(username, hostname, port);
|
||||
|
||||
free(username);
|
||||
free(hostname);
|
||||
}
|
||||
|
||||
static void ui_login(void) {
|
||||
MwWidget wnd = ui_notice(0, 0);
|
||||
int bw = MwDefaultBorderWidth(wnd);
|
||||
MwWidget join = MwVaCreateWidget(MwButtonClass, "join", wnd, MwGetInteger(wnd, MwNwidth) - bw - 10 - 96, MwGetInteger(wnd, MwNheight) - bw - 10 - 24, 96, 24,
|
||||
MwNtext, "Join",
|
||||
NULL);
|
||||
MwWidget box = MwVaCreateWidget(MwBoxClass, "box", wnd, bw, bw, MwGetInteger(wnd, MwNwidth) - bw * 2, MwGetInteger(wnd, MwNheight) - bw * 2 - 10 - 24,
|
||||
MwNorientation, MwVERTICAL,
|
||||
MwNmargin, 10,
|
||||
MwNpadding, 10,
|
||||
NULL);
|
||||
MwWidget icon = MwVaCreateWidget(MwImageClass, "icon", box, 0, 0, 0, 0,
|
||||
MwNfillArea, 0,
|
||||
MwNfixedSize, 100,
|
||||
NULL);
|
||||
MwWidget entrybox[3];
|
||||
MwWidget entryinput[3];
|
||||
MwLLPixmap px = MwLoadImage(wnd, DATAROOTDIR "/assaultfish/logo.png");
|
||||
const char* labels[3] = {
|
||||
"Username",
|
||||
"Hostname",
|
||||
"Port"};
|
||||
const char* entries[3] = {
|
||||
"JohnDoe",
|
||||
"127.0.0.1",
|
||||
"",
|
||||
};
|
||||
int i;
|
||||
char buf[16];
|
||||
|
||||
sprintf(buf, "%d", AF_DEFAULT_PORT);
|
||||
|
||||
entries[2] = buf;
|
||||
|
||||
for(i = 0; i < 3; i++) {
|
||||
entrybox[i] = MwVaCreateWidget(MwBoxClass, "entrybox", box, 0, 0, 0, 0,
|
||||
MwNfixedSize, 24,
|
||||
MwNmargin, 10,
|
||||
NULL);
|
||||
MwVaCreateWidget(MwLabelClass, "label", entrybox[i], 0, 0, 0, 0,
|
||||
MwNfixedSize, 100,
|
||||
MwNtext, labels[i],
|
||||
MwNalignment, MwALIGNMENT_END,
|
||||
NULL);
|
||||
entryinput[i] = MwVaCreateWidget(MwEntryClass, "entry", entrybox[i], 0, 0, 0, 0,
|
||||
MwNtext, entries[i],
|
||||
NULL);
|
||||
}
|
||||
|
||||
MwVaApply(icon,
|
||||
MwNpixmap, px,
|
||||
NULL);
|
||||
|
||||
MwVaApply(wnd,
|
||||
MwNpixmap, px,
|
||||
"VusernameEntry", entryinput[0],
|
||||
"VhostnameEntry", entryinput[1],
|
||||
"VportEntry", entryinput[2],
|
||||
NULL);
|
||||
|
||||
MwAddUserHandler(join, MwNactivateHandler, ui_login_join, wnd);
|
||||
}
|
||||
|
||||
static void ui_message_ok(MwWidget handle, void* user, void* client) {
|
||||
MwDispatchUserHandler(user, MwNactivateHandler, NULL);
|
||||
|
||||
ui_notice_destroy(user);
|
||||
}
|
||||
|
||||
MwWidget ui_message(const char* message) {
|
||||
MwWidget wnd = ui_notice(0, 0);
|
||||
int bw = MwDefaultBorderWidth(wnd);
|
||||
MwWidget label = MwVaCreateWidget(MwLabelClass, "label", wnd, bw, (MwGetInteger(wnd, MwNheight) - 24) / 2, MwGetInteger(wnd, MwNwidth) - bw * 2, 24,
|
||||
MwNtext, message,
|
||||
NULL);
|
||||
MwWidget ok = MwVaCreateWidget(MwButtonClass, "ok", wnd, MwGetInteger(wnd, MwNwidth) - bw - 10 - 96, MwGetInteger(wnd, MwNheight) - bw - 10 - 24, 96, 24,
|
||||
MwNtext, "OK",
|
||||
NULL);
|
||||
|
||||
MwAddUserHandler(ok, MwNactivateHandler, ui_message_ok, wnd);
|
||||
|
||||
return wnd;
|
||||
}
|
||||
|
||||
void ui_scene_change(void) {
|
||||
if(gl_scene == AF_SCENE_MAIN) {
|
||||
ui_login();
|
||||
}
|
||||
}
|
||||
|
||||
void ui_init(void) {
|
||||
MwToggleDarkTheme(root, 1);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue