gawsrc_gl = src/gaw/gaw_gl.c
gawsrc_sw = src/gaw/gaw_sw.c src/gaw/gawswtnl.c src/gaw/polyfill.c src/gaw/polyclip.c
+gawdef_gl = -DGFX_GL
+gawdef_sw = -DGFX_SW
+
src = $(wildcard src/*.c) $(wildcard src/modern/*.c) $(gawsrc_$(build_gfx))
obj = $(src:.c=.o)
dep = $(src:.c=.d)
warn = -pedantic -Wall
dbg = -g
#opt = -O3
-def = -DMINIGLUT_USE_LIBC
+def = -DMINIGLUT_USE_LIBC $(gawdef_$(build_gfx))
inc = -Isrc -Isrc/modern -Ilibs -Ilibs/imago/src -Ilibs/treestor/include -Ilibs/drawtext
libs = libs/unix/imago.a libs/unix/treestor.a libs/unix/drawtext.a
#include "options.h"
#include "font.h"
#include "util.h"
+#include "rtk.h"
+#ifdef GFX_SW
+#include "gaw/gaw_sw.h"
+#endif
+
+static void gui_fill(rtk_rect *rect, uint32_t color);
+static void gui_blit(int x, int y, rtk_icon *icon);
+static void gui_drawtext(int x, int y, const char *str);
+static void gui_textrect(const char *str, rtk_rect *rect);
static void txdraw(struct dtx_vertex *v, int vcount, struct dtx_pixmap *pixmap, void *cls);
int mouse_x, mouse_y, mouse_state[3];
struct font *uifont;
+uint32_t *framebuf;
+
+
/* available screens */
#define MAX_SCREENS 8
static struct app_screen *screens[MAX_SCREENS];
{
int i;
char *start_scr_name;
+ static rtk_draw_ops guigfx = {gui_fill, gui_blit, gui_drawtext, gui_textrect};
+
+ init_logger();
#if !defined(NDEBUG) && defined(DBG_FPEXCEPT)
printf("floating point exceptions enabled\n");
return -1;
}
+ rtk_setup(&guigfx);
+
/* initialize screens */
screens[num_screens++] = &scr_model;
screens[num_screens++] = &scr_rend;
destroy_font(uifont);
free(uifont);
+
+ cleanup_logger();
}
void app_display(void)
void app_reshape(int x, int y)
{
+ int numpix = x * y;
+ int prev_numpix = win_width * win_height;
+
+ if(numpix > prev_numpix) {
+ void *tmp;
+ if(!(tmp = realloc(framebuf, numpix * sizeof *framebuf))) {
+ errormsg("failed to resize framebuffer to %dx%d\n", x, y);
+ return;
+ }
+ framebuf = tmp;
+ }
+#ifdef GFX_SW
+ gaw_sw_framebuffer(x, y, framebuf);
+#endif
+
win_width = x;
win_height = y;
win_aspect = (float)x / (float)y;
cur_scr = scr;
}
-static void txdraw(struct dtx_vertex *v, int vcount, struct dtx_pixmap *pixmap, void *cls)
+static void gui_fill(rtk_rect *rect, uint32_t color)
{
- /*
- int i, aref, npix;
- unsigned char *src, *dest;
- struct texture *tex = pixmap->udata;
-
- if(!tex) {
- struct img_pixmap *img = img_create();
- img_set_pixels(img, pixmap->width, pixmap->height, IMG_FMT_RGBA32, 0);
-
- npix = pixmap->width * pixmap->height;
- src = pixmap->pixels;
- dest = img->pixels;
- for(i=0; i<npix; i++) {
- dest[0] = dest[1] = dest[2] = 0xff;
- dest[3] = *src++;
- dest += 4;
- }
+ int i, j;
+ uint32_t *fb = framebuf + rect->y * win_width + rect->x;
- if(!(tex = tex_image(img))) {
- return;
+ for(i=0; i<rect->height; i++) {
+ for(j=0; j<rect->width; j++) {
+ fb[j] = color;
}
- pixmap->udata = tex;
+ fb += win_width;
}
+}
- gaw_save();
- if(dtx_get(DTX_GL_BLEND)) {
- gaw_enable(GAW_BLEND);
- gaw_blend_func(GAW_SRC_ALPHA, GAW_ONE_MINUS_SRC_ALPHA);
- } else {
- gaw_disable(GAW_BLEND);
- }
- if((aref = dtx_get(DTX_GL_ALPHATEST))) {
- gaw_enable(GAW_ALPHA_TEST);
- gaw_alpha_func(GAW_GREATER, aref);
- } else {
- gaw_disable(GAW_ALPHA_TEST);
+static void gui_blit(int x, int y, rtk_icon *icon)
+{
+ int i, j;
+ uint32_t *dest, *src;
+
+ dest = framebuf + y * win_width + x;
+ src = icon->pixels;
+
+ for(i=0; i<icon->height; i++) {
+ for(j=0; j<icon->width; j++) {
+ int r = src[j] & 0xff;
+ int g = (src[j] >> 8) & 0xff;
+ int b = (src[j] >> 16) & 0xff;
+ dest[j] = 0xff000000 | (r << 16) | (g << 8) | b;
+ }
+ dest += win_width;
+ src += icon->scanlen;
}
+}
- gaw_set_tex2d(tex->texid);
+static void gui_drawtext(int x, int y, const char *str)
+{
+}
- gaw_begin(GAW_TRIANGLES);
- for(i=0; i<vcount; i++) {
- gaw_texcoord2f(v->s, v->t);
- gaw_vertex2f(v->x, v->y);
- v++;
- }
- gaw_end();
+static void gui_textrect(const char *str, rtk_rect *rect)
+{
+ rect->x = rect->y = 0;
+ rect->width = 20;
+ rect->height = 10;/* TODO */
+}
- gaw_restore();
- gaw_set_tex2d(0);
- */
+static void txdraw(struct dtx_vertex *v, int vcount, struct dtx_pixmap *pixmap, void *cls)
+{
}
#ifndef APP_H_
#define APP_H_
+#include "sizeint.h"
+#include "logger.h"
+
enum {
KEY_ESC = 27,
KEY_DEL = 127,
struct font;
extern struct font *uifont;
+extern uint32_t *framebuf;
+
+
int app_init(void);
void app_shutdown(void);
/*
-Deep Runner - 6dof shooter game for the SGI O2.
+RetroRay - integrated standalone vintage modeller/renderer
Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
This program is free software: you can redistribute it and/or modify
void gaw_texcoord2f(float u, float v);
void gaw_vertex2f(float x, float y);
void gaw_vertex3f(float x, float y, float z);
+void gaw_vertex4f(float x, float y, float z, float w);
void gaw_rect(float x1, float y1, float x2, float y2);
/*
-Deep Runner - 6dof shooter game for the SGI O2.
+RetroRay - integrated standalone vintage modeller/renderer
Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
This program is free software: you can redistribute it and/or modify
glVertex3f(x, y, z);
}
+void gaw_vertex4f(float x, float y, float z, float w)
+{
+ glVertex4f(x, y, z, w);
+}
+
void gaw_rect(float x1, float y1, float x2, float y2)
{
glRectf(x1, y1, x2, y2);
/*
-Deep Runner - 6dof shooter game for the SGI O2.
+RetroRay - integrated standalone vintage modeller/renderer
Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
This program is free software: you can redistribute it and/or modify
/*
-Deep Runner - 6dof shooter game for the SGI O2.
+RetroRay - integrated standalone vintage modeller/renderer
Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
This program is free software: you can redistribute it and/or modify
/*
-Deep Runner - 6dof shooter game for the SGI O2.
+RetroRay - integrated standalone vintage modeller/renderer
Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
This program is free software: you can redistribute it and/or modify
/*
-Deep Runner - 6dof shooter game for the SGI O2.
+RetroRay - integrated standalone vintage modeller/renderer
Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
This program is free software: you can redistribute it and/or modify
void gaw_vertex2f(float x, float y)
{
- gaw_vertex3f(x, y, 0);
+ gaw_vertex4f(x, y, 0, 1);
}
void gaw_vertex3f(float x, float y, float z)
{
+ gaw_vertex4f(x, y, z, 1);
+
+void gaw_vertex4f(float x, float y, float z, float w)
+{
float *cptr = st.imm_cbuf + st.imm_numv * 4;
struct vertex *vptr = st.imm_vbuf + st.imm_numv++;
*vptr = st.imm_curv;
vptr->x = x;
vptr->y = y;
vptr->z = z;
- vptr->w = 1.0f;
+ vptr->w = w;
cptr[0] = st.imm_curcol[0];
cptr[1] = st.imm_curcol[1];
/*
-Deep Runner - 6dof shooter game for the SGI O2.
+RetroRay - integrated standalone vintage modeller/renderer
Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
This program is free software: you can redistribute it and/or modify
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
#include <stdio.h>
#include <math.h>
#include <assert.h>
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
#ifndef POLYCLIP_H_
#define POLYCLIP_H_
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
#ifndef POLYFILL_H_
#define POLYFILL_H_
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
#ifdef _MSC_VER
#pragma warning (disable: 4101)
#endif
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "logger.h"
+
+#if defined(__MSDOS__) || defined(MSDOS)
+static int setup_serial(int sdev);
+#else
+#define USE_STD
+#endif
+
+enum { LOG_FILE, LOG_STREAM, LOG_CON, LOG_CB };
+enum { LOG_DBG, LOG_INFO, LOG_WARN, LOG_ERR };
+
+struct log_callback {
+ void (*func)(const char*, void*);
+ void *cls;
+};
+
+struct log_output {
+ int type, level;
+ union {
+ FILE *fp;
+ int con;
+ struct log_callback cb;
+ } out;
+};
+
+#define MAX_OUTPUTS 8
+static struct log_output outputs[MAX_OUTPUTS];
+static int num_outputs;
+
+void init_logger(void)
+{
+ num_outputs = 0;
+}
+
+void cleanup_logger(void)
+{
+ int i;
+
+ for(i=0; i<num_outputs; i++) {
+ if(outputs[i].type == LOG_FILE) {
+ fclose(outputs[i].out.fp);
+ }
+ }
+ num_outputs = 0;
+}
+
+int add_log_file(const char *fname)
+{
+ FILE *fp;
+ int idx;
+
+ if(num_outputs >= MAX_OUTPUTS) {
+ return -1;
+ }
+ if(!(fp = fopen(fname, "w"))) {
+ return -1;
+ }
+ idx = num_outputs++;
+
+ outputs[idx].type = LOG_FILE;
+ outputs[idx].out.fp = fp;
+ return 0;
+}
+
+int add_log_stream(FILE *fp)
+{
+ int idx;
+
+ if(num_outputs >= MAX_OUTPUTS) {
+ return -1;
+ }
+ idx = num_outputs++;
+
+ outputs[idx].type = LOG_STREAM;
+ outputs[idx].out.fp = fp;
+ return 0;
+}
+
+int add_log_console(const char *devname)
+{
+#if defined(MSDOS) || defined(__MSDOS__)
+ int i, comport;
+ if(sscanf(devname, "COM%d", &comport) != 1 || comport < 1 || comport > 2) {
+ return -1;
+ }
+ comport--;
+
+ if(num_outputs >= MAX_OUTPUTS) {
+ return -1;
+ }
+ for(i=0; i<num_outputs; i++) {
+ if(outputs[i].type == LOG_CON && outputs[i].out.con == comport) {
+ return -1;
+ }
+ }
+ if(setup_serial(comport) == -1) {
+ return -1;
+ }
+
+ i = num_outputs++;
+ outputs[i].type = LOG_CON;
+ outputs[i].out.con = comport;
+ return 0;
+
+#elif defined(unix) || defined(__unix__)
+ /* TODO? */
+ return -1;
+#endif
+}
+
+int add_log_callback(void (*cbfunc)(const char*, void*), void *cls)
+{
+ int idx;
+
+ if(num_outputs >= MAX_OUTPUTS) {
+ return -1;
+ }
+ idx = num_outputs++;
+
+ outputs[idx].type = LOG_CB;
+ outputs[idx].out.cb.func = cbfunc;
+ outputs[idx].out.cb.cls = cls;
+ return 0;
+}
+
+#if defined(__WATCOMC__)
+#ifndef vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+#endif
+
+static void logmsg(int type, const char *fmt, va_list ap)
+{
+ static char *buf;
+ static int bufsz;
+ int i, ret, newsz;
+ char *tmp;
+
+ while((ret = vsnprintf(buf, bufsz, fmt, ap)) > bufsz || ret < 0) {
+ if(ret > bufsz) {
+ newsz = ret + 1;
+ } else {
+ newsz = bufsz ? bufsz * 2 : 256;
+ }
+ if(!(tmp = realloc(buf, newsz))) {
+ if(buf) {
+ buf[bufsz - 1] = 0;
+ }
+ break;
+ }
+ buf = tmp;
+ bufsz = newsz;
+ }
+
+ if(!buf) return;
+
+ for(i=0; i<num_outputs; i++) {
+ switch(outputs[i].type) {
+ case LOG_FILE:
+ case LOG_STREAM:
+ fputs(buf, outputs[i].out.fp);
+ break;
+
+#if defined(MSDOS) || defined(__MSDOS__)
+ case LOG_CON:
+ ser_puts(buf);
+ break;
+#endif
+ case LOG_CB:
+ outputs[i].out.cb.func(buf, outputs[i].out.cb.cls);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void errormsg(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ logmsg(LOG_ERR, fmt, ap);
+ va_end(ap);
+}
+
+void warnmsg(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ logmsg(LOG_WARN, fmt, ap);
+ va_end(ap);
+}
+
+void infomsg(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ logmsg(LOG_INFO, fmt, ap);
+ va_end(ap);
+}
+
+void dbgmsg(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ logmsg(LOG_DBG, fmt, ap);
+ va_end(ap);
+}
+
+void verrormsg(const char *fmt, va_list ap)
+{
+ logmsg(LOG_ERR, fmt, ap);
+}
+
+void vwarnmsg(const char *fmt, va_list ap)
+{
+ logmsg(LOG_ERR, fmt, ap);
+}
+
+void vinfomsg(const char *fmt, va_list ap)
+{
+ logmsg(LOG_ERR, fmt, ap);
+}
+
+void vdbgmsg(const char *fmt, va_list ap)
+{
+ logmsg(LOG_ERR, fmt, ap);
+}
+
+
+#if defined(MSDOS) || defined(__MSDOS__)
+#define UART1_BASE 0x3f8
+#define UART2_BASE 0x2f8
+
+#define UART_DATA 0
+#define UART_DIVLO 0
+#define UART_DIVHI 1
+#define UART_FIFO 2
+#define UART_LCTL 3
+#define UART_MCTL 4
+#define UART_LSTAT 5
+
+#define DIV_9600 (115200 / 9600)
+#define DIV_38400 (115200 / 38400)
+#define LCTL_8N1 0x03
+#define LCTL_DLAB 0x80
+#define FIFO_ENABLE_CLEAR 0x07
+#define MCTL_DTR_RTS_OUT2 0x0b
+#define LST_TRIG_EMPTY 0x20
+
+static unsigned int iobase;
+
+static int setup_serial(int sdev)
+{
+ if(sdev < 0 || sdev > 1) {
+ return -1;
+ }
+ iobase = sdev == 0 ? UART1_BASE : UART2_BASE;
+
+ /* set clock divisor */
+ outp(iobase | UART_LCTL, LCTL_DLAB);
+ outp(iobase | UART_DIVLO, DIV_9600 & 0xff);
+ outp(iobase | UART_DIVHI, DIV_9600 >> 8);
+ /* set format 8n1 */
+ outp(iobase | UART_LCTL, LCTL_8N1);
+ /* assert RTS and DTR */
+ outp(iobase | UART_MCTL, MCTL_DTR_RTS_OUT2);
+ return 0;
+}
+
+void ser_putchar(int c)
+{
+ if(c == '\n') {
+ ser_putchar('\r');
+ }
+
+ while((inp(iobase | UART_LSTAT) & LST_TRIG_EMPTY) == 0);
+ outp(iobase | UART_DATA, c);
+}
+
+void ser_puts(const char *s)
+{
+ while(*s) {
+ ser_putchar(*s++);
+ }
+}
+
+void ser_printf(const char *fmt, ...)
+{
+ va_list ap;
+ char buf[512];
+
+ va_start(ap, fmt);
+ vsprintf(buf, fmt, ap);
+ va_end(ap);
+
+ ser_puts(buf);
+}
+#endif
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef LOGGER_H_
+#define LOGGER_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+void init_logger(void);
+void cleanup_logger(void);
+
+int add_log_file(const char *fname);
+int add_log_stream(FILE *fp);
+int add_log_console(const char *devname);
+int add_log_callback(void (*cbfunc)(const char*, void*), void *cls);
+
+void errormsg(const char *fmt, ...);
+void warnmsg(const char *fmt, ...);
+void infomsg(const char *fmt, ...);
+void dbgmsg(const char *fmt, ...);
+
+void verrormsg(const char *fmt, va_list ap);
+void vwarnmsg(const char *fmt, va_list ap);
+void vinfomsg(const char *fmt, va_list ap);
+void vdbgmsg(const char *fmt, va_list ap);
+
+#endif /* LOGGER_H_ */
void app_swap_buffers(void)
{
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glRasterPos2i(-1, 1);
+ glPixelZoom(1, -1);
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.5f);
+ glDrawPixels(win_width, win_height, GL_BGRA, GL_UNSIGNED_BYTE, framebuf);
+ glDisable(GL_ALPHA_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
glutSwapBuffers();
assert(glGetError() == GL_NO_ERROR);
}
static rtk_draw_ops gfx;
static void calc_widget_rect(rtk_widget *w, rtk_rect *rect);
+static void draw_window(rtk_widget *w);
+static void draw_button(rtk_widget *w);
+static void draw_checkbox(rtk_widget *w);
+static void draw_separator(rtk_widget *w);
void rtk_setup(rtk_draw_ops *drawop)
{
void rtk_bn_set_icon(rtk_widget *w, rtk_icon *icon)
{
+ rtk_rect rect;
+
RTK_ASSERT_TYPE(w, RTK_BUTTON);
w->bn.icon = icon;
+
+ calc_widget_rect(w, &rect);
+ rtk_resize(w, rect.width, rect.height);
}
rtk_icon *rtk_bn_get_icon(rtk_widget *w)
if(!(w = rtk_create_widget())) {
return 0;
}
+ w->type = RTK_WIN;
if(par) rtk_win_add(par, w);
rtk_set_text(w, title);
rtk_move(w, x, y);
if(!(w = rtk_create_widget())) {
return 0;
}
+ w->type = RTK_BUTTON;
if(par) rtk_win_add(par, w);
rtk_set_text(w, str);
rtk_set_callback(w, cbfunc, 0);
if(!(w = rtk_create_widget())) {
return 0;
}
+ w->type = RTK_BUTTON;
if(par) rtk_win_add(par, w);
rtk_bn_set_icon(w, icon);
rtk_set_callback(w, cbfunc, 0);
if(!(w = rtk_create_widget())) {
return 0;
}
+ w->type = RTK_LABEL;
if(par) rtk_win_add(par, w);
rtk_set_text(w, text);
return w;
if(!(w = rtk_create_widget())) {
return 0;
}
+ w->type = RTK_CHECKBOX;
if(par) rtk_win_add(par, w);
rtk_set_text(w, text);
rtk_set_value(w, chk ? 1 : 0);
return w;
}
+rtk_widget *rtk_create_separator(rtk_widget *par)
+{
+ rtk_widget *w;
+
+ if(!(w = rtk_create_widget())) {
+ return 0;
+ }
+ w->type = RTK_SEP;
+ if(par) rtk_win_add(par, w);
+ return w;
+}
+
+
/* --- icon functions --- */
rtk_iconsheet *rtk_load_iconsheet(const char *fname)
{
rect->height = txrect.height + PAD * 2;
break;
+ case RTK_SEP:
+ if(w->any.par->win.layout == RTK_VBOX) {
+ rect->width = w->any.par->any.width - PAD * 2;
+ rect->height = (PAD + BEVELSZ) * 2;
+ } else if(w->any.par->win.layout == RTK_HBOX) {
+ rect->width = (PAD + BEVELSZ) * 2;
+ rect->height = w->any.par->any.height - PAD * 2;
+ } else {
+ rect->width = rect->height = 0;
+ }
+ break;
+
default:
rect->width = rect->height = 0;
}
w->any.flags = (w->any.flags & ~GEOMCHG) | DIRTY;
}
-static void draw_window(rtk_widget *w);
-static void draw_button(rtk_widget *w);
-static void draw_checkbox(rtk_widget *w);
-
void rtk_draw_widget(rtk_widget *w)
{
if(need_relayout(w)) {
draw_checkbox(w);
break;
+ case RTK_SEP:
+ draw_separator(w);
+ break;
+
default:
break;
}
*ypos = y;
}
-#define COL_BG 0xa0a0a0
-#define COL_LBEV 0xcccccc
-#define COL_SBEV 0x202020
-#define COL_TEXT 0
+#define COL_BG 0xff666666
+#define COL_LBEV 0xffaaaaaa
+#define COL_SBEV 0xff333333
+#define COL_TEXT 0xff000000
+
+static void hline(int x, int y, int sz, uint32_t col)
+{
+ rtk_rect rect;
+ rect.x = x;
+ rect.y = y;
+ rect.width = sz;
+ rect.height = 1;
+ gfx.fill(&rect, col);
+}
+
+static void vline(int x, int y, int sz, uint32_t col)
+{
+ rtk_rect rect;
+ rect.x = x;
+ rect.y = y;
+ rect.width = 1;
+ rect.height = sz;
+ gfx.fill(&rect, col);
+}
+
+enum {FRM_SOLID, FRM_OUTSET, FRM_INSET};
+
+static void draw_frame(rtk_rect *rect, int type)
+{
+ int tlcol, brcol;
+
+ switch(type) {
+ case FRM_SOLID:
+ tlcol = brcol = 0xff000000;
+ break;
+ case FRM_OUTSET:
+ tlcol = COL_LBEV;
+ brcol = COL_SBEV;
+ break;
+ case FRM_INSET:
+ tlcol = COL_SBEV;
+ brcol = COL_LBEV;
+ break;
+ default:
+ break;
+ }
+
+ hline(rect->x, rect->y, rect->width, tlcol);
+ vline(rect->x, rect->y + 1, rect->height - 2, tlcol);
+ hline(rect->x, rect->y + rect->height - 1, rect->width, brcol);
+ vline(rect->x + rect->width - 1, rect->y + 1, rect->height - 2, brcol);
+}
static void draw_window(rtk_widget *w)
{
rtk_rect rect;
+ rtk_widget *c;
widget_rect(w, &rect);
gfx.fill(&rect, COL_BG);
+
+ c = w->win.clist;
+ while(c) {
+ rtk_draw_widget(c);
+ c = c->any.next;
+ }
}
static void draw_button(rtk_widget *w)
widget_rect(w, &rect);
abs_pos(w, &rect.x, &rect.y);
+ if(rect.width > 2 && rect.height > 2) {
+ draw_frame(&rect, FRM_OUTSET);
+
+ rect.x++;
+ rect.y++;
+ rect.width -= 2;
+ rect.height -= 2;
+ }
+
gfx.fill(&rect, COL_BG);
if(w->bn.icon) {
gfx.blit(rect.x + OFFS, rect.y + OFFS, w->bn.icon);
} else {
- gfx.fill(&rect, 0x802020);
+ gfx.fill(&rect, 0xff802020);
}
}
static void draw_checkbox(rtk_widget *w)
{
}
+
+static void draw_separator(rtk_widget *w)
+{
+ rtk_widget *win = w->any.par;
+ rtk_rect rect;
+
+ widget_rect(w, &rect);
+ abs_pos(w, &rect.x, &rect.y);
+
+ draw_frame(&rect, FRM_INSET);
+}
#define RTK_H_
/* widget type */
-enum { RTK_ANY, RTK_WIN, RTK_BUTTON, RTK_LABEL, RTK_CHECKBOX, RTK_SLIDER };
+enum { RTK_ANY, RTK_WIN, RTK_BUTTON, RTK_LABEL, RTK_CHECKBOX, RTK_SLIDER, RTK_SEP };
/* window layout */
enum { RTK_NONE, RTK_VBOX, RTK_HBOX };
int x, y, width, height;
} rtk_rect;
+typedef struct rtk_icon {
+ char *name;
+ int width, height, scanlen;
+ uint32_t *pixels;
+
+ struct rtk_icon *next;
+} rtk_icon;
+
+
typedef struct rtk_draw_ops {
void (*fill)(rtk_rect *rect, uint32_t color);
void (*blit)(int x, int y, rtk_icon *icon);
void rtk_free_widget(rtk_widget *w);
int rtk_type(rtk_widget *w);
+rtk_widget *rtk_parent(rtk_widget *w);
void rtk_move(rtk_widget *w, int x, int y);
void rtk_pos(rtk_widget *w, int *xptr, int *yptr);
rtk_widget *rtk_create_iconbutton(rtk_widget *par, rtk_icon *icon, rtk_callback cbfunc);
rtk_widget *rtk_create_label(rtk_widget *par, const char *text);
rtk_widget *rtk_create_checkbox(rtk_widget *par, const char *text, int chk, rtk_callback cbfunc);
+rtk_widget *rtk_create_separator(rtk_widget *par);
/* icon functions */
rtk_iconsheet *rtk_load_iconsheet(const char *fname);
void rtk_free_iconsheet(rtk_iconsheet *is);
rtk_icon *rtk_define_icon(rtk_iconsheet *is, const char *name, int x, int y, int w, int h);
+rtk_icon *rtk_lookup_icon(rtk_iconsheet *is, const char *name);
void rtk_draw_widget(rtk_widget *w);
rtk_button bn;
} rtk_widget;
-typedef struct rtk_icon {
- char *name;
- int width, height, scanlen;
- uint32_t *pixels;
-
- struct rtk_icon *next;
-} rtk_icon;
-
typedef struct rtk_iconsheet {
int width, height;
uint32_t *pixels;
*/
#include "gaw/gaw.h"
#include "app.h"
+#include "rtk.h"
+
+enum {
+ TBN_NEW, TBN_OPEN, TBN_SAVE, TBN_SEP1,
+ TBN_SEL, TBN_MOVE, TBL_ROT, TBN_SCALE, TBN_SEP2,
+ TBL_ADD, TBL_RM, TBN_SEP3,
+ TBN_MTL, TBN_REND, TBL_VIEWREND, TBN_SEP4, TBL_CFG,
+
+ NUM_TOOL_BUTTONS
+};
+static const char *tbn_icon_name[] = {
+ "new", "open", "save", 0,
+ "sel", "move", "rot", "scale", 0,
+ "add", "remove", 0,
+ "mtl", "rend", "viewrend", 0, "cfg"
+};
+static int tbn_icon_pos[][2] = {
+ {0,0}, {16,0}, {32,0}, {-1,-1},
+ {48,0}, {64,0}, {80,0}, {96,0}, {-1,-1},
+ {112,0}, {112,16}, {-1,-1},
+ {48,16}, {64,16}, {80,16}, {-1,-1}, {96,16}
+};
+static rtk_icon *tbn_icons[NUM_TOOL_BUTTONS];
+
+#define TOOLBAR_HEIGHT 26
+
static int mdl_init(void);
static void mdl_destroy(void);
static void mdl_mouse(int bn, int press, int x, int y);
static void mdl_motion(int x, int y);
+static void draw_grid(void);
+
struct app_screen scr_model = {
"modeller",
mdl_keyb, mdl_mouse, mdl_motion
};
+static rtk_widget *toolbar;
+static rtk_iconsheet *icons;
+
+static float cam_theta, cam_phi = 20, cam_dist = 8;
+
static int mdl_init(void)
{
+ int i;
+ rtk_widget *w;
+
+ if(!(icons = rtk_load_iconsheet("data/icons.png"))) {
+ errormsg("failed to load iconsheet\n");
+ return -1;
+ }
+ for(i=0; i<NUM_TOOL_BUTTONS; i++) {
+ if(tbn_icon_name[i]) {
+ tbn_icons[i] = rtk_define_icon(icons, tbn_icon_name[i],
+ tbn_icon_pos[i][0], tbn_icon_pos[i][1], 16, 16);
+ }
+ }
+
+ if(!(toolbar = rtk_create_window(0, "toolbar", 0, 0, win_width, TOOLBAR_HEIGHT))) {
+ return -1;
+ }
+ rtk_win_layout(toolbar, RTK_HBOX);
+
+ for(i=0; i<NUM_TOOL_BUTTONS; i++) {
+ if(!tbn_icons[i]) {
+ rtk_create_separator(toolbar);
+ } else {
+ if(!(w = rtk_create_iconbutton(toolbar, tbn_icons[i], 0))) {
+ return -1;
+ }
+ }
+ }
return 0;
}
static void mdl_destroy(void)
{
+ rtk_free_iconsheet(icons);
}
static int mdl_start(void)
{
+ gaw_clear_color(0.125, 0.125, 0.125, 1);
return 0;
}
static void mdl_display(void)
{
+ gaw_clear(GAW_COLORBUF | GAW_DEPTHBUF);
+
+ rtk_draw_widget(toolbar);
+
+ gaw_viewport(0, TOOLBAR_HEIGHT, win_width, win_height - TOOLBAR_HEIGHT);
+
+ gaw_matrix_mode(GAW_MODELVIEW);
+ gaw_load_identity();
+ gaw_translate(0, 0, -cam_dist);
+ gaw_rotate(cam_phi, 1, 0, 0);
+ gaw_rotate(cam_theta, 0, 1, 0);
+
+ draw_grid();
+
+ gaw_begin(GAW_QUADS);
+ gaw_color3f(1, 0, 0);
+ gaw_vertex2f(-1, -1);
+ gaw_color3f(0, 1, 0);
+ gaw_vertex2f(1, -1);
+ gaw_color3f(0, 0, 1);
+ gaw_vertex2f(1, 1);
+ gaw_color3f(1, 1, 0);
+ gaw_vertex2f(-1, 1);
+ gaw_end();
+
+ gaw_viewport(0, 0, win_width, win_height);
+}
+
+static void draw_grid(void)
+{
+ gaw_begin(GAW_LINES);
+ gaw_color3f(0.5, 0, 0);
+ gaw_vertex4f(0, 0, 0, 1);
+ gaw_vertex4f(-1, 0, 0, 0);
+ gaw_vertex4f(0, 0, 0, 1);
+ gaw_vertex4f(1, 0, 0, 0);
+ gaw_color3f(0, 0.5, 0);
+ gaw_vertex4f(0, 0, 0, 1);
+ gaw_vertex4f(0, 0, -1, 0);
+ gaw_vertex4f(0, 0, 0, 1);
+ gaw_vertex4f(0, 0, 1, 0);
+ gaw_end();
}
static void mdl_reshape(int x, int y)
{
+ float aspect = (float)x / (float)(y - TOOLBAR_HEIGHT);
+
gaw_matrix_mode(GAW_PROJECTION);
gaw_load_identity();
- gaw_perspective(50, win_aspect, 0.5, 100.0);
+ gaw_perspective(50, aspect, 0.5, 100.0);
+
+ rtk_resize(toolbar, win_width, TOOLBAR_HEIGHT);
}
static void mdl_keyb(int key, int press)
static void mdl_motion(int x, int y)
{
+ int dx = x - mouse_x;
+ int dy = y - mouse_y;
+
+ if((dx | dy) == 0) return;
+
+ if(mouse_state[0]) {
+ cam_theta += dx * 0.5f;
+ cam_phi += dy * 0.5f;
+ if(cam_phi < -90) cam_phi = -90;
+ if(cam_phi > 90) cam_phi = 90;
+ app_redisplay();
+ }
+
+ if(mouse_state[2]) {
+ cam_dist += dy * 0.1f;
+ if(cam_dist < 0) cam_dist = 0;
+ app_redisplay();
+ }
}