Add Save/Load functionality
This commit is contained in:
367
ui/frame.cpp
367
ui/frame.cpp
@@ -28,12 +28,97 @@
|
||||
|
||||
#include<hi/linearity.h>
|
||||
|
||||
static void ShapeGrNode(GrNode *gn) {
|
||||
if(gn->logical->type == CUTIHI_T('CPre','view')) {
|
||||
gn->name = "Preview";
|
||||
gn->sinks = {{"Video", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CMix','er ')) {
|
||||
gn->name = "Mixer";
|
||||
gn->sinks = {{"Sink 1", GrNode::Port::Type::SAMPLE}, {"Sink 2", GrNode::Port::Type::SAMPLE}};
|
||||
gn->sources = {{"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CTex','t ')) {
|
||||
gn->name = "Text";
|
||||
gn->sinks = {{"Text", GrNode::Port::Type::TEXT}, {"Color", GrNode::Port::Type::COLOR}, {"DPI", GrNode::Port::Type::VEC1}};
|
||||
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CTim','e ')) {
|
||||
gn->name = "Time";
|
||||
gn->sinks = {};
|
||||
gn->sources = {{"t", GrNode::Port::Type::VEC1}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CMod','ulat')) {
|
||||
gn->name = "Modulate";
|
||||
gn->sinks = {{"Sample", GrNode::Port::Type::SAMPLE}, {"Brightness", GrNode::Port::Type::VEC1}, {"Contrast", GrNode::Port::Type::VEC1}, {"Hue", GrNode::Port::Type::VEC1}};
|
||||
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CCns','tCol')) {
|
||||
gn->name = "Constant";
|
||||
gn->sinks = {{"Color", GrNode::Port::Type::COLOR}};
|
||||
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CEmb','ed ')) {
|
||||
gn->name = "Embed";
|
||||
gn->sinks = {
|
||||
{"Frame", GrNode::Port::Type::SAMPLE},
|
||||
{"Sub 1", GrNode::Port::Type::SAMPLE}, {" Pos", GrNode::Port::Type::VEC2}, {" Size", GrNode::Port::Type::VEC1},
|
||||
{"Sub 2", GrNode::Port::Type::SAMPLE}, {" Pos", GrNode::Port::Type::VEC2}, {" Size", GrNode::Port::Type::VEC1},
|
||||
{"Sub 3", GrNode::Port::Type::SAMPLE}, {" Pos", GrNode::Port::Type::VEC2}, {" Size", GrNode::Port::Type::VEC1}
|
||||
};
|
||||
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CIma','ge ')) {
|
||||
gn->name = "Image";
|
||||
gn->sinks = {{"Filepath", GrNode::Port::Type::FILE_OPEN}};
|
||||
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CWin','dow ')) {
|
||||
gn->name = "Window";
|
||||
gn->sinks = {{"Name", GrNode::Port::Type::WINDOW_SOURCE}};
|
||||
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CInA','udio')) {
|
||||
gn->name = "Microphone";
|
||||
gn->sinks = {{"Source", GrNode::Port::Type::MIC_SOURCE}};
|
||||
gn->sources = {{"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CExp','Wave')) {
|
||||
gn->name = "Mux Wav";
|
||||
gn->sinks = {{"Filename", GrNode::Port::Type::FILE_SAVE}, {"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
gn->sources = {};
|
||||
} else if(gn->logical->type == CUTIHI_T('CMov','ie ')) {
|
||||
gn->name = "Movie";
|
||||
gn->sinks = {{"Filepath", GrNode::Port::Type::FILE_OPEN}, {"Time", GrNode::Port::Type::VEC1}};
|
||||
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}, {"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CEnc','GVP8')) {
|
||||
gn->name = "Encode VP8";
|
||||
gn->sinks = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
gn->sources = {{"Bitstream"}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CEnc','GVP9')) {
|
||||
gn->name = "Encode VP9";
|
||||
gn->sinks = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
gn->sources = {{"Bitstream"}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CExp','Webm')) {
|
||||
gn->name = "Mux WebM";
|
||||
gn->sinks = {{"Video Bitstream"}, {"Audio Bitstream"}, {"Filename", GrNode::Port::Type::FILE_SAVE}};
|
||||
gn->sources = {};
|
||||
} else if(gn->logical->type == CUTIHI_T('CKey','hook')) {
|
||||
gn->name = "Keyhook";
|
||||
gn->sinks = {{"Key", GrNode::Port::Type::VEC1}, {"Smooth Time", GrNode::Port::Type::VEC1}};
|
||||
gn->sources = {{"Bool", GrNode::Port::Type::VEC1}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CEnc','Opus')) {
|
||||
gn->name = "Encode Opus";
|
||||
gn->sinks = {{"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
gn->sources = {{"Bitstream"}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CWeb','Cam ')) {
|
||||
gn->name = "Live Digital Camera";
|
||||
gn->sinks = {};
|
||||
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(gn->logical->type == CUTIHI_T('CCmp','nScl')) {
|
||||
gn->name = "Scale";
|
||||
gn->sinks = {{"Vector", GrNode::Port::Type::VEC4}, {"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else {
|
||||
puts("Unknown node type.");
|
||||
}
|
||||
}
|
||||
|
||||
Frame::Frame() : wxFrame(NULL, wxID_ANY, "Cuticle", wxDefaultPosition, {wxSystemSettings::GetMetric(wxSYS_SCREEN_X) / 2, wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) / 2}) {
|
||||
aui.SetManagedWindow(this);
|
||||
|
||||
viewer = new ImageViewer(this);
|
||||
graph = new NodeGraph(this);
|
||||
compsets = new CompositionSettings(this);
|
||||
timeline = new Timeline(this);
|
||||
|
||||
auto info = wxAuiPaneInfo().Center().Caption("Preview").BestSize(GetSize().x, GetSize().y * 3 / 4);
|
||||
@@ -42,9 +127,6 @@ Frame::Frame() : wxFrame(NULL, wxID_ANY, "Cuticle", wxDefaultPosition, {wxSystem
|
||||
info = wxAuiPaneInfo().Bottom().Caption("Node Graph").BestSize(GetSize().x, GetSize().y * 1 / 4);
|
||||
aui.AddPane(graph, info);
|
||||
|
||||
info = wxAuiPaneInfo().Right().Caption("Composition");
|
||||
aui.AddPane(compsets, info);
|
||||
|
||||
info = wxAuiPaneInfo().Bottom().Row(2).Caption("Timeline");
|
||||
aui.AddPane(timeline, info);
|
||||
|
||||
@@ -55,15 +137,165 @@ Frame::Frame() : wxFrame(NULL, wxID_ANY, "Cuticle", wxDefaultPosition, {wxSystem
|
||||
[CUTIHI_MODE_LIVE] = wxBitmap{"tlml.bmp", wxBITMAP_TYPE_ANY},
|
||||
[CUTIHI_MODE_OFFLINE] = wxBitmap{"tlmo.bmp", wxBITMAP_TYPE_ANY}
|
||||
};
|
||||
int modeTool = tlba->AddTool(wxID_ANY, "Mode", wxBitmap{"tlml.bmp", wxBITMAP_TYPE_ANY})->GetId();
|
||||
auto modeTool = tlba->AddTool(wxID_ANY, "Mode", wxBitmap{"tlml.bmp", wxBITMAP_TYPE_ANY});
|
||||
CHi_SetMode(CUTIHI_MODE_LIVE);
|
||||
|
||||
tlba->AddTool(wxID_OPEN, "Load", wxBitmap{"btn_load.bmp", wxBITMAP_TYPE_ANY});
|
||||
tlba->AddTool(wxID_SAVE, "Save", wxBitmap{"btn_save.bmp", wxBITMAP_TYPE_ANY});
|
||||
|
||||
tlba->Bind(wxEVT_COMMAND_TOOL_CLICKED, [=](wxCommandEvent &ev){
|
||||
if(ev.GetId() == modeTool) {
|
||||
if(ev.GetId() == modeTool->GetId()) {
|
||||
CHi_SetMode((CHiMode) ((CHi_GetMode() + 1) % 2));
|
||||
tlba->SetToolNormalBitmap(modeTool, modeImgs[CHi_GetMode()]);
|
||||
tlba->SetToolNormalBitmap(modeTool->GetId(), modeImgs[CHi_GetMode()]);
|
||||
|
||||
// wxToolBarToolBase::SetShortHelp doesn't work
|
||||
if(CHi_GetMode() == CUTIHI_MODE_LIVE) {
|
||||
tlba->SetToolShortHelp(modeTool->GetId(), "Set to live processing.");
|
||||
} else {
|
||||
tlba->SetToolShortHelp(modeTool->GetId(), "Set to offline processing.");
|
||||
}
|
||||
} else if(ev.GetId() == wxID_SAVE) {
|
||||
wxFileDialog save{this, "Save", "", "", "Cuticle Project (*.ctc)|*.ctc", wxFD_SAVE | wxFD_OVERWRITE_PROMPT};
|
||||
|
||||
if(save.ShowModal() == wxID_OK) {
|
||||
FILE *f = fopen(save.GetPath().mb_str(), "wb");
|
||||
|
||||
CHi_NodeGraphSave(graph->backendNG, +[](void *ud, const void *data, size_t len){
|
||||
auto f = (FILE*) ud;
|
||||
|
||||
return fwrite(data, 1, len, f);
|
||||
}, f);
|
||||
|
||||
for(size_t n = 0; n < graph->backendNG->count; n++) {
|
||||
GrNode *gn = *std::find_if(graph->gnodes.begin(), graph->gnodes.end(), [=](GrNode *gn){
|
||||
return gn->logical == graph->backendNG->nodes[n];
|
||||
});
|
||||
|
||||
int32_t pos[2] = {gn->GetPosition().x, gn->GetPosition().y};
|
||||
fwrite(pos, sizeof(pos), 1, f);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
} else if(ev.GetId() == wxID_OPEN) {
|
||||
wxFileDialog load{this, "Load", "", "", "Cuticle Project (*.ctc)|*.ctc", wxFD_OPEN | wxFD_FILE_MUST_EXIST};
|
||||
|
||||
if(load.ShowModal() == wxID_OK) {
|
||||
FILE *f = fopen(load.GetPath().mb_str(), "rb");
|
||||
|
||||
if(CHi_NodeGraphLoad(graph->backendNG, +[](void *ud, void *data, size_t len){
|
||||
auto f = (FILE*) ud;
|
||||
|
||||
return fread(data, 1, len, f);
|
||||
}, f) == 0) {
|
||||
|
||||
for(GrNode *gnode : graph->gnodes) {
|
||||
gnode->Destroy();
|
||||
}
|
||||
|
||||
graph->gnodes.clear();
|
||||
graph->links.clear();
|
||||
|
||||
for(size_t n = 0; n < graph->backendNG->count; n++) {
|
||||
GrNode *gnode = new GrNode(graph);
|
||||
|
||||
int32_t pos[2];
|
||||
fread(pos, sizeof(pos), 1, f);
|
||||
|
||||
gnode->SetPosition({pos[0], pos[1]});
|
||||
|
||||
gnode->logical = graph->backendNG->nodes[n];
|
||||
|
||||
ShapeGrNode(gnode);
|
||||
gnode->Fit();
|
||||
|
||||
graph->gnodes.push_back(gnode);
|
||||
}
|
||||
|
||||
for(size_t n = 0; n < graph->backendNG->count; n++) {
|
||||
CHiPubNode *node = graph->backendNG->nodes[n];
|
||||
|
||||
for(size_t s = 0; s < node->sinkCount; s++) {
|
||||
if(node->sinks[s].type == CUTIHI_VAL_LINKED) {
|
||||
graph->links.push_back(NodeGraph::Link{graph->gnodes[n], s, *std::find_if(graph->gnodes.begin(), graph->gnodes.end(), [=](GrNode *gn){ return gn->logical == node->sinks[s].data.linked.to; }), node->sinks[s].data.linked.idx});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toolbar.duration->SetSeconds(std::max(0.f, graph->backendNG->duration));
|
||||
|
||||
if(graph->backendNG->duration <= 0) {
|
||||
toolbar.durationEnable->SetValue(false);
|
||||
toolbar.duration->Enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
});
|
||||
tlba->AddSeparator();
|
||||
|
||||
toolbar.durationEnable = new wxCheckBox(tlba, wxID_ANY, "");
|
||||
toolbar.duration = new ctTimeCtrl(tlba, 120);
|
||||
|
||||
toolbar.duration->Bind(wxEVT_COMMAND_TEXT_UPDATED, [=](wxCommandEvent&){
|
||||
CHi_SetDuration(graph->backendNG, toolbar.durationEnable->IsChecked() ? toolbar.duration->GetSeconds() : -1);
|
||||
});
|
||||
|
||||
toolbar.durationEnable->SetValue(true);
|
||||
toolbar.durationEnable->Bind(wxEVT_CHECKBOX, [=](wxCommandEvent&){
|
||||
toolbar.duration->Enable(toolbar.durationEnable->GetValue());
|
||||
|
||||
if(!toolbar.durationEnable->GetValue()) {
|
||||
CHi_SetDuration(graph->backendNG, -1);
|
||||
}
|
||||
});
|
||||
|
||||
toolbar.btnPerform = new wxButton(tlba, wxID_ANY, "Compile");
|
||||
toolbar.btnPerform->Bind(wxEVT_BUTTON, [=](wxCommandEvent &ev){
|
||||
if(toolbar.btnPerform->GetLabel() == "Kill") {
|
||||
CHi_StopCompilation(graph->backendNG);
|
||||
toolbar.btnPerform->Disable();
|
||||
tlba->EnableTool(wxID_SAVE, false);
|
||||
tlba->EnableTool(wxID_OPEN, false);
|
||||
} else {
|
||||
CHi_BeginCompilation(graph->backendNG);
|
||||
toolbar.btnPerform->SetLabel("Kill");
|
||||
|
||||
std::thread{[=](){
|
||||
while(graph->backendNG->compilationStatus == CUTIHI_COMP_RUNNING) {
|
||||
CallAfter([=](){
|
||||
float t = CHi_Time_Get(graph->backendNG);
|
||||
stba->SetStatusText(wxString::Format("%02i:%02i:%06.03fs", (int) (t / 3600), (int) (t / 60), fmodf(t, 60)));
|
||||
});
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
CallAfter([=](){
|
||||
stba->SetStatusText("Compilation has ended.");
|
||||
});
|
||||
}}.detach();
|
||||
}
|
||||
});
|
||||
|
||||
tlba->AddControl(toolbar.durationEnable);
|
||||
tlba->AddControl(toolbar.duration);
|
||||
tlba->AddControl(toolbar.btnPerform);
|
||||
|
||||
graph->backendNG->eventOnStopComplete = +[](CHiNodeGraph *ng){
|
||||
wxTheApp->CallAfter([ng](){
|
||||
wxButton *btn = ((Frame*) ng->ud)->toolbar.btnPerform;
|
||||
btn->Enable();
|
||||
btn->SetLabel("Compile");
|
||||
|
||||
auto tlba = ((Frame*) ng->ud)->tlba;
|
||||
tlba->EnableTool(wxID_SAVE, true);
|
||||
tlba->EnableTool(wxID_OPEN, true);
|
||||
});
|
||||
};
|
||||
|
||||
tlba->Realize();
|
||||
|
||||
aui.SetFlags(wxAUI_MGR_LIVE_RESIZE | wxAUI_MGR_DEFAULT);
|
||||
@@ -320,8 +552,8 @@ GrNode::GrNode(NodeGraph *parent) : wxPanel(parent, wxID_ANY, {0, 0}, {175, 80})
|
||||
wxSingleChoiceDialog dlg(this, "", "Choose Source", choices.size(), choices.data(), datae.data());
|
||||
if(dlg.ShowModal() == wxID_OK) {
|
||||
CHiValue newv;
|
||||
newv.type = CUTIHI_VAL_VEC4;
|
||||
newv.data.vec4[0] = (size_t) (uintptr_t) dlg.GetSelectionData();
|
||||
newv.type = CUTIHI_VAL_TEXT;
|
||||
newv.data.text = strdup(CHi_Microphone_GetSourceName((size_t) (uintptr_t) dlg.GetSelectionData()));
|
||||
CHi_ConfigureSink(this->logical, p, newv);
|
||||
parent->Dirtify(this);
|
||||
}
|
||||
@@ -500,8 +732,8 @@ NodeGraph::NodeGraph(Frame *f) : wxPanel(f, wxID_ANY) {
|
||||
{
|
||||
GrNode *v = new GrNode(this);
|
||||
v->logical = CHi_Preview();
|
||||
v->name = "Preview";
|
||||
v->sinks = {{"Video", GrNode::Port::Type::SAMPLE}};
|
||||
|
||||
ShapeGrNode(v);
|
||||
|
||||
CHi_RegisterNode(backendNG, v->logical);
|
||||
gnodes.push_back(v);
|
||||
@@ -536,39 +768,18 @@ NodeGraph::NodeGraph(Frame *f) : wxPanel(f, wxID_ANY) {
|
||||
if(ev.GetId() == idConstant) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_ConstantSample();
|
||||
printf("%p\n", noed->logical->sinks[0].data.vec4);
|
||||
noed->name = "Constant";
|
||||
noed->sinks = {{"Color", GrNode::Port::Type::COLOR}};
|
||||
noed->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idImage) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Image();
|
||||
noed->name = "Image";
|
||||
noed->sinks = {{"Filepath", GrNode::Port::Type::FILE_OPEN}};
|
||||
noed->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idEmbed) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Embed();
|
||||
noed->name = "Embed";
|
||||
noed->sinks = {
|
||||
{"Frame", GrNode::Port::Type::SAMPLE},
|
||||
{"Sub 1", GrNode::Port::Type::SAMPLE}, {" Pos", GrNode::Port::Type::VEC2}, {" Size", GrNode::Port::Type::VEC1},
|
||||
{"Sub 2", GrNode::Port::Type::SAMPLE}, {" Pos", GrNode::Port::Type::VEC2}, {" Size", GrNode::Port::Type::VEC1},
|
||||
{"Sub 3", GrNode::Port::Type::SAMPLE}, {" Pos", GrNode::Port::Type::VEC2}, {" Size", GrNode::Port::Type::VEC1}
|
||||
};
|
||||
noed->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idModulate) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Modulate();
|
||||
noed->name = "Modulate";
|
||||
noed->sinks = {{"Sample", GrNode::Port::Type::SAMPLE}, {"Brightness", GrNode::Port::Type::VEC1}, {"Contrast", GrNode::Port::Type::VEC1}, {"Hue", GrNode::Port::Type::VEC1}};
|
||||
noed->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idMovie) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Movie();
|
||||
noed->name = "Movie";
|
||||
noed->sinks = {{"Filepath", GrNode::Port::Type::FILE_OPEN}, {"Time", GrNode::Port::Type::VEC1}};
|
||||
noed->sources = {{"Sample", GrNode::Port::Type::SAMPLE}, {"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
|
||||
after = [=](){
|
||||
size_t portIdx = std::distance(noed->sinks.begin(), std::find_if(noed->sinks.begin(), noed->sinks.end(), [](GrNode::Port& p) -> bool {
|
||||
@@ -583,84 +794,47 @@ NodeGraph::NodeGraph(Frame *f) : wxPanel(f, wxID_ANY) {
|
||||
} else if(ev.GetId() == idEncodeVp9) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_EncodeVP9();
|
||||
noed->name = "Encode VP9";
|
||||
noed->sinks = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
noed->sources = {{"Bitstream"}};
|
||||
} else if(ev.GetId() == idEncodeVp8) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_EncodeVP8();
|
||||
noed->name = "Encode VP8";
|
||||
noed->sinks = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
noed->sources = {{"Bitstream"}};
|
||||
} else if(ev.GetId() == idMuxWebm) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_MuxWebm();
|
||||
noed->name = "Mux WebM";
|
||||
noed->sinks = {{"Video Bitstream"}, {"Audio Bitstream"}, {"Filename", GrNode::Port::Type::FILE_SAVE}};
|
||||
noed->sources = {};
|
||||
} else if(ev.GetId() == idWindow) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Window();
|
||||
noed->name = "Window";
|
||||
noed->sinks = {{"Name", GrNode::Port::Type::WINDOW_SOURCE}};
|
||||
noed->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idText) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Text();
|
||||
noed->name = "Text";
|
||||
noed->sinks = {{"Text", GrNode::Port::Type::TEXT}, {"Color", GrNode::Port::Type::COLOR}, {"DPI", GrNode::Port::Type::VEC1}};
|
||||
noed->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idTime) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Time();
|
||||
noed->name = "Time";
|
||||
noed->sinks = {};
|
||||
noed->sources = {{"t", GrNode::Port::Type::VEC1}};
|
||||
} else if(ev.GetId() == idMicrophone) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Microphone();
|
||||
noed->name = "Microphone";
|
||||
noed->sinks = {{"Source", GrNode::Port::Type::MIC_SOURCE}};
|
||||
noed->sources = {{"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idMixer) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Mixer();
|
||||
noed->name = "Mixer";
|
||||
noed->sinks = {{"Sink 1", GrNode::Port::Type::SAMPLE}, {"Sink 2", GrNode::Port::Type::SAMPLE}};
|
||||
noed->sources = {{"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idMuxWav) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_ExportWav();
|
||||
noed->name = "Mux Wav";
|
||||
noed->sinks = {{"Filename", GrNode::Port::Type::FILE_SAVE}, {"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
noed->sources = {};
|
||||
} else if(ev.GetId() == idEncodeOpus) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_EncodeOpus();
|
||||
noed->name = "Encode Opus";
|
||||
noed->sinks = {{"Audio", GrNode::Port::Type::SAMPLE}};
|
||||
noed->sources = {{"Bitstream"}};
|
||||
} else if(ev.GetId() == idCamera) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Camera();
|
||||
noed->name = "Live Digital Camera";
|
||||
noed->sinks = {};
|
||||
noed->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idComponentScale) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_ComponentScale();
|
||||
noed->name = "Scale";
|
||||
noed->sinks = {{"Vector", GrNode::Port::Type::VEC4}, {"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
noed->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
|
||||
} else if(ev.GetId() == idKeyhook) {
|
||||
noed = new GrNode(this);
|
||||
noed->logical = CHi_Keyhook();
|
||||
noed->name = "Keyhook";
|
||||
noed->sinks = {{"Key", GrNode::Port::Type::VEC1}, {"Smooth Time", GrNode::Port::Type::VEC1}};
|
||||
noed->sources = {{"Bool", GrNode::Port::Type::VEC1}};
|
||||
}
|
||||
|
||||
if(noed) {
|
||||
ShapeGrNode(noed);
|
||||
|
||||
noed->Fit();
|
||||
noed->SetPosition(position);
|
||||
CHi_RegisterNode(backendNG, noed->logical);
|
||||
@@ -754,7 +928,7 @@ void NodeGraph::Dirtify(GrNode *g) {
|
||||
}
|
||||
}
|
||||
|
||||
if(g == gnodes[0]) {
|
||||
if(g->logical->type == CUTIHI_T('CPre','view')) {
|
||||
if(CHi_Hysteresis(g->logical)) {
|
||||
CHiValue *val = CHi_Crawl(&g->logical->sinks[0]);
|
||||
|
||||
@@ -787,52 +961,3 @@ bool NodeGraph::DetectCycles(GrNode *root) {
|
||||
std::set<GrNode*> p{};
|
||||
return dfs(this, p, root);
|
||||
}
|
||||
|
||||
CompositionSettings::CompositionSettings(Frame *parent) : wxPanel(parent, wxID_ANY) {
|
||||
auto sz = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
sz->Add(this->durationEnable = new wxCheckBox(this, wxID_ANY, "Duration"), 0, wxALIGN_CENTER);
|
||||
sz->Add(this->duration = new ctTimeCtrl(this, 120), 0, wxEXPAND);
|
||||
|
||||
durationEnable->SetValue(true);
|
||||
durationEnable->Bind(wxEVT_CHECKBOX, [=](wxCommandEvent&){
|
||||
duration->Enable(durationEnable->GetValue());
|
||||
});
|
||||
|
||||
sz->Add(this->btnPerform = new wxButton(this, wxID_ANY, "Compile"), 0, wxEXPAND);
|
||||
btnPerform->Bind(wxEVT_BUTTON, [=](wxCommandEvent &ev){
|
||||
if(btnPerform->GetLabel() == "Kill") {
|
||||
CHi_StopCompilation(parent->graph->backendNG);
|
||||
btnPerform->Disable();
|
||||
} else {
|
||||
CHi_SetDuration(parent->graph->backendNG, durationEnable->IsChecked() ? duration->GetSeconds() : -1);
|
||||
CHi_BeginCompilation(parent->graph->backendNG);
|
||||
btnPerform->SetLabel("Kill");
|
||||
|
||||
std::thread{[=](){
|
||||
while(parent->graph->backendNG->compilationStatus == CUTIHI_COMP_RUNNING) {
|
||||
parent->CallAfter([=](){
|
||||
float t = CHi_Time_Get(parent->graph->backendNG);
|
||||
parent->stba->SetStatusText(wxString::Format("%02i:%02i:%06.03fs", (int) (t / 3600), (int) (t / 60), fmodf(t, 60)));
|
||||
});
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
parent->CallAfter([=](){
|
||||
parent->stba->SetStatusText("Compilation has ended.");
|
||||
});
|
||||
}}.detach();
|
||||
}
|
||||
});
|
||||
|
||||
parent->graph->backendNG->eventOnStopComplete = +[](CHiNodeGraph *ng){
|
||||
wxTheApp->CallAfter([ng](){
|
||||
wxButton *btn = ((Frame*) ng->ud)->compsets->btnPerform;
|
||||
btn->Enable();
|
||||
btn->SetLabel("Compile");
|
||||
});
|
||||
};
|
||||
|
||||
SetSizerAndFit(sz);
|
||||
}
|
||||
|
||||
22
ui/frame.h
22
ui/frame.h
@@ -18,19 +18,26 @@
|
||||
|
||||
struct NodeGraph;
|
||||
struct ImageViewer;
|
||||
struct CompositionSettings;
|
||||
struct Timeline;
|
||||
struct ctTimeCtrl;
|
||||
|
||||
struct Frame : wxFrame {
|
||||
wxAuiManager aui;
|
||||
|
||||
ImageViewer *viewer;
|
||||
NodeGraph *graph;
|
||||
CompositionSettings *compsets;
|
||||
Timeline *timeline;
|
||||
|
||||
wxStatusBar *stba;
|
||||
wxToolBar *tlba;
|
||||
|
||||
struct {
|
||||
ctTimeCtrl *duration;
|
||||
wxCheckBox *durationEnable;
|
||||
|
||||
wxButton *btnPerform;
|
||||
} toolbar;
|
||||
|
||||
Frame();
|
||||
virtual ~Frame();
|
||||
};
|
||||
@@ -59,17 +66,6 @@ struct GrNode : wxPanel {
|
||||
virtual void Fit() override;
|
||||
};
|
||||
|
||||
struct ctTimeCtrl;
|
||||
struct CompositionSettings : wxPanel {
|
||||
ctTimeCtrl *duration;
|
||||
wxCheckBox *durationEnable;
|
||||
|
||||
wxButton *btnPerform;
|
||||
|
||||
CompositionSettings(Frame*);
|
||||
virtual ~CompositionSettings() = default;
|
||||
};
|
||||
|
||||
struct ImageViewer : wxPanel {
|
||||
wxPoint pos;
|
||||
wxImage img;
|
||||
|
||||
Reference in New Issue
Block a user