9 Star 40 Fork 8

sinriv / meshlang

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
node.cpp 17.08 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
#include "node.h"
#include <QMessageBox>
namespace meshlang{
void line::remove(bool erst,bool ered){
if(erst){
if(startId==-1){
start->trueThen = NULL;
}else
if(startId==-2){
start->falseThen = NULL;
}else{
try{
start->output.at(startId).erase(this);
}catch(...){
QMessageBox::information(NULL,"Error",QStringLiteral("找不到端口"),QMessageBox::Ok);
}
}
}
if(ered){
if(endId<0){
end->last.erase(this);
}else{
try{
end->input.at(endId).erase(this);
}catch(...){
QMessageBox::information(NULL,"Error",QStringLiteral("找不到端口"),QMessageBox::Ok);
}
}
}
delete this;
}
void program::addModule(const std::string & name,const std::vector<variable> & input,const std::vector<variable> & output,const HBB::vec & posi){
auto p = addFunc(name,input,output);
if(p){
std::vector<variable> var;
for(auto it:p->types){
var.push_back(variable(it.first,it.second));
}
var.push_back(variable("result","int"));
auto pname = name+"_self";
addFunc(pname,var,var);
auto npt = addNode(pname,posi);
npt->name = name;
npt->initval["result"] = "0";
}
}
function * functions::addFunc(const std::string & name,const std::vector<variable> & input,const std::vector<variable> & output){
if(funcs.find(name)!=funcs.end())
return NULL;
auto p = new function;
p->input.clear();
p->output.clear();
p->types.clear();
for(auto it:input){
p->types[it.name] = it.type;
}
for(auto it:output){
p->types[it.name] = it.type;
}
for(auto it:input){
p->input.push_back(variable(it.name,p->types[it.name]));
}
for(auto it:output){
p->output.push_back(variable(it.name,p->types[it.name]));
}
p->name = name;
p->size.X = 4;
p->size.Y = std::max(input.size(),output.size())*2 + 4;
p->isPrivate = false;
if(p->name.size()>5){
int len = p->name.size();
auto ns = p->name.c_str();
if(ns[len-1]=='f' && ns[len-2]=='l' && ns[len-3]=='e' && ns[len-4]=='s' && ns[len-5]=='_')
p->isPrivate = true;
}
funcs[name]=p;
return p;
}
functions::~functions(){
for(auto it:funcs){
delete it.second;
}
}
node * program::addNode(const std::string & name,const HBB::vec & tposition , int id){
if(id>0 && nodeMap.find(id)!=nodeMap.end()){
QMessageBox::information(NULL,"Error",QStringLiteral("id重名"),QMessageBox::Ok);
return NULL;
}
auto it = funcs.find(name);//找到函数
if(it==funcs.end()){
QMessageBox::information(NULL,"Error",QStringLiteral("找不到函数"),QMessageBox::Ok);
return NULL;
}
auto p = new node;
p->type = it->second;
p->input.resize(p->type->input.size());//设置输出
p->output.resize(p->type->output.size());
int len,i;
len=p->input.size();
for(i=0;i<len;++i){
p->input[i].clear();
p->initval[p->type->input[i].name] = "";
}
len=p->output.size();
for(i=0;i<len;++i){
p->output[i].clear();
p->initval[p->type->output[i].name] = "";
}
p->trueThen=NULL;
p->falseThen=NULL;
p->last.clear();
p->name.clear();
HBB::vec from,to;
//p->position = tposition - (p->type->size/2);
p->position = tposition;
from = p->position;
to = from + p->type->size;
p->em=elements.add(from,to,p);
if(id>0){
p->id = id;
if(id > nodeId){
nodeId = id;
}
}else{
p->id = ++nodeId;
}
nodeMap[p->id]=p;
nodes.insert(p);
return p;
}
void program::removeNode(node * n){
for(auto itn:n->input){
for(auto it:itn){
if(it){
removeLine(it,true,false);
}
}
}
for(auto itn:n->output){
for(auto it:itn){
if(it){
removeLine(it,false,true);
}
}
}
if(n->trueThen){
removeLine(n->trueThen,false,true);
}
if(n->falseThen){
removeLine(n->falseThen,false,true);
}
for(auto it:n->last){
removeLine(it,true,false);
}
n->last.clear();
if(n->em){
n->em->autodrop();
}
nodes.erase(n);
nodeMap.erase(n->id);
delete n;
}
line * program::link(int a, int ida, int b, int idb){
auto ita = nodeMap.find(a);
if(ita == nodeMap.end())
return NULL;
auto itb = nodeMap.find(b);
if(itb == nodeMap.end())
return NULL;
return link(ita->second,ida,itb->second,idb);
}
line * program::link(node * a,int ida,node * b,int idb){
try{
if((ida>=0 && idb<0) || (ida<0 && idb>=0)){
QMessageBox::information(NULL,"Error",QStringLiteral("流程端口与普通端口间无法连接"),QMessageBox::Ok);
return NULL;
}
bool isProcess = false;
if(ida>=0 && idb>=0){
for(auto it:a->output.at(ida)){
if(it->end == b && it->endId == idb)
return NULL;
}
for(auto it:b->input.at(idb)){
if(it->start == a && it->startId == ida)
return NULL;
}
if(a->type->output.at(ida).type!=b->type->input.at(idb).type)//类型不符
return NULL;
}else{
if(ida==-1 && a->trueThen!=NULL)
return NULL;
if(ida==-2 && a->falseThen!=NULL)
return NULL;
for(auto it:b->last){
if(it->start==a && it->startId==ida)
return NULL;
}
if(b->type->isPrivate)
return NULL;
if(ida==-2 && a->type->isPrivate)
return NULL;
isProcess = true;
}
auto p = new line;
if(!isProcess)
p->var = a->type->output.at(ida);
else
p->var.type.clear();
char buf[64];
snprintf(buf,64,"line%d",lineNum);
p->var.name = buf;
++lineNum;
p->startId = ida>=0 ? ida : (ida==-1 ? -1 : -2);
p->endId = idb>=0 ? idb : -2;
a->getPortPosition(p->startPosi,2,p->startId);
b->getPortPosition(p->endPosi ,1,p->endId);
if(ida<0 || idb<0){
if(ida==-1)
a->trueThen = p;
else
a->falseThen = p;
b->last.insert(p);
}else{
try{
a->output.at(p->startId).insert(p);
b->input.at(p->endId) .insert(p);
}catch(...){
}
}
p->start = a;
p->end = b;
printf("link %d %d %d %d\n" , a->id , ida , b->id , idb);
HBB::vec from,to;
from.X = std::min(a->position.X - a->type->size.X , b->position.X - b->type->size.X);
to.X = std::max(a->position.X + a->type->size.X , b->position.X + b->type->size.X);
from.Y = std::min(a->position.Y - a->type->size.Y , b->position.Y - b->type->size.Y);
to.Y = std::max(a->position.Y + a->type->size.Y , b->position.Y + b->type->size.Y);
from.Y-=4;
to.Y +=4;
p->em=elementlines.add(from,to,p);
lines.insert(p);
return p;
}catch(...){
QMessageBox::information(NULL,"Error",QStringLiteral("节点无法被连接"),QMessageBox::Ok);
return NULL;
}
}
void program::removeLine(line * l,bool erst,bool ered){
if(l->em){
l->em->autodrop();
}
lines.erase(l);
l->remove(erst,ered);
}
program::program(){
lineNum =0;
nodeId =0;
}
program::~program(){
for(auto it:lines)
delete it;
for(auto it:nodes)
delete it;
}
void node::getClickStatus(const HBB::vec & p , int & mode /* 1 input , 2 output , 3 center */ , int & port){
auto realp = p-position;
if(realp.X < 0 || realp.Y<0 || realp.X > 4){
mode=0;
return;
}
port = (int)(realp.Y/2) - 2;
if(realp.X<1){//left
mode = 1;
}else
if(realp.X>3){//right
mode = 2;
}else{//center
mode = 3;
}
}
void node::getPortPosition(HBB::vec & p , int mode /* 1 input , 2 output , 3 center */ , int port){
p.Y = (port+2) * 2 + 1;
if(mode==1){
p.X = 0;
}else
if(mode==3){
p.X = 2;
}else{
p.X = 4;
}
p = p+position;
}
void program::clickToRemove(const HBB::vec & a){
node * A=NULL;
elements.fetchByPoint(a,[](HBB::AABB * bx,void * arg){
*((node**)arg) = (node*)bx->data;
},&A);
if(A)
removeNode(A);
}
void program::clickToEdit(const HBB::vec & a){
node * A=NULL;
elements.fetchByPoint(a,[](HBB::AABB * bx,void * arg){
*((node**)arg) = (node*)bx->data;
},&A);
if(A){
int Amode,Aport;
A->getClickStatus(a,Amode,Aport);
try{
if(Amode==1){
if(Aport==-2){
if(!A->last.empty()){
for(auto p:A->last){
if(p)
removeLine(p);
}
}
}else{
for(auto p:A->input.at(Aport)){
if(p)
removeLine(p);
}
}
}else
if(Amode==2){
if(Aport==-1){
if(A->trueThen){
removeLine(A->trueThen);
}
}else
if(Aport==-2){
if(A->falseThen){
removeLine(A->falseThen);
}
}else{
auto p = A->output.at(Aport);
if(!p.empty()){
for(auto pt:p){
if(pt)
removeLine(pt);
}
}
}
}else
if(Amode==3){
editNode(A);
}
}catch(...){
}
}else{
if(!editNote(a))
showMenu();
}
}
void program::clickTwoPoint(const HBB::vec & a , const HBB::vec & b){
node * A=NULL;
int Amode,Aport;
node * B=NULL;
int Bmode,Bport;
elements.fetchByPoint(a,[](HBB::AABB * bx,void * arg){
*((node**)arg) = (node*)bx->data;
},&A);
elements.fetchByPoint(b,[](HBB::AABB * bx,void * arg){
*((node**)arg) = (node*)bx->data;
},&B);
if(A==NULL){
if(B==NULL){//添加
std::string inm;
getInsertingName(inm);
if(!inm.empty()){
B = addNode(inm,b);
}
}
}else{
A->getClickStatus(a,Amode,Aport);
if((Aport==-2 || Aport==-1) && Amode==2 && B==NULL){//添加并连线
if(Aport==-1){
if(A->trueThen)
return;
}else
if(Aport==-2){
if(A->falseThen)
return;
}
std::string inm;
getInsertingName(inm);
if(!inm.empty()){
B = addNode(inm,b);
if(B){
link(A,Aport,B,-1);
}
}
}else{
if(A!=B && B!=NULL){
B->getClickStatus(b,Bmode,Bport);
if(Amode==1 && Bmode==2){
link(B,Bport,A,Aport);
}else
if(Amode==2 && Bmode==1){
link(A,Aport,B,Bport);
}
}
}
}
}
void program::import(const std::string & path){
FILE * fp = fopen(path.c_str(),"r");
if(fp){
char buf[2048];
while(!feof(fp)){
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),fp);
std::istringstream iss(buf);
std::string active;
iss>>active;
if(active=="line"){
int a,aid,b,bid;
iss>>a;
iss>>aid;
iss>>b;
iss>>bid;
link(a,aid,b,bid);
}else
if(active=="node"){
std::string type;
int id=0;
float x,y;
iss>>type;
iss>>id;
iss>>x;
iss>>y;
addNode(type,HBB::vec(x,y),id);
}else
if(active=="function"){
std::string name;
iss>>name;
QString str = buf;
QStringList inlist = str.split("input:");
std::vector<variable> input,output;
input.clear();
output.clear();
if(inlist.size()>1){
QStringList flist = inlist[1].split("output:");
if(flist.size()>0){
QStringList inputs = flist[0].split(",");
for(auto it:inputs){
QString real = it.trimmed();
if(!real.isEmpty()){
QStringList var = real.split("/");
if(var.size()>1)
input.push_back(variable(var[1].toStdString(),var[0].toStdString()));
}
}
}
if(flist.size()>1){
QStringList outputs = flist[1].split(",");
for(auto it:outputs){
QString real = it.trimmed();
if(!real.isEmpty()){
QStringList var = real.split("/");
if(var.size()>1)
output.push_back(variable(var[1].toStdString(),var[0].toStdString()));
}
}
}
}
addFunc(name,input,output);
}else
if(active=="initval"){
int id;
std::string key;
std::string val;
iss>>id;
iss>>key;
iss>>val;
if(!key.empty() && !val.empty()){
auto it = nodeMap.find(id);
if(it!=nodeMap.end()){
it->second->initval[key] = QByteArray::fromPercentEncoding(val.c_str()).toStdString().c_str();
}
}
}else
if(active=="setName"){
int id;
std::string n;
iss>>id;
iss>>n;
if(!n.empty()){
auto it = nodeMap.find(id);
if(it!=nodeMap.end()){
it->second->name = n;
}
}
}else
if(active=="note"){
float x,y;
std::string val;
iss>>x;
iss>>y;
iss>>val;
addNote(QByteArray::fromPercentEncoding(val.c_str()).toStdString().c_str() , HBB::vec(x,y));
}
}
fclose(fp);
}else{
QMessageBox::information(NULL,"Error",QString("载入文件\"")+path.c_str()+"\"失败",QMessageBox::Ok);
}
}
void program::save(const std::string & path){
FILE * fp = fopen(path.c_str(),"w");
if(fp){
for(auto it:funcs){
fprintf(fp,"function %s input:",it.first.c_str());
bool first=true;
for(auto it2:it.second->input){
if(first)
fprintf(fp,"%s/%s",it2.type.c_str(),it2.name.c_str());
else
fprintf(fp,",%s/%s",it2.type.c_str(),it2.name.c_str());
first = false;
}
first = true;
fprintf(fp," output:");
for(auto it2:it.second->output){
if(first)
fprintf(fp,"%s/%s",it2.type.c_str(),it2.name.c_str());
else
fprintf(fp,",%s/%s",it2.type.c_str(),it2.name.c_str());
first = false;
}
fprintf(fp," \n");
}
for(auto it:nodes){
fprintf(fp,"node %s %d %f %f\n" , it->type->name.c_str() , it->id , it->position.X , it->position.Y);
if(!it->name.empty())
fprintf(fp,"setName %d %s\n" , it->id , it->name.c_str());
for(auto it2:it->initval){
if(!it2.second.empty()){
QByteArray barr = it2.second.c_str();
fprintf(fp,"initval %d %s %s\n" , it->id , it2.first.c_str() , barr.toPercentEncoding().toStdString().c_str());
}
}
}
for(auto it:lines){
fprintf(fp,"line %d %d %d %d\n" , it->start->id , it->startId , it->end->id , it->endId);
}
saveNotes(fp);
fclose(fp);
}
}
}
C++
1
https://gitee.com/sinriv/meshlang.git
git@gitee.com:sinriv/meshlang.git
sinriv
meshlang
meshlang
master

搜索帮助