variabletime/src/ofApp.h
2024-02-29 16:32:49 +01:00

368 lines
13 KiB
C++

#pragma once
#include "Zip.h"
#include "Atlas.h"
#include "conversion.h"
#include "Artboard.h"
#include "ofEasyCam.h"
#include "ofMain.h"
#include "ofQuaternion.h"
#include "ofTrueTypeFont.h"
#include "ofxVariableLab.h"
#include "ofxProfiler.h"
#include <unordered_map>
#ifdef TARGET_EMSCRIPTEN
#include <emscripten/em_macros.h>
#include <emscripten/bind.h>
#include <emscripten.h>
#include <emscripten-browser-file/emscripten_browser_file.h>
#endif
using namespace msdfgen;
// TODO: better antialias
// possibly just draw a bigger fbo?
// or do it properly:
// https://github.com/emscripten-core/emscripten/issues/7898
//
// TODO: fix linux build
namespace VariableEditor {
struct AppSettings {
std::array <float, 4> backgroundColor = {212 / 255.0,
212 / 255.0,
212 / 255.0,
1}; // check data/appSettings.json
std::string tmpExportDir = "data/export";
std::string tmpImportDir = "data/import";
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AppSettings,
backgroundColor,
tmpExportDir);
};
class ZipProjectSaver :
public ofThread {
public:
void setup(string projectName,
string projectJsonString){
this->projectName = projectName;
this->projectJsonString = projectJsonString;
this->userFontsPath = "/idbfs/fonts";
this->userAudioPath = "/idbfs/audio";
this->timestamp = ofGetTimestampString();
this->filename = projectName + "_project_" + timestamp + ".zip";
}
void update(){
if(freshDownload.load()){
emscripten_browser_file::download(filename.c_str(),
"application/zip",
buffer,
buffer_size);
freshDownload.store(false);
}
}
void threadedFunction(){
Zip zip(filename.c_str());
ofDisableDataPath();
{
char buffy[projectJsonString.length()];
projectJsonString.copy(buffy, projectJsonString.length());
zip.addBuffer("project.json", buffy, projectJsonString.length());
}
ofDirectory userFonts(userFontsPath);
userFonts.sort();
userFonts.allowExt("ttf");
userFonts.allowExt("otf");
userFonts.listDir();
for(int i = 0; i < userFonts.size(); i++){
std::string fontFilename = userFonts.getName(i);
std::string fontFilepath = userFontsPath + "/" + fontFilename;
ofFile file = userFonts.getFile(i);
ofStringReplace(fontFilepath, "/idbfs/", "idbfs/");
if(of::filesystem::exists(fontFilepath)){
//cout << "huuurrayy " << fontFilepath << " exists" << endl;
}else{
cout << "ofApp::downloadProject() trying to load " << fontFilepath << " but it does not exist." << endl;
}
file.open(fontFilepath);
ofBuffer buffy = file.readToBuffer();
zip.addBuffer(fontFilename, buffy.getData(), buffy.size());
}
ofDirectory userAudio(userAudioPath);
userAudio.sort();
userAudio.allowExt("mp3");
userAudio.allowExt("ogg");
userAudio.allowExt("wav");
userAudio.allowExt("webm");
userAudio.allowExt("m4a");
userAudio.listDir();
for(int i = 0; i < userAudio.size(); i++){
std::string audioFilename = userAudio.getName(i);
std::string audioFilepath = userAudioPath + "/" + audioFilename;
ofFile file = userAudio.getFile(i);
ofStringReplace(audioFilepath, "/idbfs/", "idbfs/");
if(of::filesystem::exists(audioFilepath)){
//cout << "huuurrayy " << audioFilepath << " exists" << endl;
}else{
cout << "ofApp::downloadProject() trying to load " << audioFilepath << " but it does not exist." << endl;
}
file.open(audioFilepath);
ofBuffer buffy = file.readToBuffer();
zip.addBuffer(audioFilename, buffy.getData(), buffy.size());
}
buffer = NULL;
buffer_size = 0;
zip.getOutputBuffer(&buffer, buffer_size);
zip.close();
ofEnableDataPath();
freshDownload.store(true);
}
void exit(){
free(buffer);
}
std::string projectName;
std::string projectJsonString;
std::string userFontsPath;
std::string userAudioPath;
std::string timestamp;
std::string filename;
char * buffer;
size_t buffer_size;
std::atomic <bool> freshDownload{false};
std::atomic <int> percent{0};
};
class ZipSaver : public ofThread {
public:
void setup(string projectName,
string framePath,
vector <string> recordedFrameNames){
this->projectName = projectName;
this->framePath = framePath;
this->recordedFrameNames = recordedFrameNames;
this->timestamp = ofGetTimestampString();
this->filename = projectName + "_frames_" + timestamp + ".zip";
}
void update(){
if(freshDownload.load()){
EM_ASM({
document.getElementById('export_progress_task').innerHTML = 'rendering';
let innerHTML = "|";
for(let i = 0; i < 100; i++){
innerHTML += "-";
}
innerHTML += "|";
let progress = document.getElementById("export_progress");
progress.innerHTML = innerHTML;
let progress_task = document.getElementById("export_progress_task");
progress_task.innerHTML = "idle";
});
emscripten_browser_file::download(filename.c_str(),
"application/zip",
buffer,
buffer_size);
freshDownload.store(false);
}else if(isThreadRunning()){
setProgress(percent.load());
}
}
void setProgress(int percent){
EM_ASM_INT({
let percent = $0;
document.getElementById('export_progress_task').innerHTML = 'rendering';
let innerHTML = "|";
const niceText = "zip ";
for(let i = 0; i < 100; i++){
if(i < percent){
innerHTML += niceText[i % niceText.length];
}else{
innerHTML += "-";
}
}
innerHTML += "|";
let progress = document.getElementById("export_progress");
progress.innerHTML = innerHTML;
let progress_task = document.getElementById("export_progress_task");
progress_task.innerHTML = "creating zip file";
}, percent);
}
void threadedFunction(){
Zip zip(filename.c_str());
ofDisableDataPath();
int total = recordedFrameNames.size();
int i = 0;
for(const std::string & f: recordedFrameNames){
std::string filepath = framePath + "/" + f + ".png";
if(of::filesystem::exists(filepath)){
//cout << "huuurrayy " << filepath << " exists" << endl;
}else{
cout << "ofApp::downloadFramesAsZip() trying to load " << filepath << " but it does not exist." << endl;
}
ofImage image;
image.setUseTexture(false);
image.load(filepath);
ofBuffer buffer;
ofSaveImage(image.getPixels(), buffer, OF_IMAGE_FORMAT_PNG);
zip.addBuffer(f + ".png", buffer.getData(), buffer.size());
percent.store((float(i) / float(total)) * 100.0f);
i++;
}
buffer = NULL;
buffer_size = 0;
zip.getOutputBuffer(&buffer, buffer_size);
zip.close();
ofEnableDataPath();
freshDownload.store(true);
}
void exit(){
free(buffer);
}
string projectName;
string framePath;
string timestamp;
string filename;
std::vector <string> recordedFrameNames;
char * buffer;
size_t buffer_size;
std::atomic <bool> freshDownload{false};
std::atomic <int> percent{0};
};
class ZipUnpacker : public ofThread {
public:
void setup(){
this->timestamp = ofGetTimestampString();
}
void update(){
if(freshUpload.load()){
freshUpload.store(false);
}else if(isThreadRunning()){
//setProgress(percent.load());
}
}
void setProgress(int percent){
EM_ASM_INT({
let percent = $0;
document.getElementById('export_progress_task').innerHTML = 'uploading and unpacking';
let innerHTML = "|";
const niceText = "zip ";
for(let i = 0; i < 100; i++){
if(i < percent){
innerHTML += niceText[i % niceText.length];
}else{
innerHTML += "-";
}
}
innerHTML += "|";
let progress = document.getElementById("import_progress");
progress.innerHTML = innerHTML;
let progress_task = document.getElementById("import_progress_task");
progress_task.innerHTML = "creating zip file";
}, percent);
}
void threadedFunction(){
ofDisableDataPath();
}
void exit(){
free(buffer);
}
string timestamp;
char * buffer;
size_t buffer_size;
std::atomic <bool> freshUpload{false};
std::atomic <int> percent{0};
};
class ofApp : public ofBaseApp {
public:
void setup() override;
void update() override;
void draw() override;
void drawGrid();
void setPlaying(bool playing);
void keyPressed(int key) override;
void keyReleased(int key) override;
void mouseMoved(int x, int y) override;
void mouseDragged(int x, int y, int button) override;
void mousePressed(int x, int y, int button) override;
void mouseReleased(int x, int y, int button) override;
void mouseEntered(int x, int y) override;
void mouseExited(int x, int y) override;
void mouseScrolled(ofMouseEventArgs & mouse) override;
void mouseScrolled(int x, int y, float scrollX, float scrollY) override;
void windowResized(int w, int h) override;
void dragEvent(ofDragInfo dragInfo) override;
void gotMessage(ofMessage msg) override;
void saveFrame(const string & filename,
const ofFbo & _fbo);
#ifdef TARGET_EMSCRIPTEN
void downloadFrame(const string & filename);
void downloadFramesAsZip(const string & projectName = "project");
static void downloadImage(const string & filename,
const ofImage & image);
static void downloadFboAsImage(const string & filename,
const ofFbo & _fbo);
static void downloadPixelsAsImage(const string & filename,
const ofPixels & image);
static void downloadJson(const string & filename,
const nlohmann::json & json);
void downloadProject(const string & projectName,
const string & projectJsonString);
#endif
void exit() override;
ofxVariableLab::LayerComposition layerComposition;
ofCamera cam;
ofFboSettings fboSettings;
ofFbo fbo;
ofEasyCam observer;
bool observing = false;
bool playing = true;
bool rendering = false;
bool renderNextFrame = false;
int guessedFrameCount = 30;
double timelineLength_seconds = 0;
int currentFrame = 0;
double theatrePosition = 0;
double timeScale = 1.0;
ofImage image42;
ofImage image420;
AppSettings settings;
ofTrueTypeFont ttf;
Artboard artboard;
std::set <ofKey> inputPressed;
// EXPORTER
std::vector <std::string> recordedFrameNames;
ZipSaver zipSaver;
ZipProjectSaver projectZipSaver;
};
}