|
@ -2,16 +2,21 @@ |
|
|
|
|
|
|
|
|
void ofTeleprompter::setup() { |
|
|
void ofTeleprompter::setup() { |
|
|
|
|
|
|
|
|
ofBackground(0); |
|
|
ofBackground(255); |
|
|
ofSetVerticalSync(false); |
|
|
ofSetVerticalSync(false); |
|
|
setupGUI(); |
|
|
setupGUI(); |
|
|
loadText(); |
|
|
|
|
|
|
|
|
|
|
|
textFont.load("Avara.otf", 32); |
|
|
/* load both texts */ |
|
|
detailsFont.load("Avara-Bold.otf", 24); |
|
|
loadText(script, filePath); |
|
|
|
|
|
loadText(scriptContemporary, filePathContemp); |
|
|
|
|
|
|
|
|
|
|
|
activeScript = &script; |
|
|
|
|
|
|
|
|
|
|
|
textFont.load("Roboto-SemiBold.ttf", 24); |
|
|
|
|
|
detailsFont.load("Roboto-SemiBold.ttf", 22); |
|
|
|
|
|
|
|
|
// Prepare first line for teleprompter
|
|
|
// Prepare first line for teleprompter
|
|
|
currentSentence = script[currentLine].sentence; |
|
|
currentSentence = (*activeScript)[currentLine].sentence; |
|
|
displayedSentence.clear(); |
|
|
displayedSentence.clear(); |
|
|
currentLetterIndex = 0; |
|
|
currentLetterIndex = 0; |
|
|
lastWordTime = ofGetElapsedTimeMillis(); |
|
|
lastWordTime = ofGetElapsedTimeMillis(); |
|
@ -23,9 +28,9 @@ void ofTeleprompter::setup() { |
|
|
void ofTeleprompter::update() { |
|
|
void ofTeleprompter::update() { |
|
|
|
|
|
|
|
|
if(ofGetFrameNum() < 2) { |
|
|
if(ofGetFrameNum() < 2) { |
|
|
currentSpeaker = script[currentLine].speaker; |
|
|
currentSpeaker = (*activeScript)[currentLine].speaker; |
|
|
currentEmotion = script[currentLine].emotion; |
|
|
currentEmotion = (*activeScript)[currentLine].emotion; |
|
|
currentSentence = script[currentLine].sentence; |
|
|
currentSentence = (*activeScript)[currentLine].sentence; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
currentLineIndex = ofToString(currentLine + 1) + " / " + ofToString(script.size() + 1); |
|
|
currentLineIndex = ofToString(currentLine + 1) + " / " + ofToString(script.size() + 1); |
|
@ -85,6 +90,7 @@ void ofTeleprompter::setupGUI() { |
|
|
|
|
|
|
|
|
useLLMOnly.addListener(this, &ofTeleprompter::toggleOffText); |
|
|
useLLMOnly.addListener(this, &ofTeleprompter::toggleOffText); |
|
|
useTextOnly.addListener(this, &ofTeleprompter::toggleOffLLM); |
|
|
useTextOnly.addListener(this, &ofTeleprompter::toggleOffLLM); |
|
|
|
|
|
useContempTextOnly.addListener(this, &ofTeleprompter::toggleContempScript); |
|
|
|
|
|
|
|
|
gui.setDefaultWidth(400); |
|
|
gui.setDefaultWidth(400); |
|
|
gui.setup(); |
|
|
gui.setup(); |
|
@ -97,14 +103,16 @@ void ofTeleprompter::setupGUI() { |
|
|
gui.add(temperature.setup("Temperature", 0.7, 0, 1.5)); |
|
|
gui.add(temperature.setup("Temperature", 0.7, 0, 1.5)); |
|
|
gui.add(useLLMOnly.setup("Use LLM Only", false)); |
|
|
gui.add(useLLMOnly.setup("Use LLM Only", false)); |
|
|
gui.add(useTextOnly.setup("Use Text Only", false)); |
|
|
gui.add(useTextOnly.setup("Use Text Only", false)); |
|
|
|
|
|
gui.add(useContempTextOnly.setup("Use Contept Text Only", false)); |
|
|
|
|
|
gui.add(useGeneratedFeedback.setup("Use LLM Feedback", false)); |
|
|
gui.add(nextLine.setup("Next Line")); |
|
|
gui.add(nextLine.setup("Next Line")); |
|
|
gui.add(reset.setup("Reset Script")); |
|
|
gui.add(reset.setup("Reset Script")); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void ofTeleprompter::loadText() { |
|
|
void ofTeleprompter::loadText(std::vector<Line> & _script, std::string & _file) { |
|
|
|
|
|
|
|
|
script.clear(); |
|
|
_script.clear(); |
|
|
ofFile jsonFile(filePath); |
|
|
ofFile jsonFile(_file); |
|
|
if(jsonFile.exists()) { |
|
|
if(jsonFile.exists()) { |
|
|
ofJson json = ofLoadJson(jsonFile); |
|
|
ofJson json = ofLoadJson(jsonFile); |
|
|
int idx = 0; |
|
|
int idx = 0; |
|
@ -115,18 +123,18 @@ void ofTeleprompter::loadText() { |
|
|
l.speaker = entry.value("first_speaker", ""); |
|
|
l.speaker = entry.value("first_speaker", ""); |
|
|
l.sentence = entry.value("first_text", ""); |
|
|
l.sentence = entry.value("first_text", ""); |
|
|
l.emotion = entry.value("first_emotion", ""); |
|
|
l.emotion = entry.value("first_emotion", ""); |
|
|
script.push_back(l); |
|
|
_script.push_back(l); |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
ofLogError() << "JSON file not found: " << filePath; |
|
|
ofLogError() << "JSON file not found: " << filePath; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Random Check
|
|
|
// Random Check
|
|
|
if (!script.empty()) { |
|
|
if (!_script.empty()) { |
|
|
int randomIdx = ofRandom(script.size()); // returns float
|
|
|
int randomIdx = ofRandom(_script.size()); // returns float
|
|
|
int idx = static_cast<int>(randomIdx); // convert to int
|
|
|
int idx = static_cast<int>(randomIdx); // convert to int
|
|
|
ofLog() << "Random line: " << script[idx].speaker << ": " << script[idx].sentence; |
|
|
ofLog() << "Random line: " << _script[idx].speaker << ": " << _script[idx].sentence; |
|
|
ofLog() << "Number of lines: " << script.size(); |
|
|
ofLog() << "Number of lines: " << _script.size(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -135,7 +143,7 @@ void ofTeleprompter::loadText() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void ofTeleprompter::drawText() { |
|
|
void ofTeleprompter::drawText() { |
|
|
ofSetColor(ofColor::white); |
|
|
ofSetColor(ofColor::red); |
|
|
|
|
|
|
|
|
// --- Display speaker and emotion centered at the top ---
|
|
|
// --- Display speaker and emotion centered at the top ---
|
|
|
std::string speakerText = "Speaker: " + currentSpeaker.getParameter().toString(); |
|
|
std::string speakerText = "Speaker: " + currentSpeaker.getParameter().toString(); |
|
@ -154,7 +162,7 @@ void ofTeleprompter::drawText() { |
|
|
|
|
|
|
|
|
// -------
|
|
|
// -------
|
|
|
|
|
|
|
|
|
ofSetColor(ofColor::yellow); |
|
|
ofSetColor(ofColor::black); |
|
|
float margin = 128; // pixels
|
|
|
float margin = 128; // pixels
|
|
|
float maxWidth = ofGetWidth() - margin * 2; |
|
|
float maxWidth = ofGetWidth() - margin * 2; |
|
|
std::string wrapped = wrapStringToWidth(displayedSentence, maxWidth); |
|
|
std::string wrapped = wrapStringToWidth(displayedSentence, maxWidth); |
|
@ -174,7 +182,7 @@ void ofTeleprompter::drawText() { |
|
|
// Draw each line centered horizontally
|
|
|
// Draw each line centered horizontally
|
|
|
for (size_t i = 0; i < lines.size(); ++i) { |
|
|
for (size_t i = 0; i < lines.size(); ++i) { |
|
|
ofRectangle bbox = textFont.getStringBoundingBox(lines[i], 0, 0); |
|
|
ofRectangle bbox = textFont.getStringBoundingBox(lines[i], 0, 0); |
|
|
float x = (ofGetWidth() - bbox.width) / 2.0f; |
|
|
float x = 128;//(ofGetWidth() - bbox.width) / 2.0f;
|
|
|
float y = startY + i * textFont.getLineHeight(); |
|
|
float y = startY + i * textFont.getLineHeight(); |
|
|
textFont.drawString(lines[i], x, y); |
|
|
textFont.drawString(lines[i], x, y); |
|
|
} |
|
|
} |
|
@ -226,18 +234,25 @@ void ofTeleprompter::nextLinePressed() { |
|
|
if (((currentEmotionIntensity > 0.8 && currentEmotionDetetced != "neutral") || useLLMOnly) && !useTextOnly) { |
|
|
if (((currentEmotionIntensity > 0.8 && currentEmotionDetetced != "neutral") || useLLMOnly) && !useTextOnly) { |
|
|
ofLog() << "Generate Line!"; |
|
|
ofLog() << "Generate Line!"; |
|
|
|
|
|
|
|
|
std::string speaker = script[currentLine - 1].speaker; |
|
|
std::string speaker = (*activeScript)[currentLine - 1].speaker; |
|
|
std::string sentence = script[currentLine - 1].sentence; |
|
|
std::string sentence = (*activeScript)[currentLine - 1].sentence; |
|
|
std::string emotion = script[currentLine].emotion; |
|
|
std::string emotion = (*activeScript)[currentLine].emotion; |
|
|
|
|
|
|
|
|
|
|
|
if (useGeneratedFeedback) { |
|
|
|
|
|
speaker = currentSpeaker; |
|
|
|
|
|
sentence = currentSentence; |
|
|
|
|
|
emotion = currentEmotion; |
|
|
|
|
|
|
|
|
|
|
|
ofLog() << "Using Generated Feedback"; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
llmThread.requestPrompt(speaker, sentence, currentEmotionDetetced, temperature); |
|
|
llmThread.requestPrompt(speaker, sentence, currentEmotionDetetced, temperature); |
|
|
waitingForLLM = true; |
|
|
waitingForLLM = true; |
|
|
// Don't set currentSentence yet!
|
|
|
// Don't set currentSentence yet!
|
|
|
} else { |
|
|
} else { |
|
|
currentSpeaker = script[currentLine].speaker; |
|
|
currentSpeaker = (*activeScript)[currentLine].speaker; |
|
|
currentEmotion = script[currentLine].emotion; |
|
|
currentEmotion = (*activeScript)[currentLine].emotion; |
|
|
currentSentence = script[currentLine].sentence; |
|
|
currentSentence = (*activeScript)[currentLine].sentence; |
|
|
displayedSentence.clear(); |
|
|
displayedSentence.clear(); |
|
|
currentLetterIndex = 0; |
|
|
currentLetterIndex = 0; |
|
|
lastWordTime = ofGetElapsedTimeMillis(); |
|
|
lastWordTime = ofGetElapsedTimeMillis(); |
|
@ -250,9 +265,9 @@ void ofTeleprompter::resetScript() { |
|
|
currentLine = 0; |
|
|
currentLine = 0; |
|
|
|
|
|
|
|
|
// Prepare teleprompter effect for letter-by-letter
|
|
|
// Prepare teleprompter effect for letter-by-letter
|
|
|
currentSpeaker = script[currentLine].speaker; |
|
|
currentSpeaker = (*activeScript)[currentLine].speaker; |
|
|
currentEmotion = script[currentLine].emotion; |
|
|
currentEmotion = (*activeScript)[currentLine].emotion; |
|
|
currentSentence = script[currentLine].sentence; |
|
|
currentSentence = (*activeScript)[currentLine].sentence; |
|
|
|
|
|
|
|
|
displayedSentence.clear(); |
|
|
displayedSentence.clear(); |
|
|
currentLetterIndex = 0; |
|
|
currentLetterIndex = 0; |
|
@ -270,3 +285,43 @@ void ofTeleprompter::toggleOffText(bool & val) { |
|
|
useTextOnly = false; |
|
|
useTextOnly = false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void ofTeleprompter::toggleContempScript(bool & val) { |
|
|
|
|
|
if (val) { |
|
|
|
|
|
activeScript = &scriptContemporary; |
|
|
|
|
|
} else { |
|
|
|
|
|
activeScript = &script; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ofLog() << "Script Size:" + (*activeScript).size(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void ofTeleprompter::keyPressed(int key){ |
|
|
|
|
|
if(key == 'f' || key == 'F'){ |
|
|
|
|
|
ofToggleFullscreen(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(key == OF_KEY_RIGHT) { |
|
|
|
|
|
nextLinePressed(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(key == OF_KEY_LEFT) { |
|
|
|
|
|
pastLine(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(key == 'r' || key == 'R'){ |
|
|
|
|
|
resetScript(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void ofTeleprompter::pastLine() { |
|
|
|
|
|
if (currentLine < script.size()) { |
|
|
|
|
|
currentLine--; |
|
|
|
|
|
currentSpeaker = (*activeScript)[currentLine].speaker; |
|
|
|
|
|
currentEmotion = (*activeScript)[currentLine].emotion; |
|
|
|
|
|
currentSentence = (*activeScript)[currentLine].sentence; |
|
|
|
|
|
displayedSentence.clear(); |
|
|
|
|
|
currentLetterIndex = 0; |
|
|
|
|
|
lastWordTime = ofGetElapsedTimeMillis(); |
|
|
|
|
|
} |
|
|
|
|
|
} |