From b10c108355008ba49ad257e6ecfc76e069e7f5e4 Mon Sep 17 00:00:00 2001 From: cailean Date: Tue, 8 Jul 2025 14:18:50 +0100 Subject: [PATCH] Scrolling Text, Font, Second window added --- bin/data/Avara-Bold.otf | Bin 0 -> 16300 bytes bin/data/Avara.otf | Bin 0 -> 19800 bytes src/main.cpp | 2 + src/ofApp.cpp | 3 + src/ofApp.h | 3 + src/ofTeleprompter.cpp | 130 +++++++++++++++++++++++++++++++++++++++- src/ofTeleprompter.h | 19 +++++- 7 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 bin/data/Avara-Bold.otf create mode 100644 bin/data/Avara.otf diff --git a/bin/data/Avara-Bold.otf b/bin/data/Avara-Bold.otf new file mode 100644 index 0000000000000000000000000000000000000000..6796b89a410e4e612c2611ffdccb10e3e7597f6b GIT binary patch literal 16300 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 literal 0 HcmV?d00001 diff --git a/bin/data/Avara.otf b/bin/data/Avara.otf new file mode 100644 index 0000000000000000000000000000000000000000..a975c8ef2795a61b2b91424ce1a9d4d617abe144 GIT binary patch literal 19800 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 mainApp(new ofApp); shared_ptr teleprompterApp(new ofTeleprompter); + mainApp->teleprompter = teleprompterApp; + ofRunApp(mainWindow, mainApp); ofRunApp(secondWindow, teleprompterApp); diff --git a/src/ofApp.cpp b/src/ofApp.cpp index d101ecd..701470d 100644 --- a/src/ofApp.cpp +++ b/src/ofApp.cpp @@ -25,6 +25,9 @@ void ofApp::update(){ videoFrame.setFromPixels(p); } onnx.update(videoFrame); + + teleprompter->updateCVData(onnx.detectedFaces.size()); + ofLog() << ofGetFrameRate(); } diff --git a/src/ofApp.h b/src/ofApp.h index 39098e4..8164946 100644 --- a/src/ofApp.h +++ b/src/ofApp.h @@ -2,6 +2,7 @@ #include "ofMain.h" #include "onxProcess.h" +#include "ofTeleprompter.h" class ofApp : public ofBaseApp{ @@ -20,4 +21,6 @@ class ofApp : public ofBaseApp{ ofImage inputImage; ofImage videoFrame; + + shared_ptr teleprompter; }; diff --git a/src/ofTeleprompter.cpp b/src/ofTeleprompter.cpp index 3b775b8..da60951 100644 --- a/src/ofTeleprompter.cpp +++ b/src/ofTeleprompter.cpp @@ -6,19 +6,44 @@ void ofTeleprompter::setup() { ofSetVerticalSync(false); setupGUI(); loadText(); + + textFont.load("Avara.otf", 32); + detailsFont.load("Avara-Bold.otf", 24); + + // Prepare first line for teleprompter + currentSentence = script[currentLine].sentence; + displayedSentence.clear(); + currentLetterIndex = 0; + lastWordTime = ofGetElapsedTimeMillis(); } void ofTeleprompter::update() { + // set labels + currentSpeaker = script[currentLine].speaker; + currentEmotion = script[currentLine].emotion; + currentLineIndex = ofToString(currentLine); + // Teleprompter logic (letter by letter) + if (currentLetterIndex < currentSentence.size()) { + uint64_t now = ofGetElapsedTimeMillis(); + if (now - lastWordTime > wordDelay) { + displayedSentence += currentSentence[currentLetterIndex]; + currentLetterIndex++; + lastWordTime = now; + } + } } void ofTeleprompter::draw() { gui.draw(); + drawText(); + } void ofTeleprompter::setupGUI() { nextLine.addListener(this, &ofTeleprompter::nextLinePressed); + gui.setDefaultWidth(400); gui.setup(); gui.add(currentLineIndex.setup("Current Line Index", "NULL")); gui.add(currentSpeaker.setup("Current Speaker", "NULL")); @@ -34,9 +59,112 @@ void ofTeleprompter::setupGUI() { void ofTeleprompter::nextLinePressed() { ofLog() << "Next Line!"; + currentLine++; + + // Prepare teleprompter effect for letter-by-letter + currentSentence = script[currentLine].sentence; + displayedSentence.clear(); + currentLetterIndex = 0; + lastWordTime = ofGetElapsedTimeMillis(); } void ofTeleprompter::loadText() { + script.clear(); - + ofFile jsonFile(filePath); + if(jsonFile.exists()) { + ofJson json = ofLoadJson(jsonFile); + int idx = 0; + for (const auto& entry : json) { + Line l; + int randomIdx = ofRandom(7); + l.idx = idx++; + l.speaker = entry.value("speaker", ""); + l.sentence = entry.value("content", ""); + l.emotion = emotions[(int)randomIdx]; + script.push_back(l); + } + } else { + ofLogError() << "JSON file not found: " << filePath; + } + + // Random Check + if (!script.empty()) { + int randomIdx = ofRandom(script.size()); // returns float + int idx = static_cast(randomIdx); // convert to int + ofLog() << "Random line: " << script[idx].speaker << ": " << script[idx].sentence; + ofLog() << "Number of lines: " << script.size(); + } + + + // Set initial current line + currentLine = 0; +} + +void ofTeleprompter::drawText() { + ofSetColor(ofColor::white); + + // --- Display speaker and emotion centered at the top --- + std::string speakerText = "Speaker: " + script[currentLine].speaker; + std::string emotionText = "Emotion: " + script[currentLine].emotion; + + ofRectangle speakerBox = detailsFont.getStringBoundingBox(speakerText, 0, 0); + float speakerX = (ofGetWidth() - speakerBox.width) / 2.0f; + float speakerY = 128; // Top margin + + ofRectangle emotionBox = detailsFont.getStringBoundingBox(emotionText, 0, 0); + float emotionX = (ofGetWidth() - emotionBox.width) / 2.0f; + float emotionY = speakerY + speakerBox.height + 10; // 10px below speaker + + detailsFont.drawString(speakerText, speakerX, speakerY); + detailsFont.drawString(emotionText, emotionX, emotionY); + + // ------- + + ofSetColor(ofColor::yellow); + float margin = 128; // pixels + float maxWidth = ofGetWidth() - margin * 2; + std::string wrapped = wrapStringToWidth(displayedSentence, maxWidth); + + // Split wrapped into lines + std::vector lines; + std::istringstream iss(wrapped); + std::string line; + while (std::getline(iss, line)) { + lines.push_back(line); + } + + // Calculate total height for vertical centering + float totalHeight = lines.size() * textFont.getLineHeight(); + float startY = (ofGetHeight() / 2.0f) - (totalHeight / 2.0f); + + // Draw each line centered horizontally + for (size_t i = 0; i < lines.size(); ++i) { + ofRectangle bbox = textFont.getStringBoundingBox(lines[i], 0, 0); + float x = (ofGetWidth() - bbox.width) / 2.0f; + float y = startY + i * textFont.getLineHeight(); + textFont.drawString(lines[i], x, y); + } +} + +std::string ofTeleprompter::wrapStringToWidth(const std::string& text, float maxWidth) { + std::istringstream iss(text); + std::string word; + std::string wrapped, line; + while (iss >> word) { + std::string testLine = line.empty() ? word : line + " " + word; + ofRectangle bbox = textFont.getStringBoundingBox(testLine, 0, 0); + if (bbox.width > maxWidth && !line.empty()) { + wrapped += line + "\n"; + line = word; + } else { + line = testLine; + } + } + if (!line.empty()) wrapped += line; + return wrapped; +} + +void ofTeleprompter::updateCVData(int numOfFacesDetected) { + facesDetected = ofToString(numOfFacesDetected); } \ No newline at end of file diff --git a/src/ofTeleprompter.h b/src/ofTeleprompter.h index d295922..ab92048 100644 --- a/src/ofTeleprompter.h +++ b/src/ofTeleprompter.h @@ -1,7 +1,6 @@ #pragma once #include "ofMain.h" #include "ofxGui.h" -#include "csv.h" struct Line { int idx; @@ -18,6 +17,10 @@ class ofTeleprompter: public ofBaseApp{ void setupGUI(); void nextLinePressed(); void loadText(); + void drawText(); + void updateCVData(int numOfFacesDetected); + + std::string wrapStringToWidth(const std::string& text, float maxWidth); ofxPanel gui; @@ -37,7 +40,19 @@ class ofTeleprompter: public ofBaseApp{ /* script */ std::vector script; - std::string filePath = "text/Macebth.json"; + std::string filePath = "text/Macbeth.json"; + int currentLine = 0; + std::string currentLineString = "N/A"; + const char* emotions[7] = {"anger", "disgust", "fear", "happiness", "neutral", "sadness", "surprise"}; + + /* scrolling text */ + int currentLetterIndex = 0; + std::string currentSentence; + uint64_t lastWordTime = 0; + uint64_t wordDelay = 10; + std::string displayedSentence; + ofTrueTypeFont textFont; + ofTrueTypeFont detailsFont; private: