From c02378a381cbb23ba56099a33fab38686c8d2b5b Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Tue, 19 Sep 2023 19:01:30 +0100 Subject: loading vector data --- futuregael/addons.make | 4 +- futuregael/bin/data/show.csv | 2 +- futuregael/config.make | 6 +- futuregael/src/ofApp.cpp | 27 +-- futuregael/src/ofApp.h | 60 +------ futuregael/src/show.h | 143 ++++++++++++++++ futuregael/src/vectortext.h | 381 +++++++++++++++++++++++++++++++++++++++++++ futuregael/start | 4 +- lasertext/config.make | 2 +- 9 files changed, 547 insertions(+), 82 deletions(-) create mode 100644 futuregael/src/show.h create mode 100644 futuregael/src/vectortext.h diff --git a/futuregael/addons.make b/futuregael/addons.make index 30c4f5d..e79327f 100644 --- a/futuregael/addons.make +++ b/futuregael/addons.make @@ -1 +1,3 @@ -ofxCsv \ No newline at end of file +ofxCsv +ofxSvg +ofxHelios \ No newline at end of file diff --git a/futuregael/bin/data/show.csv b/futuregael/bin/data/show.csv index 2884832..cee509c 100644 --- a/futuregael/bin/data/show.csv +++ b/futuregael/bin/data/show.csv @@ -1,4 +1,4 @@ -Inneall Intleacht Shaorga mé.wav|00A8FF,FFB700,FF3082|Inneall Intleacht Shaorga mé, le cumhacht agus críonnacht chuile cleamhnais a bhí riamh ann. Tá beirt tagtha chugainn anocht chun leigheas a chuir ar a gcuid uaigneas go deo, le cabhair uaimse. Briseadh bualadh bos. Go raibh maith agaibh, tá míle fáílte romhaibh anseo chuig Sráid Láir na Gaillimhe, don chéad babhta eile liomsa - an Inneall Cleamhnais agus Cuardach Croíthe. Casaimid lenár gcroíthe.wav|E27D60,085DCB,E8A87C,C38D9E,41B3A3|Casaimid lenár gcroíthe anois. Agus ní ghlacann an inneall seo.wav|00A8FF,FFB700,FF3082|Agus ní ghlacann an inneall seo freagracht as timpistí nó toradh ar bith bainteach le saorthoil aon rannpháirtí. +Inneall Intleacht Shaorga mé.wav|00A8FF,FFB700,FF3082|Inneall Intleacht Shaorga mé, le cumhacht agus críonnacht chuile cleamhnais a bhí riamh ann. Tá beirt tagtha chugainn anocht chun leigheas a chuir ar a gcuid uaigneas go deo, le cabhair uaimse. Briseadh bualadh bos. Go raibh maith agaibh, tá míle fáílte romhaibh anseo chuig Sráid Láir na Gaillimhe, don chéad babhta eile liomsa - an Inneall Cleamhnais agus Cuardach Croíthe. diff --git a/futuregael/config.make b/futuregael/config.make index 9e6452a..f924803 100644 --- a/futuregael/config.make +++ b/futuregael/config.make @@ -7,7 +7,7 @@ # OF ROOT # The location of your root openFrameworks installation -# OF_ROOT = ../../openFrameworks +OF_ROOT = ../../openFrameworks ################################################################################ # OF_ROOT = ../../.. @@ -143,3 +143,7 @@ ################################################################################ # PROJECT_CXX = # PROJECT_CC = + +# Uncomment/comment below to switch between C++11 and C++17 ( or newer ). On macOS C++17 needs 10.15 or above. +export MAC_OS_MIN_VERSION = 10.15 +export MAC_OS_CPP_VER = -std=c++17 diff --git a/futuregael/src/ofApp.cpp b/futuregael/src/ofApp.cpp index c912916..2393618 100644 --- a/futuregael/src/ofApp.cpp +++ b/futuregael/src/ofApp.cpp @@ -4,32 +4,23 @@ //-------------------------------------------------------------- void ofApp::setup(){ - // Load a CSV File. - if(csv.load("show.csv","|")) { - - for (auto row:csv){ - if (row.size()<2){ - ofLog()<<"Error, found row with "<isPlaying()){ - playline->stop(); + if (show.isPlaying){ + show.stop(); } - else playline->play(); + else show.play(); break; } default:{ diff --git a/futuregael/src/ofApp.h b/futuregael/src/ofApp.h index d656bf1..20bf7d6 100644 --- a/futuregael/src/ofApp.h +++ b/futuregael/src/ofApp.h @@ -2,59 +2,7 @@ #include "ofMain.h" -#include "ofxCsv.h" - -class scriptLine{ -public: - scriptLine(string audiofile,string cols,string wrds){ - if (audio.load(audiofile)){ - //requires https://github.com/arturoc/openFrameworks/tree/feature-soundPlayerDuration - duration = ((float)audio.getDurationMS())/1000.0f; - - vector words=ofSplitString(wrds," "); - - avgWordDuration = duration / words.size(); - - ofLog()<<"loaded "< colours=ofSplitString(cols,","); - for (auto c: colours){ - palette.push_back(ofColor::fromHex(ofHexToInt(c))); - } - - bisPlaying=false; - - } - void play(){ - if (audio.isLoaded()){ - audio.play(); - startTime=ofGetElapsedTimef(); - } - } - bool isPlaying(){ - return audio.isPlaying(); - } - void stop(){ - if (isPlaying()){ - audio.stop(); - } - } - void update(){ - if (isPlaying()){ - //if (ofGetElapsedTimef()){} - } - } - vector palette; - string text; - ofSoundPlayer audio; - float duration; - float avgWordDuration; - bool bisPlaying; - float startTime; -}; +#include "show.h" class ofApp : public ofBaseApp{ @@ -74,9 +22,5 @@ class ofApp : public ofBaseApp{ void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); - ofxCsv csv; - - vector script; - - vector::iterator playline; + Show show; }; diff --git a/futuregael/src/show.h b/futuregael/src/show.h new file mode 100644 index 0000000..7261d8d --- /dev/null +++ b/futuregael/src/show.h @@ -0,0 +1,143 @@ +#include "ofMain.h" +#include "ofxCsv.h" +#include "vectortext.h" + +class ScriptLine{ +public: + ScriptLine(SVGFont &font,string audiofile,string cols,string message){ + + vector colours=ofSplitString(cols,","); + for (auto c: colours){ + palette.push_back(ofColor::fromHex(ofHexToInt(c))); + } + + clear(); + vector m=ofSplitString(message," "); + for (auto& word: m){ + glyphWord w; + int pos=0; + for (auto& c: word){ + string uniglyph = ofUTF8Substring(word, pos, 1); + if (c<0){ + //ofLog()<<"got unicode glyph, "<231 hue sat 0->255 brightness 255 + ofColor::fromHsb(ofRandom(119)+112,ofRandom(255),255) + )); + pos++; + } + words.push_back(w); + } + + if (audio.load(audiofile)){ + //requires https://github.com/arturoc/openFrameworks/tree/feature-soundPlayerDuration + duration = ((float)audio.getDurationMS())/1000.0f; + + avgWordDuration = duration / words.size(); + + ofLog()<<"Line "< palette; + vector words; + ofSoundPlayer audio; + float duration; + float avgWordDuration; + +}; + + +class Show{ +public: + bool loadFont(filesystem::path fontpath){ + return font.load(fontpath); + } + Show(){ + isPlaying=false; + } + Show(filesystem::path fontpath){ + font.load(fontpath); + Show(); + } + bool load(string file){ + + if (!font.isLoaded()){ + ofLogError()<<"cannot load show without a font"; + return false; + } + + // Load a CSV File. + if(csv.load(file,"|")) { + + for (auto row:csv){ + if (row.size()<2){ + ofLog()<<"Error, found row with "<audio.isLoaded()){ + playline->audio.play(); + startTime=ofGetElapsedTimef(); + isPlaying=true; + ofLog()<<"Line playing "<duration; + } + } + + void stop(){ + if (isPlaying){ + playline->audio.stop(); + isPlaying=false; + ofLog()<<"Line stopped"; + } + } + + void update(){ + if (isPlaying){ + if (ofGetElapsedTimef()-startTime>playline->duration){ + playline->audio.stop(); + isPlaying=false; + ofLog()<<"Line finished! "<duration;; + playline++; + if (playline==script.end()){ + ofLog()<<"Show finished!"; + } + } + } + } + + ofxCsv csv; + + vector script; + + vector::iterator playline; + + float startTime; + bool isPlaying; + + SVGFont font; +}; \ No newline at end of file diff --git a/futuregael/src/vectortext.h b/futuregael/src/vectortext.h new file mode 100644 index 0000000..0f79e58 --- /dev/null +++ b/futuregael/src/vectortext.h @@ -0,0 +1,381 @@ +#pragma once + +#include "ofMain.h" +#include "ofxSvg.h" +#include "colourPolyline.h" + +class glyph{ +public: + glyph(char c,float w,vector lines){ + glyph(c,w,lines,ofColor(0,0,0)); + } + glyph(string s,float w,vector lines){ + glyph(s,w,lines,ofColor(0,0,0)); + } + glyph(char c,float w,vector lines,ofColor col){ + string str(1, c); + glyph(str,w,lines,col); + } + glyph(string str,float w,vector lines,ofColor col){ + chr=str; + width=w; + outline=lines; + colour=col; + } + void draw(float x, float y){ + ofSetColor(colour); + ofPushMatrix(); + ofTranslate(x,y); + for (auto& v:outline) v.draw(); + ofPopMatrix(); + } + void randomiseColour(){ + colour=ofColor::fromHsb(ofRandom(255.0),225,255); + } + string chr; + float width; + vector outline; + ofColor colour; +}; + +class glyphWord{ +public: + glyphWord(){amount=1.0f;} + vector glyphs; + float amount; +}; + +class SVGFont{ + ofXml svg; + float enspace; + bool bisLoaded; +public: + bool isLoaded() { + return bisLoaded; + } + bool load(filesystem::path path){ + if( svg.load(path) ){ + enspace=getGlyph(" ").width; + ofLog()<<"loaded "< shapes; + ofPolyline shape; + string elementPath; + + elementPath = "/svg/defs/font/glyph[@unicode='"+c+"']"; + + ofXml xmlElement = svg.findFirst(elementPath); + + float charWidth = ofToFloat(xmlElement.getAttribute("horiz-adv-x").getValue()); + + vector splitGlyphPath = ofSplitString(xmlElement.getAttribute("d").getValue(), " ");//glyph path data in SVG looks like this: "M 139 -9.45 L 230 18.9 L 299 22.1 L 227 25.2" + + for(int i=0; i words; + vector outlines; + ofVec2f centre; + float lastUpdateTime; + float playhead; + float enspace; + vector palette; + struct { + vector balanced={ + ofColor::fromHex(0xE27D60), + ofColor::fromHex(0x085DCB), + ofColor::fromHex(0xE8A87C), + ofColor::fromHex(0xC38D9E), + ofColor::fromHex(0x41B3A3) + }; + vector uneasy={ + ofColor::fromHex(0x2154B9), + ofColor::fromHex(0xC45A62), + ofColor::fromHex(0x95A28A), + ofColor::fromHex(0x98546D), + ofColor::fromHex(0xE9DADA), + ofColor::fromHex(0x9FF3E9), + ofColor::fromHex(0xD07B37), + ofColor::fromHex(0x741710), + ofColor::fromHex(0x102ADC), + ofColor::fromHex(0x9FA1AC) + }; + vector als23={ + ofColor::fromHex(0x00A8FF), + ofColor::fromHex(0xFFB700), + ofColor::fromHex(0xFF3082) + }; + }palettes; + vector split(string s) { + size_t pos_start = 0, pos_end; + string token; + vector res; + + while ((pos_end = s.find (" ", pos_start)) != string::npos) { + token = s.substr (pos_start, pos_end - pos_start); + pos_start = pos_end + 1; + res.push_back (token); + } + + res.push_back (s.substr (pos_start)); + return res; + } +public: + glyphbanner(){ + palette=palettes.als23; + }; + void init(string message){ + createWords(message,true); + lastUpdateTime=ofGetElapsedTimef(); + playhead=0.0f; + } + int length(){ + int l=0; + for (auto& w:words) { + l+=w.glyphs.size(); + } + return l+max(0,(int)words.size()-1); + } + float width(){ + float _w=0.0f; + for (auto& w:words) { + for (auto& g:w.glyphs) _w+=g.width; + } + return _w+max((float)(words.size()-1)*enspace,0.0f); + } + int glyphCount(){ + int c=0; + for (auto& w:words){ + c+=w.glyphs.size(); + } + return c; + } + string text(){ + string s; + for (auto& w:words) { + for (auto& g:w.glyphs) s+=g.chr; + } + return s; + } + void loadFont(filesystem::path path){ + if( SVGFont.load(path) ){ + vector w=words; + clear(); + createWords(w); + enspace=getGlyph(" ").width; + ofLog()<<"loaded "< m=split(message); + for (auto& word: m){ + glyphWord w; + int pos=0; + for (auto& c: word){ + string uniglyph = ofUTF8Substring(word, pos, 1); + if (c<0){ + ofLog()<<"got unicode glyph, "<231 hue sat 0->255 brightness 255 + ofColor::fromHsb(ofRandom(119)+112,ofRandom(255),255) + )); + pos++; + } + words.push_back(w); + } + //ofLog()<<"created "< _words){ + clear(); + for (auto& _w:_words) { + glyphWord w; + for (auto& g: _w.glyphs){ + w.glyphs.push_back(getGlyph(g.chr,g.colour)); + } + words.push_back(w); + } + } + glyph getGlyph(string c,ofColor col=ofColor(255,255,255)){ + vector shapes; + ofPolyline shape; + string elementPath; +/* +[notice ] getGlyph placed ? for missing char -61 (?) +[notice ] getGlyph placed ? for missing char -119 (?) +[notice ] getGlyph placed ? for missing char -61 (?) +[notice ] getGlyph placed ? for missing char -70 (?) +[notice ] getGlyph placed ? for missing char -61 (?) +[notice ] getGlyph placed ? for missing char -95 (?) + +hack to add unicode support for these chars + + if (c==-61){ + elementPath = '/svg/defs/font/glyph[@unicode="Ĕ"]'; //Ebreve + //this doesn't actually display the accent + ofLog()<<"getGlyph substituted 'Ĕ' for missing char -61"; + } + if (c==-119||c==-70||c==-95){ + elementPath = '/svg/defs/font/glyph[@unicode="È"]'; //Egrave + //this doesn't actually find anything + ofLog()<<"getGlyph substituted 'È' for missing char -119"; + } + + ofUTF8Substring(const std::string & utf8, size_t pos, size_t len); + else { + */ + elementPath = "/svg/defs/font/glyph[@unicode='"+ofToString(c)+"']"; + //} + + /* + if(SVGFont.findFirst(elementPath) == 0 ){ + elementPath = "/svg/defs/font/glyph[@unicode='?']"; + ofLog()<<"getGlyph placed ? for missing char "< splitGlyphPath = ofSplitString(xmlElement.getAttribute("d").getValue(), " ");//glyph path data in SVG looks like this: "M 139 -9.45 L 230 18.9 L 299 22.1 L 227 25.2" + + for(int i=0; iwords[theword].glyphs.size()){ + theletter-=words[theword].glyphs.size(); + theword++; + } + float playfraction=playhead-int(playhead); + + //segment=(((float)theletter+words[theword].glyphs.size()+playhead-int(playhead))/words[theword].glyphs.size()); + segment=(((float)theletter+playfraction-1)/words[theword].glyphs.size()); + } + //calculate params for word/letter anim + for (int i=0;i& getOutlines(float s=1.0f){ + outlines.clear(); + float p=(-width())/2; + for (auto& w:words){ + for (auto& g:w.glyphs){ + if (w.amount>0.0f){ + for (auto& o:g.outline){ + auto q=o; + q.scale(s,-s); + q.translate(glm::vec3(p*s,-ofGetHeight()/3,0)); + outlines.push_back(colourPolyline(q,g.colour*w.amount)); + } + } + p+=g.width; + } + p+=enspace; + } + return outlines; + } +}; \ No newline at end of file diff --git a/futuregael/start b/futuregael/start index 80acf6e..4a806c0 100755 --- a/futuregael/start +++ b/futuregael/start @@ -1,6 +1,6 @@ -mkdir bin/lasertext.app/Contents/Frameworks +mkdir bin/futuregael.app/Contents/Frameworks mkdir bin/data -cp libs/libHeliosDacAPI.dylib bin/lasertext.app/Contents/MacOS/ +cp libs/libHeliosDacAPI.dylib bin/futuregael.app/Contents/MacOS/ mkdir bin/data/fonts cp fonts/*.svg bin/data/fonts diff --git a/lasertext/config.make b/lasertext/config.make index 9e6452a..d622cd5 100644 --- a/lasertext/config.make +++ b/lasertext/config.make @@ -7,7 +7,7 @@ # OF ROOT # The location of your root openFrameworks installation -# OF_ROOT = ../../openFrameworks +OF_ROOT = ../../openFrameworks ################################################################################ # OF_ROOT = ../../.. -- cgit v1.2.3