Start Windows compatibility

screen_capture_lite turned out to be pretty broken and so I brought back
my old X11 implementation for the Window node, for Unices only.
Hopefully SCL actually works on Windows because lemme tell you, I do not
want to go knee-deep in that.

Additionally, SAIL was replaced with stb_image because I couldn't get
SAIL to build under MinGW.
This commit is contained in:
mid
2025-10-12 11:23:08 +03:00
parent d77ae15b46
commit 3993163d6d
19 changed files with 654 additions and 198 deletions

View File

@@ -135,19 +135,19 @@ static void ShapeGrNode(GrNode *gn) {
gn->sinks.push_back({" Size", GrNode::Port::Type::VEC1, true});
}
} else if(gn->logical->type == CUTIHI_T('CIma','ge ')) {
gn->sinks = {{"Filepath", GrNode::Port::Type::FILE_OPEN}};
gn->sinks = {{"Filepath", GrNode::Port::Type::FILE_OPENING}};
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
} else if(gn->logical->type == CUTIHI_T('CWin','dow ')) {
gn->sinks = {{"Name", GrNode::Port::Type::WINDOW_SOURCE}};
gn->sinks = {{"Name", GrNode::Port::Type::WINDOW_SOURCE}, {"Ignore Alpha", GrNode::Port::Type::CHECKBOX}};
gn->sources = {{"Sample", GrNode::Port::Type::SAMPLE}};
} else if(gn->logical->type == CUTIHI_T('CInA','udio')) {
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->sinks = {{"Filename", GrNode::Port::Type::FILE_SAVE}, {"Audio", GrNode::Port::Type::SAMPLE}};
gn->sinks = {{"Filename", GrNode::Port::Type::FILE_SAVING}, {"Audio", GrNode::Port::Type::SAMPLE}};
gn->sources = {};
} else if(gn->logical->type == CUTIHI_T('CMov','ie ')) {
gn->sinks = {{"Filepath", GrNode::Port::Type::FILE_OPEN}, {"Time", GrNode::Port::Type::VEC1}};
gn->sinks = {{"Filepath", GrNode::Port::Type::FILE_OPENING}, {"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->sinks = {{"Sample", GrNode::Port::Type::SAMPLE}};
@@ -159,7 +159,7 @@ static void ShapeGrNode(GrNode *gn) {
gn->sinks = {{"Sample", GrNode::Port::Type::SAMPLE}};
gn->sources = {{"Bitstream"}};
} else if(gn->logical->type == CUTIHI_T('CExp','Webm')) {
gn->sinks = {{"Video Bitstream"}, {"Audio Bitstream"}, {"Filename", GrNode::Port::Type::FILE_SAVE}};
gn->sinks = {{"Video Bitstream"}, {"Audio Bitstream"}, {"Filename", GrNode::Port::Type::FILE_SAVING}};
gn->sources = {};
} else if(gn->logical->type == CUTIHI_T('CKey','hook')) {
gn->sinks = {{"Key", GrNode::Port::Type::TEXT}, {"Smooth Time", GrNode::Port::Type::VEC1}};
@@ -183,7 +183,7 @@ static void ShapeGrNode(GrNode *gn) {
gn->sinks = {{"Audio", GrNode::Port::Type::SAMPLE}};
gn->sources = {{"Bitstream"}};
} else if(gn->logical->type == CUTIHI_T('CExp','Mkv ')) {
gn->sinks = {{"Video Bitstream"}, {"Audio Bitstream"}, {"Filename", GrNode::Port::Type::FILE_SAVE}};
gn->sinks = {{"Video Bitstream"}, {"Audio Bitstream"}, {"Filename", GrNode::Port::Type::FILE_SAVING}};
gn->sources = {};
}
@@ -484,8 +484,8 @@ GrNode::GrNode(NodeGraph *parent) : wxPanel(parent, wxID_ANY, {0, 0}, {175, 80})
int y = 13;
int i = 0;
for(Port &p : sinks) {
wxColour col = p.type == GrNode::Port::Type::FILE_OPEN ? wxColour{255, 0, 0}
: p.type == GrNode::Port::Type::FILE_SAVE ? wxColour{255, 0, 0}
wxColour col = p.type == GrNode::Port::Type::FILE_OPENING ? wxColour{255, 0, 0}
: p.type == GrNode::Port::Type::FILE_SAVING ? wxColour{255, 0, 0}
: p.type == GrNode::Port::Type::COLOR ? wxColour{0, 0, 255}
: p.type == GrNode::Port::Type::VEC2 ? wxColour{0, 255, 0}
: p.type == GrNode::Port::Type::TEXT ? wxColour{255, 255, 0}
@@ -512,8 +512,8 @@ GrNode::GrNode(NodeGraph *parent) : wxPanel(parent, wxID_ANY, {0, 0}, {175, 80})
y = 13;
i = 0;
for(Port &p : sources) {
wxColour col = p.type == GrNode::Port::Type::FILE_OPEN ? wxColour{255, 0, 0}
: p.type == GrNode::Port::Type::FILE_SAVE ? wxColour{255, 0, 0}
wxColour col = p.type == GrNode::Port::Type::FILE_OPENING ? wxColour{255, 0, 0}
: p.type == GrNode::Port::Type::FILE_SAVING ? wxColour{255, 0, 0}
: p.type == GrNode::Port::Type::COLOR ? wxColour{0, 0, 255}
: p.type == GrNode::Port::Type::VEC2 ? wxColour{0, 255, 0}
: p.type == GrNode::Port::Type::TEXT ? wxColour{255, 255, 0}
@@ -650,7 +650,7 @@ GrNode::GrNode(NodeGraph *parent) : wxPanel(parent, wxID_ANY, {0, 0}, {175, 80})
pthread_mutex_unlock(&this->logical->ng->mut);
}
} else if(sinks[p].type == Port::Type::FILE_OPEN) {
} else if(sinks[p].type == Port::Type::FILE_OPENING) {
wxFileDialog dlg(this, wxFileSelectorPromptStr, wxEmptyString, wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_PREVIEW);
if(dlg.ShowModal() == wxID_OK) {
pthread_mutex_lock(&this->logical->ng->mut);
@@ -663,7 +663,7 @@ GrNode::GrNode(NodeGraph *parent) : wxPanel(parent, wxID_ANY, {0, 0}, {175, 80})
pthread_mutex_unlock(&this->logical->ng->mut);
}
} else if(sinks[p].type == Port::Type::FILE_SAVE) {
} else if(sinks[p].type == Port::Type::FILE_SAVING) {
wxFileDialog dlg(this, wxFileSelectorPromptStr, wxEmptyString, wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_SAVE | wxFD_PREVIEW | wxFD_OVERWRITE_PROMPT);
if(dlg.ShowModal() == wxID_OK) {
pthread_mutex_lock(&this->logical->ng->mut);
@@ -679,28 +679,29 @@ GrNode::GrNode(NodeGraph *parent) : wxPanel(parent, wxID_ANY, {0, 0}, {175, 80})
} else if(sinks[p].type >= Port::Type::VEC1 && sinks[p].type <= Port::Type::VEC4) {
auto ctrls = std::make_shared<std::vector<wxTextCtrl*>>();
for(int i = 0; i <= (int) sinks[p].type - (int) Port::Type::VEC1; i++) {
wxTextCtrl *tc = new wxTextCtrl(GetParent(), wxID_ANY, wxString::Format("%f", this->logical->sinks[p].data.vec4[i]), GetParent()->ScreenToClient(ClientToScreen({5 + 60 * i, (p + 1) * 20})));
tc->Bind(wxEVT_KEY_DOWN, [=](wxKeyEvent &ev){
if(ev.GetKeyCode() == WXK_RETURN) {
double d;
if(tc->GetValue().ToDouble(&d)) {
pthread_mutex_lock(&this->logical->ng->mut);
CHiValue newv = *CHi_Crawl(&this->logical->sinks[p]);
newv.type = CUTIHI_VAL_VEC4;
newv.data.vec4[i] = d;
CHi_ConfigureSink(this->logical, p, newv);
wxTextCtrl *tc = new wxTextCtrl(GetParent(), wxID_ANY, wxString::Format("%f", this->logical->sinks[p].data.vec4[i]), GetParent()->ScreenToClient(ClientToScreen({5 + 60 * i, (p + 1) * 20})), wxDefaultSize, wxTE_PROCESS_ENTER);
tc->Bind(wxEVT_TEXT_ENTER, [=](wxCommandEvent &ev){
double d;
if(tc->GetValue().ToDouble(&d)) {
pthread_mutex_lock(&this->logical->ng->mut);
auto it = std::find(ctrls->begin(), ctrls->end(), tc);
ctrls->operator[]((it - ctrls->begin() + 1) % ctrls->size())->SetFocus();
ctrls->erase(it);
CallAfter([tc](){tc->Destroy();});
parent->Dirtify(this);
pthread_mutex_unlock(&this->logical->ng->mut);
}
} else if(ev.GetKeyCode() == WXK_TAB) {
CHiValue newv = *CHi_Crawl(&this->logical->sinks[p]);
newv.type = CUTIHI_VAL_VEC4;
newv.data.vec4[i] = d;
CHi_ConfigureSink(this->logical, p, newv);
auto it = std::find(ctrls->begin(), ctrls->end(), tc);
ctrls->operator[]((it - ctrls->begin() + 1) % ctrls->size())->SetFocus();
ctrls->erase(it);
CallAfter([tc](){tc->Destroy();});
parent->Dirtify(this);
pthread_mutex_unlock(&this->logical->ng->mut);
}
});
tc->Bind(wxEVT_KEY_DOWN, [=](wxKeyEvent &ev){
if(ev.GetKeyCode() == WXK_TAB) {
ctrls->operator[]((i + ctrls->size() + (wxGetKeyState(WXK_SHIFT) ? -1 : 1)) % ctrls->size())->SetFocus();
parent->Dirtify(this);
@@ -710,7 +711,7 @@ GrNode::GrNode(NodeGraph *parent) : wxPanel(parent, wxID_ANY, {0, 0}, {175, 80})
}
ctrls->operator[](0)->SetFocus();
} else if(sinks[p].type == Port::Type::TEXT) {
wxTextCtrl *ctrl = new wxTextCtrl(GetParent(), wxID_ANY, this->logical->sinks[p].data.text, GetParent()->ScreenToClient(ClientToScreen({5, (p + 1) * 26})));
wxTextCtrl *ctrl = new wxTextCtrl(GetParent(), wxID_ANY, this->logical->sinks[p].data.text, GetParent()->ScreenToClient(ClientToScreen({5, (p + 1) * 26})), wxDefaultSize, wxTE_PROCESS_ENTER);
ctrl->SetValue(wxString{CHi_Crawl(&this->logical->sinks[p])->data.text});
ctrl->SetFocus();
ctrl->Bind(wxEVT_KILL_FOCUS, [=](wxFocusEvent &ev){
@@ -727,21 +728,19 @@ GrNode::GrNode(NodeGraph *parent) : wxPanel(parent, wxID_ANY, {0, 0}, {175, 80})
pthread_mutex_unlock(&this->logical->ng->mut);
});
ctrl->Bind(wxEVT_KEY_DOWN, [=](wxKeyEvent &ev){
if(ev.GetKeyCode() == WXK_RETURN) {
pthread_mutex_lock(&this->logical->ng->mut);
CHiValue newv = {};
newv.type = CUTIHI_VAL_TEXT;
char *c = (char*) malloc(ctrl->GetValue().Len() + 1);
memcpy(c, ctrl->GetValue().c_str(), ctrl->GetValue().Len() + 1);
newv.data.text = c;
CHi_ConfigureSink(this->logical, p, newv);
CallAfter([ctrl](){ctrl->Destroy();});
parent->Dirtify(this);
pthread_mutex_unlock(&this->logical->ng->mut);
} else ev.Skip();
ctrl->Bind(wxEVT_TEXT_ENTER, [=](wxCommandEvent &ev){
pthread_mutex_lock(&this->logical->ng->mut);
CHiValue newv = {};
newv.type = CUTIHI_VAL_TEXT;
char *c = (char*) malloc(ctrl->GetValue().Len() + 1);
memcpy(c, ctrl->GetValue().c_str(), ctrl->GetValue().Len() + 1);
newv.data.text = c;
CHi_ConfigureSink(this->logical, p, newv);
CallAfter([ctrl](){ctrl->Destroy();});
parent->Dirtify(this);
pthread_mutex_unlock(&this->logical->ng->mut);
});
} else if(sinks[p].type == Port::Type::MIC_SOURCE) {
std::vector<wxString> choices;
@@ -790,6 +789,26 @@ GrNode::GrNode(NodeGraph *parent) : wxPanel(parent, wxID_ANY, {0, 0}, {175, 80})
}
CHi_Window_FreeList(wbuf);
} else if(sinks[p].type == Port::Type::CHECKBOX) {
wxCheckBox *cb = new wxCheckBox(this, wxID_ANY, sinks[p].name);
cb->SetValue((bool) this->logical->sinks[p].data.vec4[0]);
cb->SetFocus();
cb->Bind(wxEVT_KILL_FOCUS, [=](wxFocusEvent &ev){
pthread_mutex_lock(&this->logical->ng->mut);
CHiValue newv = {};
newv.type = CUTIHI_VAL_VEC4;
newv.data.vec4[0] = cb->IsChecked();
newv.data.vec4[1] = cb->IsChecked();
newv.data.vec4[2] = cb->IsChecked();
newv.data.vec4[3] = cb->IsChecked();
CHi_ConfigureSink(this->logical, p, newv);
parent->Dirtify(this);
CallAfter([cb](){cb->Destroy();});
pthread_mutex_unlock(&this->logical->ng->mut);
});
}
}
});

View File

@@ -51,7 +51,7 @@ struct GrNode : wxPanel {
struct Port {
wxString name;
enum class Type {
NONE, FILE_OPEN, COLOR, VEC1, VEC2, VEC3, VEC4, TEXT, SAMPLE, FILE_SAVE, MIC_SOURCE, WINDOW_SOURCE
NONE, FILE_OPENING, COLOR, VEC1, VEC2, VEC3, VEC4, TEXT, SAMPLE, FILE_SAVING, MIC_SOURCE, WINDOW_SOURCE, CHECKBOX
} type;
bool separator;

View File

@@ -6,6 +6,9 @@ Frame *globaldis;
struct App : wxApp {
virtual bool OnInit() {
#if wxCHECK_VERSION(3, 3, 0)
SetAppearance(Appearance::System);
#endif
(new Frame())->Show(true);
return true;
}

View File

@@ -259,8 +259,8 @@ Timeline::Timeline(struct Frame *parent) : wxPanel(parent, wxID_ANY) {
switch(sinks[i].type) {
case GrNode::Port::Type::TEXT:
case GrNode::Port::Type::FILE_OPEN:
case GrNode::Port::Type::FILE_SAVE:
case GrNode::Port::Type::FILE_OPENING:
case GrNode::Port::Type::FILE_SAVING:
SetToolTip(wxString{val->text});
break;
case GrNode::Port::Type::VEC1: