some code in the exhibit ui, and first stab at laying out the
authorJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 19 Jan 2018 10:27:45 +0000 (12:27 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 19 Jan 2018 10:27:45 +0000 (12:27 +0200)
description text.

src/exman.cc
src/ui.cc
src/ui.h
src/ui_exhibit.cc
src/ui_exhibit.h

index 31ee1ae..e5cdd9f 100644 (file)
@@ -8,6 +8,7 @@
 #include "geomdraw.h"
 
 static Exhibit *create_exhibit(const char *type);
 #include "geomdraw.h"
 
 static Exhibit *create_exhibit(const char *type);
+static void clean_desc_text(char *dest, const char *src);
 
 
 ExhibitSlot::ExhibitSlot(Exhibit *ex)
 
 
 ExhibitSlot::ExhibitSlot(Exhibit *ex)
@@ -244,7 +245,10 @@ bool ExhibitManager::load(MetaScene *mscn, const char *fname)
                                ExData exd;
 
                                if(desc) {
                                ExData exd;
 
                                if(desc) {
-                                       exd.text = std::string(desc);
+                                       char *fixed_desc = new char[strlen(desc) + 1];
+                                       clean_desc_text(fixed_desc, desc);
+                                       exd.text = std::string(fixed_desc);
+                                       delete [] fixed_desc;
                                }
                                if(voice) {
                                        exd.voice = new OggVorbisStream;
                                }
                                if(voice) {
                                        exd.voice = new OggVorbisStream;
@@ -368,3 +372,27 @@ static Exhibit *create_exhibit(const char *type)
        error_log("unknown exhibit type: %s\n", type);
        return 0;
 }
        error_log("unknown exhibit type: %s\n", type);
        return 0;
 }
+
+/* clean up description text to be more easily layed out later.
+ * more specifically:
+ *  - remove redundant spaces
+ *  - remove all newlines except as paragraph separators
+ *  - remove all other whitespace chars
+ * destination buffer must be as large as the source buffer
+ */
+static void clean_desc_text(char *dest, const char *src)
+{
+       while(*src) {
+               if(isspace(*src)) {
+                       if(*src == '\n' && *(src + 1) == '\n') {
+                               *dest++ = '\n';
+                       } else {
+                               *dest++ = ' ';
+                       }
+                       while(*src && isspace(*src)) ++src;
+               } else {
+                       *dest++ = *src++;
+               }
+       }
+       *dest = 0;
+}
index a0babe4..78c7ece 100644 (file)
--- a/src/ui.cc
+++ b/src/ui.cc
@@ -29,7 +29,8 @@ static Text *txlist;
 
 static long timeout = 2000;
 static long trans_time = 250;
 
 static long timeout = 2000;
 static long trans_time = 250;
-static dtx_font *font;
+dtx_font *ui_font;
+int ui_font_size = FONTSZ;
 
 void set_message_timeout(long tm)
 {
 
 void set_message_timeout(long tm)
 {
@@ -108,7 +109,7 @@ void print_textv(const Vec2 &pos, const Vec3 &color, const char *fmt, va_list ap
 
 void draw_ui()
 {
 
 void draw_ui()
 {
-       if(!font) return;
+       if(!ui_font) return;
 
        while(msglist && msglist->show_until <= time_msec) {
                Message *msg = msglist;
 
        while(msglist && msglist->show_until <= time_msec) {
                Message *msg = msglist;
@@ -117,7 +118,7 @@ void draw_ui()
                delete msg;
        }
 
                delete msg;
        }
 
-       dtx_use_font(font, FONTSZ);
+       dtx_use_font(ui_font, ui_font_size);
 
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
 
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
@@ -176,10 +177,10 @@ static bool init()
 
        done_init = true;
 
 
        done_init = true;
 
-       if(!(font = dtx_open_font("data/ui.font", 0))) {
+       if(!(ui_font = dtx_open_font("data/ui.font", 0))) {
                fprintf(stderr, "failed to open font: data/ui.font\n");
                return false;
        }
                fprintf(stderr, "failed to open font: data/ui.font\n");
                return false;
        }
-       dtx_prepare_range(font, FONTSZ, 32, 127);
+       dtx_prepare_range(ui_font, ui_font_size, 32, 127);
        return true;
 }
        return true;
 }
index 088fb82..ed229cb 100644 (file)
--- a/src/ui.h
+++ b/src/ui.h
@@ -4,6 +4,10 @@
 #include <stdarg.h>
 #include <gmath/gmath.h>
 
 #include <stdarg.h>
 #include <gmath/gmath.h>
 
+struct dtx_font;
+extern dtx_font *ui_font;
+extern int ui_font_size;
+
 void set_message_timeout(long timeout);
 void show_message(const char *fmt, ...);
 void show_message(long timeout, const Vec3 &color, const char *fmt, ...);
 void set_message_timeout(long timeout);
 void show_message(const char *fmt, ...);
 void show_message(long timeout, const Vec3 &color, const char *fmt, ...);
index 409bd94..355d078 100644 (file)
@@ -1,8 +1,28 @@
 #include "ui_exhibit.h"
 #include "ui_exhibit.h"
+#include "ui.h"
 #include "app.h"
 #include "app.h"
+#include <drawtext.h>
+
+static void draw_titlebar();
+static void draw_tabs();
+static void layout_text(const char *text);
+
+static Vec3 pos;
+static Vec2 size;
+static float text_padding;
+static Exhibit *ex;
+static int vis_tab;
+static float scroll;
+static std::vector<const char*> text_lines;
+static AudioStream *voice;
+
 
 bool exui_init()
 {
 
 bool exui_init()
 {
+       size.x = 150;
+       size.y = 180;
+       text_padding = size.x * 0.01;
+
        return true;
 }
 
        return true;
 }
 
@@ -10,12 +30,103 @@ void exui_shutdown()
 {
 }
 
 {
 }
 
+void exui_change_tab(int dir)
+{
+}
+
+void exui_scroll(float delta)
+{
+}
+
+bool exui_raycast(const Ray &ray)
+{
+       return false;
+}
+
 void exui_update(float dt)
 {
 void exui_update(float dt)
 {
+       if(exsel_active.ex != ex) {
+               ex = exsel_active.ex;
+               scroll = 0.0f;
+               vis_tab = 0;
+               text_lines.clear();
+               if(voice) voice->stop();
+
+               if(ex) {
+                       int num_data = ex->data.size();
+                       for(int i=0; i<num_data; i++) {
+                               if(ex->data[i].type == EXDATA_INFO) {
+                                       layout_text(ex->data[i].text.c_str());
+                                       voice = ex->data[i].voice;
+                               }
+                       }
+
+                       if(voice) {
+                               voice->play(AUDIO_PLAYMODE_ONCE);
+                       }
+               } else {
+                       voice = 0;
+               }
+       }
 }
 
 void exui_draw()
 {
        if(!exsel_active) return;
 
 }
 
 void exui_draw()
 {
        if(!exsel_active) return;
 
+       draw_titlebar();
+       draw_tabs();
+}
+
+static void draw_titlebar()
+{
+}
+
+static void draw_tabs()
+{
+}
+
+static void layout_text(const char *text)
+{
+       text_lines.clear();
+       if(!text) return;
+       if(!ui_font) return;
+
+       dtx_use_font(ui_font, ui_font_size);
+
+       float pos = text_padding;
+       text_lines.push_back(text);
+       const char *last_break = 0;
+
+       while(*text) {
+               if(*text == '\n') {     // paragraph break
+                       text_lines.push_back(text);
+                       text_lines.push_back(++text);
+                       pos = text_padding;
+                       last_break = 0;
+                       continue;
+               }
+
+               int code = dtx_utf8_char_code(text);
+               const char *next = dtx_utf8_next_char((char*)text);
+               pos += dtx_glyph_width(code);
+
+               if(pos >= size.x - text_padding) {
+                       if(text == text_lines.back()) {
+                               // not even a single character fits on a line... abort
+                               warning_log("text layout failed. glyph %d doesn't fit in line (%g)\n", code, size.x - 2.0 * text_padding);
+                               text_lines.clear();
+                               return;
+                       }
+                       if(last_break) {
+                               text_lines.push_back(last_break + 1);
+                               last_break = 0;
+                       } else {
+                               // no good point to break, just break here
+                               text_lines.push_back(text);
+                       }
+                       pos = text_padding;
+               }
+               text = next;
+       }
 }
 }
index 6fdb6ca..bf0d222 100644 (file)
@@ -1,9 +1,16 @@
 #ifndef UI_EXHIBIT_H_
 #define UI_EXHIBIT_H_
 
 #ifndef UI_EXHIBIT_H_
 #define UI_EXHIBIT_H_
 
+#include <gmath/gmath.h>
+
 bool exui_init();
 void exui_shutdown();
 
 bool exui_init();
 void exui_shutdown();
 
+void exui_change_tab(int dir);
+void exui_scroll(float delta);
+
+bool exui_raytest(const Ray &ray);
+
 void exui_update(float dt);
 void exui_draw();
 
 void exui_update(float dt);
 void exui_draw();