From a7407edaf81c685d4a389785a405a53a5de4b148 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Tue, 12 May 2020 00:58:40 +0800 Subject: Format EVERYTHING. Hopefully this will make the source code less horrendous and actually readable. The command used was: ``` astyle --suffix=none --style=allman --attach-extern-c --attach-closing-while --indent-switches --indent-after-parens --pad-oper --pad-header --unpad-paren --align-pointer=name --recursive './*.cpp,*.hpp' ``` --- visualization/extrasmeltutils.cpp | 657 ++++---- visualization/extrasmeltutils.hpp | 234 +-- visualization/qmpvirtualpiano3d.cpp | 426 ++--- visualization/qmpvirtualpiano3d.hpp | 20 +- visualization/qmpvisualization.cpp | 2249 +++++++++++++++------------ visualization/qmpvisualization.hpp | 188 ++- visualization/renderer/main.cpp | 80 +- visualization/renderer/qmppluginapistub.cpp | 220 ++- visualization/renderer/qmppluginapistub.hpp | 140 +- visualization/renderer/qmpsettingsro.cpp | 310 ++-- visualization/renderer/qmpsettingsro.hpp | 103 +- visualization/renderer/qmpvisrendercore.cpp | 463 +++--- visualization/renderer/qmpvisrendercore.hpp | 67 +- 13 files changed, 2867 insertions(+), 2290 deletions(-) (limited to 'visualization') diff --git a/visualization/extrasmeltutils.cpp b/visualization/extrasmeltutils.cpp index 2d0a807..ec9f021 100644 --- a/visualization/extrasmeltutils.cpp +++ b/visualization/extrasmeltutils.cpp @@ -3,367 +3,494 @@ #include #include #include "extrasmeltutils.hpp" -SMELT* smEntity3DBuffer::sm=nullptr; -SMELT* smParticle::sm=nullptr; -SMELT* smParticleSystem::sm=nullptr; -smVertex makeVertex(float x,float y,float z,DWORD color,float tx,float ty) -{smVertex v;v.x=x;v.y=y;v.z=z;v.col=color;v.tx=tx;v.ty=ty;return v;} -void smEntity3D::addVertices(size_t n,...) -{ - va_list vl;va_start(vl,n); - for(int i=0;i0&&idx 0 && idx < vertices.size()) + return vertices[idx]; + return smVertex(); } WORD smEntity3D::index(size_t idx)const { - if(idx>0&&idx 0 && idx < indices.size()) + return indices[idx]; + return 0; } -void smEntity3D::setVertex(size_t idx,smVertex v) +void smEntity3D::setVertex(size_t idx, smVertex v) { - if(idx>0&&idx 0 && idx < vertices.size()) + vertices[idx] = v; } -void smEntity3D::setIndex(size_t idx,WORD i) +void smEntity3D::setIndex(size_t idx, WORD i) { - if(idx>0&&idx 0 && idx < indices.size()) + indices[idx] = i; } -smEntity3D smEntity3D::cube(smvec3d a,smvec3d b,DWORD color,int faces) -{ - smEntity3D ret; - ret.addVertices(8, - makeVertex(a.x,a.y,a.z,color,0,0),makeVertex(b.x,a.y,a.z,color,0,0), - makeVertex(b.x,b.y,a.z,color,0,0),makeVertex(a.x,b.y,a.z,color,0,0), - makeVertex(a.x,a.y,b.z,color,0,0),makeVertex(b.x,a.y,b.z,color,0,0), - makeVertex(b.x,b.y,b.z,color,0,0),makeVertex(a.x,b.y,b.z,color,0,0)); - if(faces&0x1)//a.z - ret.addIndices(6, 0,1,3, 1,2,3); - if(faces&0x2)//b.z - ret.addIndices(6, 4,5,7, 5,6,7); - if(faces&0x4)//a.x - ret.addIndices(6, 0,3,7, 0,4,7); - if(faces&0x8)//b.x - ret.addIndices(6, 1,2,6, 1,5,6); - if(faces&0x10)//a.y - ret.addIndices(6, 0,1,4, 1,4,5); - if(faces&0x20)//b.y - ret.addIndices(6, 2,3,7, 2,6,7); - return ret; +smEntity3D smEntity3D::cube(smvec3d a, smvec3d b, DWORD color, int faces) +{ + smEntity3D ret; + ret.addVertices(8, + makeVertex(a.x, a.y, a.z, color, 0, 0), makeVertex(b.x, a.y, a.z, color, 0, 0), + makeVertex(b.x, b.y, a.z, color, 0, 0), makeVertex(a.x, b.y, a.z, color, 0, 0), + makeVertex(a.x, a.y, b.z, color, 0, 0), makeVertex(b.x, a.y, b.z, color, 0, 0), + makeVertex(b.x, b.y, b.z, color, 0, 0), makeVertex(a.x, b.y, b.z, color, 0, 0)); + if (faces & 0x1) //a.z + ret.addIndices(6, 0, 1, 3, 1, 2, 3); + if (faces & 0x2) //b.z + ret.addIndices(6, 4, 5, 7, 5, 6, 7); + if (faces & 0x4) //a.x + ret.addIndices(6, 0, 3, 7, 0, 4, 7); + if (faces & 0x8) //b.x + ret.addIndices(6, 1, 2, 6, 1, 5, 6); + if (faces & 0x10) //a.y + ret.addIndices(6, 0, 1, 4, 1, 4, 5); + if (faces & 0x20) //b.y + ret.addIndices(6, 2, 3, 7, 2, 6, 7); + return ret; } smEntity3DBuffer::smEntity3DBuffer() { - sm=smGetInterface(SMELT_APILEVEL); - vertices.clear();indices.clear(); + sm = smGetInterface(SMELT_APILEVEL); + vertices.clear(); + indices.clear(); } -void smEntity3DBuffer::addTransformedEntity(smEntity3D *entity,smMatrix t,smvec3d p) +void smEntity3DBuffer::addTransformedEntity(smEntity3D *entity, smMatrix t, smvec3d p) { - if(entity->vertices.size()+vertices.size()>4000)drawBatch(); - for(unsigned i=0;iindices.size();++i) - indices.push_back(entity->indices[i]+vertices.size()); - for(unsigned i=0;ivertices.size();++i) - { - smvec3d tp=smvec3d(entity->vertices[i].x,entity->vertices[i].y,entity->vertices[i].z); - tp=t*tp;tp=tp+p;vertices.push_back(makeVertex(tp.x,tp.y,tp.z,entity->vertices[i].col,entity->vertices[i].tx,entity->vertices[i].ty)); - } + if (entity->vertices.size() + vertices.size() > 4000) + drawBatch(); + for (unsigned i = 0; i < entity->indices.size(); ++i) + indices.push_back(entity->indices[i] + vertices.size()); + for (unsigned i = 0; i < entity->vertices.size(); ++i) + { + smvec3d tp = smvec3d(entity->vertices[i].x, entity->vertices[i].y, entity->vertices[i].z); + tp = t * tp; + tp = tp + p; + vertices.push_back(makeVertex(tp.x, tp.y, tp.z, entity->vertices[i].col, entity->vertices[i].tx, entity->vertices[i].ty)); + } } void smEntity3DBuffer::drawBatch() { - if(!vertices.size())return; - sm->smDrawCustomIndexedVertices(&vertices[0],&indices[0],vertices.size(),indices.size(),BLEND_ALPHABLEND,0); - vertices.clear();indices.clear(); + if (!vertices.size()) + return; + sm->smDrawCustomIndexedVertices(&vertices[0], &indices[0], vertices.size(), indices.size(), BLEND_ALPHABLEND, 0); + vertices.clear(); + indices.clear(); } smParticle::smParticle() -{sm=smGetInterface(SMELT_APILEVEL);dead=false;clifespan=0;} -smParticle::~smParticle(){sm->smRelease();} +{ + sm = smGetInterface(SMELT_APILEVEL); + dead = false; + clifespan = 0; +} +smParticle::~smParticle() +{ + sm->smRelease(); +} void smParticle::render() -{sm->smRenderQuad(&q);} +{ + sm->smRenderQuad(&q); +} void smParticle::update() { - clifespan+=sm->smGetDelta();if(clifespan>lifespan){dead=true;return;} - vel=vel+accel;pos=pos+vel;rotv=rotv+rota;rot=rot+rotv; - size=clifespan/lifespan*(finalsize-initsize)+initsize; - smColorRGBA fc(finalcolor),ic(initcolor),cc; - cc.a=clifespan/lifespan*(fc.a-ic.a)+ic.a; - cc.r=clifespan/lifespan*(fc.r-ic.r)+ic.r; - cc.g=clifespan/lifespan*(fc.g-ic.g)+ic.g; - cc.b=clifespan/lifespan*(fc.b-ic.b)+ic.b; - color=cc.getHWColor(); - for(int i=0;i<4;++i)q.v[i].col=color; - smMatrix m;m.loadIdentity(); - if(lookat)m.lookat(pos,lookatpos,smvec3d(0,0,1));else - {m.rotate(rot.x,1,0,0);m.rotate(rot.y,0,1,0);m.rotate(rot.z,0,0,1);} - smvec3d v0=m*smvec3d(-size,-size,0),v1=m*smvec3d(size,-size,0); - smvec3d v2=m*smvec3d(size,size,0),v3=m*smvec3d(-size,size,0); - q.v[0].x=v0.x+pos.x;q.v[0].y=v0.y+pos.y;q.v[0].z=v0.z+pos.z; - q.v[1].x=v1.x+pos.x;q.v[1].y=v1.y+pos.y;q.v[1].z=v1.z+pos.z; - q.v[2].x=v2.x+pos.x;q.v[2].y=v2.y+pos.y;q.v[2].z=v2.z+pos.z; - q.v[3].x=v3.x+pos.x;q.v[3].y=v3.y+pos.y;q.v[3].z=v3.z+pos.z; + clifespan += sm->smGetDelta(); + if (clifespan > lifespan) + { + dead = true; + return; + } + vel = vel + accel; + pos = pos + vel; + rotv = rotv + rota; + rot = rot + rotv; + size = clifespan / lifespan * (finalsize - initsize) + initsize; + smColorRGBA fc(finalcolor), ic(initcolor), cc; + cc.a = clifespan / lifespan * (fc.a - ic.a) + ic.a; + cc.r = clifespan / lifespan * (fc.r - ic.r) + ic.r; + cc.g = clifespan / lifespan * (fc.g - ic.g) + ic.g; + cc.b = clifespan / lifespan * (fc.b - ic.b) + ic.b; + color = cc.getHWColor(); + for (int i = 0; i < 4; ++i) + q.v[i].col = color; + smMatrix m; + m.loadIdentity(); + if (lookat) + m.lookat(pos, lookatpos, smvec3d(0, 0, 1)); + else + { + m.rotate(rot.x, 1, 0, 0); + m.rotate(rot.y, 0, 1, 0); + m.rotate(rot.z, 0, 0, 1); + } + smvec3d v0 = m * smvec3d(-size, -size, 0), v1 = m * smvec3d(size, -size, 0); + smvec3d v2 = m * smvec3d(size, size, 0), v3 = m * smvec3d(-size, size, 0); + q.v[0].x = v0.x + pos.x; + q.v[0].y = v0.y + pos.y; + q.v[0].z = v0.z + pos.z; + q.v[1].x = v1.x + pos.x; + q.v[1].y = v1.y + pos.y; + q.v[1].z = v1.z + pos.z; + q.v[2].x = v2.x + pos.x; + q.v[2].y = v2.y + pos.y; + q.v[2].z = v2.z + pos.z; + q.v[3].x = v3.x + pos.x; + q.v[3].y = v3.y + pos.y; + q.v[3].z = v3.z + pos.z; } smParticleSystem::smParticleSystem() -{sm=smGetInterface(SMELT_APILEVEL);particles.clear();posGenerator=nullptr;active=false;} +{ + sm = smGetInterface(SMELT_APILEVEL); + particles.clear(); + posGenerator = nullptr; + active = false; +} smParticleSystem::~smParticleSystem() -{for(unsigned i=0;ismGetDelta(); - if(active&&cemdelay>nemdelay&&(int)particles.size()pos=pos+(posGenerator?posGenerator->genPos():smvec3d(0,0,0)); - p->vel=smvec3d( - re.nextDouble(psinfo.vel.x-psinfo.velvar.x,psinfo.vel.x+psinfo.velvar.x), - re.nextDouble(psinfo.vel.y-psinfo.velvar.y,psinfo.vel.y+psinfo.velvar.y), - re.nextDouble(psinfo.vel.z-psinfo.velvar.z,psinfo.vel.z+psinfo.velvar.z)); - p->accel=smvec3d( - re.nextDouble(psinfo.acc.x-psinfo.accvar.x,psinfo.acc.x+psinfo.accvar.x), - re.nextDouble(psinfo.acc.y-psinfo.accvar.y,psinfo.acc.y+psinfo.accvar.y), - re.nextDouble(psinfo.acc.z-psinfo.accvar.z,psinfo.acc.z+psinfo.accvar.z)); - p->rotv=smvec3d( - re.nextDouble(psinfo.rotv.x-psinfo.rotvvar.x,psinfo.rotv.x+psinfo.rotvvar.x), - re.nextDouble(psinfo.rotv.y-psinfo.rotvvar.y,psinfo.rotv.y+psinfo.rotvvar.y), - re.nextDouble(psinfo.rotv.z-psinfo.rotvvar.z,psinfo.rotv.z+psinfo.rotvvar.z)); - p->rota=smvec3d( - re.nextDouble(psinfo.rota.x-psinfo.rotavar.x,psinfo.rota.x+psinfo.rotavar.x), - re.nextDouble(psinfo.rota.y-psinfo.rotavar.y,psinfo.rota.y+psinfo.rotavar.y), - re.nextDouble(psinfo.rota.z-psinfo.rotavar.z,psinfo.rota.z+psinfo.rotavar.z)); - p->rot=smvec3d(0,0,0);if(lookat)p->lookat=true,p->lookatpos=lookatpos;else p->lookat=false; - p->lifespan=re.nextDouble(psinfo.lifespan-psinfo.lifespanvar,psinfo.lifespan+psinfo.lifespanvar); - p->initsize=re.nextDouble(psinfo.initsize-psinfo.initsizevar,psinfo.initsize+psinfo.initsizevar); - p->finalsize=re.nextDouble(psinfo.finalsize-psinfo.finalsizevar,psinfo.finalsize+psinfo.finalsizevar); - p->size=p->initsize; - p->initcolor=ARGB( - re.nextInt(GETA(psinfo.initcolor)-GETA(psinfo.initcolorvar),GETA(psinfo.initcolor)+GETA(psinfo.initcolorvar)), - re.nextInt(GETR(psinfo.initcolor)-GETR(psinfo.initcolorvar),GETR(psinfo.initcolor)+GETR(psinfo.initcolorvar)), - re.nextInt(GETG(psinfo.initcolor)-GETG(psinfo.initcolorvar),GETG(psinfo.initcolor)+GETG(psinfo.initcolorvar)), - re.nextInt(GETB(psinfo.initcolor)-GETB(psinfo.initcolorvar),GETB(psinfo.initcolor)+GETB(psinfo.initcolorvar))); - p->finalcolor=ARGB( - re.nextInt(GETA(psinfo.finalcolor)-GETA(psinfo.finalcolorvar),GETA(psinfo.finalcolor)+GETA(psinfo.finalcolorvar)), - re.nextInt(GETR(psinfo.finalcolor)-GETR(psinfo.finalcolorvar),GETR(psinfo.finalcolor)+GETR(psinfo.finalcolorvar)), - re.nextInt(GETG(psinfo.finalcolor)-GETG(psinfo.finalcolorvar),GETG(psinfo.finalcolor)+GETG(psinfo.finalcolorvar)), - re.nextInt(GETB(psinfo.finalcolor)-GETB(psinfo.finalcolorvar),GETB(psinfo.finalcolor)+GETB(psinfo.finalcolorvar))); - p->color=p->initcolor;p->q.tex=psinfo.texture;p->q.blend=psinfo.blend; - p->q.v[0].tx=p->q.v[3].tx=0;p->q.v[0].ty=p->q.v[1].ty=0; - p->q.v[1].tx=p->q.v[2].tx=1;p->q.v[2].ty=p->q.v[3].ty=1; - particles.push_back(p); - } - cemdelay=0; - nemdelay=re.nextDouble(psinfo.emissiondelay-psinfo.edvar,psinfo.emissiondelay+psinfo.edvar); - } - for(unsigned i=0,j;idead;++i) - { - particles[i]->update(); - if(particles[i]->dead) - { - for(j=particles.size()-1;j>i&&particles[j]->dead;--j); - std::swap(particles[i],particles[j]); - } - } - while(!particles.empty()&&particles.back()->dead) - {delete particles.back();particles.back()=nullptr;particles.pop_back();} + cemdelay += sm->smGetDelta(); + if (active && cemdelay > nemdelay && (int)particles.size() < psinfo.maxcount) + { + int ec = re.nextInt(psinfo.emissioncount - psinfo.ecvar, psinfo.emissioncount + psinfo.ecvar); + for (int i = 0; i < ec; ++i) + { + smParticle *p = new smParticle(); + p->pos = pos + (posGenerator ? posGenerator->genPos() : smvec3d(0, 0, 0)); + p->vel = smvec3d( + re.nextDouble(psinfo.vel.x - psinfo.velvar.x, psinfo.vel.x + psinfo.velvar.x), + re.nextDouble(psinfo.vel.y - psinfo.velvar.y, psinfo.vel.y + psinfo.velvar.y), + re.nextDouble(psinfo.vel.z - psinfo.velvar.z, psinfo.vel.z + psinfo.velvar.z)); + p->accel = smvec3d( + re.nextDouble(psinfo.acc.x - psinfo.accvar.x, psinfo.acc.x + psinfo.accvar.x), + re.nextDouble(psinfo.acc.y - psinfo.accvar.y, psinfo.acc.y + psinfo.accvar.y), + re.nextDouble(psinfo.acc.z - psinfo.accvar.z, psinfo.acc.z + psinfo.accvar.z)); + p->rotv = smvec3d( + re.nextDouble(psinfo.rotv.x - psinfo.rotvvar.x, psinfo.rotv.x + psinfo.rotvvar.x), + re.nextDouble(psinfo.rotv.y - psinfo.rotvvar.y, psinfo.rotv.y + psinfo.rotvvar.y), + re.nextDouble(psinfo.rotv.z - psinfo.rotvvar.z, psinfo.rotv.z + psinfo.rotvvar.z)); + p->rota = smvec3d( + re.nextDouble(psinfo.rota.x - psinfo.rotavar.x, psinfo.rota.x + psinfo.rotavar.x), + re.nextDouble(psinfo.rota.y - psinfo.rotavar.y, psinfo.rota.y + psinfo.rotavar.y), + re.nextDouble(psinfo.rota.z - psinfo.rotavar.z, psinfo.rota.z + psinfo.rotavar.z)); + p->rot = smvec3d(0, 0, 0); + if (lookat) + p->lookat = true, p->lookatpos = lookatpos; + else p->lookat = false; + p->lifespan = re.nextDouble(psinfo.lifespan - psinfo.lifespanvar, psinfo.lifespan + psinfo.lifespanvar); + p->initsize = re.nextDouble(psinfo.initsize - psinfo.initsizevar, psinfo.initsize + psinfo.initsizevar); + p->finalsize = re.nextDouble(psinfo.finalsize - psinfo.finalsizevar, psinfo.finalsize + psinfo.finalsizevar); + p->size = p->initsize; + p->initcolor = ARGB( + re.nextInt(GETA(psinfo.initcolor) - GETA(psinfo.initcolorvar), GETA(psinfo.initcolor) + GETA(psinfo.initcolorvar)), + re.nextInt(GETR(psinfo.initcolor) - GETR(psinfo.initcolorvar), GETR(psinfo.initcolor) + GETR(psinfo.initcolorvar)), + re.nextInt(GETG(psinfo.initcolor) - GETG(psinfo.initcolorvar), GETG(psinfo.initcolor) + GETG(psinfo.initcolorvar)), + re.nextInt(GETB(psinfo.initcolor) - GETB(psinfo.initcolorvar), GETB(psinfo.initcolor) + GETB(psinfo.initcolorvar))); + p->finalcolor = ARGB( + re.nextInt(GETA(psinfo.finalcolor) - GETA(psinfo.finalcolorvar), GETA(psinfo.finalcolor) + GETA(psinfo.finalcolorvar)), + re.nextInt(GETR(psinfo.finalcolor) - GETR(psinfo.finalcolorvar), GETR(psinfo.finalcolor) + GETR(psinfo.finalcolorvar)), + re.nextInt(GETG(psinfo.finalcolor) - GETG(psinfo.finalcolorvar), GETG(psinfo.finalcolor) + GETG(psinfo.finalcolorvar)), + re.nextInt(GETB(psinfo.finalcolor) - GETB(psinfo.finalcolorvar), GETB(psinfo.finalcolor) + GETB(psinfo.finalcolorvar))); + p->color = p->initcolor; + p->q.tex = psinfo.texture; + p->q.blend = psinfo.blend; + p->q.v[0].tx = p->q.v[3].tx = 0; + p->q.v[0].ty = p->q.v[1].ty = 0; + p->q.v[1].tx = p->q.v[2].tx = 1; + p->q.v[2].ty = p->q.v[3].ty = 1; + particles.push_back(p); + } + cemdelay = 0; + nemdelay = re.nextDouble(psinfo.emissiondelay - psinfo.edvar, psinfo.emissiondelay + psinfo.edvar); + } + for (unsigned i = 0, j; i < particles.size() && !particles[i]->dead; ++i) + { + particles[i]->update(); + if (particles[i]->dead) + { + for (j = particles.size() - 1; j > i && particles[j]->dead; --j); + std::swap(particles[i], particles[j]); + } + } + while (!particles.empty() && particles.back()->dead) + { + delete particles.back(); + particles.back() = nullptr; + particles.pop_back(); + } } void smParticleSystem::renderPS() -{for(unsigned i=0;irender();} +{ + for (unsigned i = 0; i < particles.size(); ++i) + particles[i]->render(); +} smColor::smColor() -{r=g=b=h=s=v=a=0;} +{ + r = g = b = h = s = v = a = 0; +} void smColor::update_rgb() { - auto f=[this](float n){ - float k=fmodf(n+6.0f*this->h,6.0f); - return this->v-this->v*this->s*max(0.0f,min(1.0f,min(k,4.0f-k))); - }; - r=f(5); - g=f(3); - b=f(1); + auto f = [this](float n) + { + float k = fmodf(n + 6.0f * this->h, 6.0f); + return this->v - this->v * this->s * max(0.0f, min(1.0f, min(k, 4.0f - k))); + }; + r = f(5); + g = f(3); + b = f(1); } void smColor::update_hsv() { - v=max(r,max(g,b)); - float vm=min(r,min(g,b)); - float chroma=v-vm; - if(v-vmEPSF) - { - r=red; - update_hsv(); - } + if (fabsf(r - red) > EPSF) + { + r = red; + update_hsv(); + } } void smColor::setGreen(float green) { - if(fabsf(g-green)>EPSF) - { - g=green; - update_hsv(); - } + if (fabsf(g - green) > EPSF) + { + g = green; + update_hsv(); + } } void smColor::setBlue(float blue) { - if(fabsf(b-blue)>EPSF) - { - b=blue; - update_hsv(); - } + if (fabsf(b - blue) > EPSF) + { + b = blue; + update_hsv(); + } } void smColor::setHue(float hue) { - if(fabsf(h-hue)>EPSF) - { - h=hue; - update_rgb(); - } + if (fabsf(h - hue) > EPSF) + { + h = hue; + update_rgb(); + } } void smColor::setSaturation(float saturation) { - if(fabsf(s-saturation)>EPSF) - { - s=saturation; - update_rgb(); - } + if (fabsf(s - saturation) > EPSF) + { + s = saturation; + update_rgb(); + } } void smColor::setHSLSaturation(float saturation) { - float ss=hslSaturation(); - float l=lightness(); - if(fabsf(ss-saturation)>EPSF) - { - ss=saturation; - v=l+ss*min(l,1-l); - if(v EPSF) + { + ss = saturation; + v = l + ss * min(l, 1 - l); + if (v < EPSF) + s = 0; + else s = 2 - 2 * l / v; + update_rgb(); + } } void smColor::setValue(float value) { - if(fabsf(v-value)>EPSF) - { - v=value; - update_rgb(); - } + if (fabsf(v - value) > EPSF) + { + v = value; + update_rgb(); + } } void smColor::setLightness(float lightness) { - float ss=hslSaturation(); - float l=this->lightness(); - if(fabsf(l-lightness)>EPSF) - { - l=lightness; - v=l+ss*min(l,1-l); - if(vlightness(); + if (fabsf(l - lightness) > EPSF) + { + l = lightness; + v = l + ss * min(l, 1 - l); + if (v < EPSF) + s = 0; + else s = 2 - 2 * l / v; + update_rgb(); + } } smColor smColor::lighter(int factor) { - smColor ret(*this); - ret.setValue(v*(factor/100.0f)); - ret.clamp(true); - return ret; + smColor ret(*this); + ret.setValue(v * (factor / 100.0f)); + ret.clamp(true); + return ret; } smColor smColor::darker(int factor) { - smColor ret(*this); - ret.setValue(factor?(v/(factor/100.0f)):1.); - ret.clamp(true); - return ret; + smColor ret(*this); + ret.setValue(factor ? (v / (factor / 100.0f)) : 1.); + ret.clamp(true); + return ret; } uint32_t smColor::toHWColor() { - return RGBA(r*255,g*255,b*255,a*255); + return RGBA(r * 255, g * 255, b * 255, a * 255); } smColor smColor::fromHWColor(uint32_t color) { - smColor ret; - ret.r=GETR(color)/255.0f; - ret.g=GETG(color)/255.0f; - ret.b=GETB(color)/255.0f; - ret.a=GETA(color)/255.0f; - ret.update_hsv(); - return ret; + smColor ret; + ret.r = GETR(color) / 255.0f; + ret.g = GETG(color) / 255.0f; + ret.b = GETB(color) / 255.0f; + ret.a = GETA(color) / 255.0f; + ret.update_hsv(); + return ret; } diff --git a/visualization/extrasmeltutils.hpp b/visualization/extrasmeltutils.hpp index 3cea3fc..ca36415 100644 --- a/visualization/extrasmeltutils.hpp +++ b/visualization/extrasmeltutils.hpp @@ -13,134 +13,152 @@ #define EPSF 1e-6f class smEntity3D { - friend class smEntity3DBuffer; - private: - std::vector vertices; - std::vector indices; - public: - smEntity3D(){vertices.clear();indices.clear();} - void addVertices(size_t n,...); - void addIndices(size_t n,...); - smVertex vertex(size_t idx)const; - WORD index(size_t idx)const; - void setVertex(size_t idx,smVertex v); - void setIndex(size_t idx,WORD i); - static smEntity3D cube(smvec3d tl,smvec3d br,DWORD color,int faces=63); + friend class smEntity3DBuffer; +private: + std::vector vertices; + std::vector indices; +public: + smEntity3D() + { + vertices.clear(); + indices.clear(); + } + void addVertices(size_t n, ...); + void addIndices(size_t n, ...); + smVertex vertex(size_t idx)const; + WORD index(size_t idx)const; + void setVertex(size_t idx, smVertex v); + void setIndex(size_t idx, WORD i); + static smEntity3D cube(smvec3d tl, smvec3d br, DWORD color, int faces = 63); }; class smEntity3DBuffer { - private: - std::vector vertices; - std::vector indices; - static SMELT* sm; - public: - smEntity3DBuffer(); - ~smEntity3DBuffer(){sm->smRelease();} - void addTransformedEntity(smEntity3D *entity,smMatrix t,smvec3d p); - void drawBatch(); +private: + std::vector vertices; + std::vector indices; + static SMELT *sm; +public: + smEntity3DBuffer(); + ~smEntity3DBuffer() + { + sm->smRelease(); + } + void addTransformedEntity(smEntity3D *entity, smMatrix t, smvec3d p); + void drawBatch(); }; class smColor { - private: - float r,g,b,h,s,v,a; - void update_rgb(); - void update_hsv(); - public: - smColor(); - void clamp(bool hsv); - float alpha()const; - float red()const; - float green()const; - float blue()const; - float hue()const; - float saturation()const; - float hslSaturation()const; - float value()const; - float lightness()const; - void setAlpha(float alpha); - void setRed(float red); - void setGreen(float green); - void setBlue(float blue); - void setHue(float hue); - void setSaturation(float saturation); - void setHSLSaturation(float saturation); - void setValue(float value); - void setLightness(float lightness); - smColor lighter(int factor); - smColor darker(int factor); - uint32_t toHWColor(); - static smColor fromHWColor(uint32_t color); +private: + float r, g, b, h, s, v, a; + void update_rgb(); + void update_hsv(); +public: + smColor(); + void clamp(bool hsv); + float alpha()const; + float red()const; + float green()const; + float blue()const; + float hue()const; + float saturation()const; + float hslSaturation()const; + float value()const; + float lightness()const; + void setAlpha(float alpha); + void setRed(float red); + void setGreen(float green); + void setBlue(float blue); + void setHue(float hue); + void setSaturation(float saturation); + void setHSLSaturation(float saturation); + void setValue(float value); + void setLightness(float lightness); + smColor lighter(int factor); + smColor darker(int factor); + uint32_t toHWColor(); + static smColor fromHWColor(uint32_t color); }; class smPSEmissionPositionGenerator { - public: - virtual smvec3d genPos(){return smvec3d(0,0,0);} +public: + virtual smvec3d genPos() + { + return smvec3d(0, 0, 0); + } }; -class smXLinePSGenerator:public smPSEmissionPositionGenerator +class smXLinePSGenerator: public smPSEmissionPositionGenerator { - private: - smRandomEngine re; - double var; - public: - smXLinePSGenerator(double _var){re.setSeed(time(nullptr));var=_var;} - smvec3d genPos(){return smvec3d(re.nextDouble(-var,var),0,0);} +private: + smRandomEngine re; + double var; +public: + smXLinePSGenerator(double _var) + { + re.setSeed(time(nullptr)); + var = _var; + } + smvec3d genPos() + { + return smvec3d(re.nextDouble(-var, var), 0, 0); + } }; class smParticleSystemInfo { - public: - smvec3d vel,velvar,acc,accvar; - smvec3d rotv,rotvvar,rota,rotavar; - double lifespan,lifespanvar; - int maxcount,emissioncount,ecvar; - double emissiondelay,edvar; - double initsize,initsizevar; - double finalsize,finalsizevar; - DWORD initcolor,initcolorvar; - DWORD finalcolor,finalcolorvar; - SMTEX texture;int blend; +public: + smvec3d vel, velvar, acc, accvar; + smvec3d rotv, rotvvar, rota, rotavar; + double lifespan, lifespanvar; + int maxcount, emissioncount, ecvar; + double emissiondelay, edvar; + double initsize, initsizevar; + double finalsize, finalsizevar; + DWORD initcolor, initcolorvar; + DWORD finalcolor, finalcolorvar; + SMTEX texture; + int blend; }; class smParticle { - friend class smParticleSystem; - private: - static SMELT* sm; - smvec3d pos,rot,lookatpos; - smvec3d vel,accel,rotv,rota; - double lifespan,clifespan; - double initsize,finalsize,size; - DWORD color,initcolor,finalcolor; - smQuad q; - bool dead,lookat; - public: - smParticle(); - ~smParticle(); - void render(); - void update(); + friend class smParticleSystem; +private: + static SMELT *sm; + smvec3d pos, rot, lookatpos; + smvec3d vel, accel, rotv, rota; + double lifespan, clifespan; + double initsize, finalsize, size; + DWORD color, initcolor, finalcolor; + smQuad q; + bool dead, lookat; +public: + smParticle(); + ~smParticle(); + void render(); + void update(); }; class smParticleSystem { - private: - static SMELT* sm; - std::vector particles; - smParticleSystemInfo psinfo; - smvec3d pos,lookatpos; - smRandomEngine re; - smPSEmissionPositionGenerator* posGenerator; - bool active,lookat; - double cemdelay,nemdelay; - public: - smParticleSystem(); - ~smParticleSystem(); - void setParticleSystemInfo(smParticleSystemInfo _psinfo); - void setPos(smvec3d _pos); - void setPSEmissionPosGen(smPSEmissionPositionGenerator* _gen); - void setPSLookAt(smvec3d at); - void unsetPSLookAt(); - void startPS(); - void stopPS(); - void updatePS(); - void renderPS(); +private: + static SMELT *sm; + std::vector particles; + smParticleSystemInfo psinfo; + smvec3d pos, lookatpos; + smRandomEngine re; + smPSEmissionPositionGenerator *posGenerator; + bool active, lookat; + double cemdelay, nemdelay; +public: + smParticleSystem(); + ~smParticleSystem(); + void setParticleSystemInfo(smParticleSystemInfo _psinfo); + void setPos(smvec3d _pos); + void setPSEmissionPosGen(smPSEmissionPositionGenerator *_gen); + void setPSLookAt(smvec3d at); + void unsetPSLookAt(); + void startPS(); + void stopPS(); + void updatePS(); + void renderPS(); }; -extern smVertex makeVertex(float x,float y,float z,DWORD color,float tx,float ty); +extern smVertex makeVertex(float x, float y, float z, DWORD color, float tx, float ty); #endif // EXTRASMELTUTILS_H diff --git a/visualization/qmpvirtualpiano3d.cpp b/visualization/qmpvirtualpiano3d.cpp index 0fbf75f..4ee7460 100644 --- a/visualization/qmpvirtualpiano3d.cpp +++ b/visualization/qmpvirtualpiano3d.cpp @@ -1,219 +1,249 @@ #include #include "qmpvirtualpiano3d.hpp" #define configureVertex(v,sub,_x,_y,_z) v[sub].x=_x,v[sub].y=_y,v[sub].z=_z; -const double gap[]={WK_TALWIDTH/2*0.92,WK_TALWIDTH/2*1.23,WK_TALWIDTH/2*1.2, - WK_TALWIDTH/2*0.95,WK_TALWIDTH*1.1,WK_TALWIDTH/2*0.95, - WK_TALWIDTH/2*1.2,WK_TALWIDTH/2*1.15,WK_TALWIDTH/2*1, - WK_TALWIDTH/2*1.3,WK_TALWIDTH/2*0.85,WK_TALWIDTH*1.1}; +const double gap[] = {WK_TALWIDTH / 2 * 0.92, WK_TALWIDTH / 2 * 1.23, WK_TALWIDTH / 2 * 1.2, + WK_TALWIDTH / 2 * 0.95, WK_TALWIDTH * 1.1, WK_TALWIDTH / 2 * 0.95, + WK_TALWIDTH / 2 * 1.2, WK_TALWIDTH / 2 * 1.15, WK_TALWIDTH / 2 * 1, + WK_TALWIDTH / 2 * 1.3, WK_TALWIDTH / 2 * 0.85, WK_TALWIDTH * 1.1 + }; qmpVirtualPiano3D::qmpVirtualPiano3D() { - ebuf=new smEntity3DBuffer();buildKeys();memset(traveld,0,sizeof(traveld)); + ebuf = new smEntity3DBuffer(); + buildKeys(); + memset(traveld, 0, sizeof(traveld)); } qmpVirtualPiano3D::~qmpVirtualPiano3D() { - delete wkcf;delete wkeb;delete wkd;delete wkg;delete wka;delete bk; - wkcf=wkeb=wkd=wkg=wka=bk=nullptr;delete ebuf;ebuf=nullptr; + delete wkcf; + delete wkeb; + delete wkd; + delete wkg; + delete wka; + delete bk; + wkcf = wkeb = wkd = wkg = wka = bk = nullptr; + delete ebuf; + ebuf = nullptr; } void qmpVirtualPiano3D::render(smvec3d p) { - p.x-=WK_TALWIDTH*37*1.075; - for(int i=0;i<128;++i) - { - smMatrix m;m.loadIdentity();m.rotate(-0.2*traveld[i],1,0,0); - switch(i%12) - { - case 0:case 5: - if(wkcf)ebuf->addTransformedEntity(wkcf,m,p); - break; - case 2: - if(wkd)ebuf->addTransformedEntity(wkd,m,p); - break; - case 4:case 11: - if(wkeb)ebuf->addTransformedEntity(wkeb,m,p); - break; - case 7: - if(wkg)ebuf->addTransformedEntity(wkg,m,p); - break; - case 9: - if(wka)ebuf->addTransformedEntity(wka,m,p); - break; - case 1:case 3:case 6:case 8:case 10: - if(bk)ebuf->addTransformedEntity(bk,m,p); - break; - } - p.x+=gap[i%12]; - } - ebuf->drawBatch(); + p.x -= WK_TALWIDTH * 37 * 1.075; + for (int i = 0; i < 128; ++i) + { + smMatrix m; + m.loadIdentity(); + m.rotate(-0.2 * traveld[i], 1, 0, 0); + switch (i % 12) + { + case 0: + case 5: + if (wkcf) + ebuf->addTransformedEntity(wkcf, m, p); + break; + case 2: + if (wkd) + ebuf->addTransformedEntity(wkd, m, p); + break; + case 4: + case 11: + if (wkeb) + ebuf->addTransformedEntity(wkeb, m, p); + break; + case 7: + if (wkg) + ebuf->addTransformedEntity(wkg, m, p); + break; + case 9: + if (wka) + ebuf->addTransformedEntity(wka, m, p); + break; + case 1: + case 3: + case 6: + case 8: + case 10: + if (bk) + ebuf->addTransformedEntity(bk, m, p); + break; + } + p.x += gap[i % 12]; + } + ebuf->drawBatch(); +} +void qmpVirtualPiano3D::setKeyTravelDist(int k, double td) +{ + traveld[k] = td; } -void qmpVirtualPiano3D::setKeyTravelDist(int k,double td) -{traveld[k]=td;} void qmpVirtualPiano3D::buildKeys() { - wkcf=new smEntity3D();wkeb=new smEntity3D();wkd=new smEntity3D(); - wkg=new smEntity3D();wka=new smEntity3D();bk=new smEntity3D(); - wkcf->addVertices(19, - makeVertex(-WK_TALWIDTH/2,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2+WK_PREWIDTH,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2+WK_PREWIDTH,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0),//// - makeVertex(-WK_TALWIDTH/2,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_PREWIDTH,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_PREWIDTH,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,0,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_PREWIDTH,0,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_PREWIDTH,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0)); - wkcf->addIndices(48, - 0,1,3, 1,2,3, 3,4,6, 4,5,6, - 7,8,13, 8,13,14, 8,14,15, 8,9,15, - 9,10,15, 10,15,16, 10,11,17, 10,16,17, - 11,12,18, 11,17,18, 18,12,13, 12,13,7); + wkcf = new smEntity3D(); + wkeb = new smEntity3D(); + wkd = new smEntity3D(); + wkg = new smEntity3D(); + wka = new smEntity3D(); + bk = new smEntity3D(); + wkcf->addVertices(19, + makeVertex(-WK_TALWIDTH / 2, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_PREWIDTH, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_PREWIDTH, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), //// + makeVertex(-WK_TALWIDTH / 2, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_PREWIDTH, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_PREWIDTH, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_PREWIDTH, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_PREWIDTH, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0)); + wkcf->addIndices(48, + 0, 1, 3, 1, 2, 3, 3, 4, 6, 4, 5, 6, + 7, 8, 13, 8, 13, 14, 8, 14, 15, 8, 9, 15, + 9, 10, 15, 10, 15, 16, 10, 11, 17, 10, 16, 17, + 11, 12, 18, 11, 17, 18, 18, 12, 13, 12, 13, 7); - wkeb->addVertices(19, - makeVertex( WK_TALWIDTH/2,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2-WK_PREWIDTH,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2-WK_PREWIDTH,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0),//// - makeVertex( WK_TALWIDTH/2,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2-WK_PREWIDTH,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2-WK_PREWIDTH,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,0,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2-WK_PREWIDTH,0,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2-WK_PREWIDTH,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0)); - wkeb->addIndices(48, - 0,1,3, 1,2,3, 3,4,6, 4,5,6, - 7,8,13, 8,13,14, 8,14,15, 8,9,15, - 9,10,15, 10,15,16, 10,11,17, 10,16,17, - 11,12,18, 11,17,18, 18,12,13, 12,13,7); + wkeb->addVertices(19, + makeVertex(WK_TALWIDTH / 2, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_PREWIDTH, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_PREWIDTH, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), //// + makeVertex(WK_TALWIDTH / 2, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_PREWIDTH, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_PREWIDTH, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_PREWIDTH, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_PREWIDTH, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0)); + wkeb->addIndices(48, + 0, 1, 3, 1, 2, 3, 3, 4, 6, 4, 5, 6, + 7, 8, 13, 8, 13, 14, 8, 14, 15, 8, 9, 15, + 9, 10, 15, 10, 15, 16, 10, 11, 17, 10, 16, 17, + 11, 12, 18, 11, 17, 18, 18, 12, 13, 12, 13, 7); - wkd->addVertices(24, - makeVertex(-WK_TALWIDTH/2+(WK_TALWIDTH-WK_PREWIDTH)/2,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2-(WK_TALWIDTH-WK_PREWIDTH)/2,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2-(WK_TALWIDTH-WK_PREWIDTH)/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2+(WK_TALWIDTH-WK_PREWIDTH)/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0),//// - makeVertex(-WK_TALWIDTH/2+(WK_TALWIDTH-WK_PREWIDTH)/2,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2-(WK_TALWIDTH-WK_PREWIDTH)/2,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2-(WK_TALWIDTH-WK_PREWIDTH)/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+(WK_TALWIDTH-WK_PREWIDTH)/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0),//// - makeVertex(-WK_TALWIDTH/2+(WK_TALWIDTH-WK_PREWIDTH)/2,0,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2-(WK_TALWIDTH-WK_PREWIDTH)/2,0,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2-(WK_TALWIDTH-WK_PREWIDTH)/2,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+(WK_TALWIDTH-WK_PREWIDTH)/2,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,0,0xFFCCCCCC,0,0)); - wkd->addIndices(60, - 0,1,2, 0,2,3, 4,5,6, 4,6,7, - 8,9,16, 9,16,17, 9,10,18, 9,17,18, - 10,12,18, 12,18,19, 12,13,20, 12,19,20, - 13,14,21, 13,20,21, 14,15,21, 15,21,22, - 15,11,22, 11,22,23, 11,23,8, 23,16,8); + wkd->addVertices(24, + makeVertex(-WK_TALWIDTH / 2 + (WK_TALWIDTH - WK_PREWIDTH) / 2, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2 - (WK_TALWIDTH - WK_PREWIDTH) / 2, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2 - (WK_TALWIDTH - WK_PREWIDTH) / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + (WK_TALWIDTH - WK_PREWIDTH) / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), //// + makeVertex(-WK_TALWIDTH / 2 + (WK_TALWIDTH - WK_PREWIDTH) / 2, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - (WK_TALWIDTH - WK_PREWIDTH) / 2, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - (WK_TALWIDTH - WK_PREWIDTH) / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + (WK_TALWIDTH - WK_PREWIDTH) / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), //// + makeVertex(-WK_TALWIDTH / 2 + (WK_TALWIDTH - WK_PREWIDTH) / 2, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - (WK_TALWIDTH - WK_PREWIDTH) / 2, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - (WK_TALWIDTH - WK_PREWIDTH) / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + (WK_TALWIDTH - WK_PREWIDTH) / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0)); + wkd->addIndices(60, + 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, + 8, 9, 16, 9, 16, 17, 9, 10, 18, 9, 17, 18, + 10, 12, 18, 12, 18, 19, 12, 13, 20, 12, 19, 20, + 13, 14, 21, 13, 20, 21, 14, 15, 21, 15, 21, 22, + 15, 11, 22, 11, 22, 23, 11, 23, 8, 23, 16, 8); - wkg->addVertices(24, - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12+WK_PREWIDTH,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12+WK_PREWIDTH,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0),//// - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12+WK_PREWIDTH,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12+WK_PREWIDTH,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0),//// - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12,0,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12+WK_PREWIDTH,0,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12+WK_PREWIDTH,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,0,0xFFCCCCCC,0,0)); - wkg->addIndices(60, - 0,1,2, 0,2,3, 4,5,6, 4,6,7, - 8,9,16, 9,16,17, 9,10,18, 9,17,18, - 10,12,18, 12,18,19, 12,13,20, 12,19,20, - 13,14,21, 13,20,21, 14,15,21, 15,21,22, - 15,11,22, 11,22,23, 11,23,8, 23,16,8); + wkg->addVertices(24, + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12 + WK_PREWIDTH, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12 + WK_PREWIDTH, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), //// + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12 + WK_PREWIDTH, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12 + WK_PREWIDTH, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), //// + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12 + WK_PREWIDTH, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12 + WK_PREWIDTH, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2 + WK_WING + WK_TALWIDTH / 12, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0)); + wkg->addIndices(60, + 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, + 8, 9, 16, 9, 16, 17, 9, 10, 18, 9, 17, 18, + 10, 12, 18, 12, 18, 19, 12, 13, 20, 12, 19, 20, + 13, 14, 21, 13, 20, 21, 14, 15, 21, 15, 21, 22, + 15, 11, 22, 11, 22, 23, 11, 23, 8, 23, 16, 8); - wka->addVertices(24, - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24-WK_PREWIDTH,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24,0,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24-WK_PREWIDTH,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN+WK_WING,WK_HEIGHT,0xFFFFFFFF,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFFFFFFF,0,0),//// - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24-WK_PREWIDTH,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24,0,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24-WK_PREWIDTH,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT,0xFFCCCCCC,0,0),//// - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24-WK_PREWIDTH,0,0,0xFFCCCCCC,0,0), - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24,0,0,0xFFCCCCCC,0,0), - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24-WK_PREWIDTH,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN,0,0xFFCCCCCC,0,0), - makeVertex( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,0,0xFFCCCCCC,0,0), - makeVertex(-WK_TALWIDTH/2,WK_PRELEN,0,0xFFCCCCCC,0,0)); - wka->addIndices(60, - 0,1,2, 0,2,3, 4,5,6, 4,6,7, - 8,9,16, 9,16,17, 9,10,18, 9,17,18, - 10,12,18, 12,18,19, 12,13,20, 12,19,20, - 13,14,21, 13,20,21, 14,15,21, 15,21,22, - 15,11,22, 11,22,23, 11,23,8, 23,16,8); + wka->addVertices(24, + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24 - WK_PREWIDTH, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24, 0, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24 - WK_PREWIDTH, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN + WK_WING, WK_HEIGHT, 0xFFFFFFFF, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFFFFFFF, 0, 0), //// + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24 - WK_PREWIDTH, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24, 0, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24 - WK_PREWIDTH, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, WK_HEIGHT, 0xFFCCCCCC, 0, 0), //// + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24 - WK_PREWIDTH, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24, 0, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2 - WK_WING - WK_TALWIDTH / 24 - WK_PREWIDTH, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN + WK_TALLEN, 0, 0xFFCCCCCC, 0, 0), + makeVertex(-WK_TALWIDTH / 2, WK_PRELEN, 0, 0xFFCCCCCC, 0, 0)); + wka->addIndices(60, + 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, + 8, 9, 16, 9, 16, 17, 9, 10, 18, 9, 17, 18, + 10, 12, 18, 12, 18, 19, 12, 13, 20, 12, 19, 20, + 13, 14, 21, 13, 20, 21, 14, 15, 21, 15, 21, 22, + 15, 11, 22, 11, 22, 23, 11, 23, 8, 23, 16, 8); - bk->addVertices(10, - makeVertex(-BK_WIDTH/2,0,BK_HEIGHT+BK_BOTTOM,0xFF000000,0,0), - makeVertex( BK_WIDTH/2,0,BK_HEIGHT+BK_BOTTOM,0xFF000000,0,0), - makeVertex( BK_WIDTH/2,BK_PRELEN,BK_HEIGHT+BK_BOTTOM,0xFF000000,0,0), - makeVertex(-BK_WIDTH/2,BK_PRELEN,BK_HEIGHT+BK_BOTTOM,0xFF000000,0,0), - makeVertex(-BK_WIDTH/2,WK_PRELEN*0.995,BK_DBOTTOM+BK_BOTTOM,0xFF000000,0,0), - makeVertex( BK_WIDTH/2,WK_PRELEN*0.995,BK_DBOTTOM+BK_BOTTOM,0xFF000000,0,0), - makeVertex( BK_WIDTH/2,WK_PRELEN*0.995,BK_BOTTOM,0xFF000000,0,0), - makeVertex(-BK_WIDTH/2,WK_PRELEN*0.995,BK_BOTTOM,0xFF000000,0,0), - makeVertex(-BK_WIDTH/2,0,BK_BOTTOM,0xFF000000,0,0), - makeVertex( BK_WIDTH/2,0,BK_BOTTOM,0xFF000000,0,0)); - bk->addIndices(48, - 0,1,3, 1,2,3, 2,3,4, 2,4,5, - 4,5,7, 5,6,7, 6,7,8, 6,8,9, - 0,1,8, 1,8,9, 2,5,6, 2,6,9, - 2,9,1, 3,4,7, 3,7,8, 3,8,0); + bk->addVertices(10, + makeVertex(-BK_WIDTH / 2, 0, BK_HEIGHT + BK_BOTTOM, 0xFF000000, 0, 0), + makeVertex(BK_WIDTH / 2, 0, BK_HEIGHT + BK_BOTTOM, 0xFF000000, 0, 0), + makeVertex(BK_WIDTH / 2, BK_PRELEN, BK_HEIGHT + BK_BOTTOM, 0xFF000000, 0, 0), + makeVertex(-BK_WIDTH / 2, BK_PRELEN, BK_HEIGHT + BK_BOTTOM, 0xFF000000, 0, 0), + makeVertex(-BK_WIDTH / 2, WK_PRELEN * 0.995, BK_DBOTTOM + BK_BOTTOM, 0xFF000000, 0, 0), + makeVertex(BK_WIDTH / 2, WK_PRELEN * 0.995, BK_DBOTTOM + BK_BOTTOM, 0xFF000000, 0, 0), + makeVertex(BK_WIDTH / 2, WK_PRELEN * 0.995, BK_BOTTOM, 0xFF000000, 0, 0), + makeVertex(-BK_WIDTH / 2, WK_PRELEN * 0.995, BK_BOTTOM, 0xFF000000, 0, 0), + makeVertex(-BK_WIDTH / 2, 0, BK_BOTTOM, 0xFF000000, 0, 0), + makeVertex(BK_WIDTH / 2, 0, BK_BOTTOM, 0xFF000000, 0, 0)); + bk->addIndices(48, + 0, 1, 3, 1, 2, 3, 2, 3, 4, 2, 4, 5, + 4, 5, 7, 5, 6, 7, 6, 7, 8, 6, 8, 9, + 0, 1, 8, 1, 8, 9, 2, 5, 6, 2, 6, 9, + 2, 9, 1, 3, 4, 7, 3, 7, 8, 3, 8, 0); } diff --git a/visualization/qmpvirtualpiano3d.hpp b/visualization/qmpvirtualpiano3d.hpp index cecd992..d00212a 100644 --- a/visualization/qmpvirtualpiano3d.hpp +++ b/visualization/qmpvirtualpiano3d.hpp @@ -16,15 +16,15 @@ #define BK_DBOTTOM 1. class qmpVirtualPiano3D { - private: - smEntity3D *wkcf,*wkeb,*wkd,*wkg,*wka,*bk; - smEntity3DBuffer *ebuf; - void buildKeys(); - double traveld[128]; - public: - qmpVirtualPiano3D(); - ~qmpVirtualPiano3D(); - void render(smvec3d p); - void setKeyTravelDist(int k,double td); +private: + smEntity3D *wkcf, *wkeb, *wkd, *wkg, *wka, *bk; + smEntity3DBuffer *ebuf; + void buildKeys(); + double traveld[128]; +public: + qmpVirtualPiano3D(); + ~qmpVirtualPiano3D(); + void render(smvec3d p); + void setKeyTravelDist(int k, double td); }; #endif // QMPVIRTUALPIANO3D_H diff --git a/visualization/qmpvisualization.cpp b/visualization/qmpvisualization.cpp index 09f80d6..0f73b8a 100644 --- a/visualization/qmpvisualization.cpp +++ b/visualization/qmpvisualization.cpp @@ -6,1018 +6,1341 @@ #include #include "qmpvisualization.hpp" -int viewdist=100; -int notestretch=100;//length of quarter note -int minnotelength=100; -int noteappearance=1,showpiano=1,stairpiano=1,savevp=1,showlabel=1; -int wwidth=800,wheight=600,wsupersample=1,wmultisample=0,showparticle=1; -int horizontal=1,flat=0,osdpos=0,fontsize=16,showmeasure=1; -int fov=60,vsync=1,tfps=60,usespectrum=0; -DWORD chkrtint=0xFF999999; -const wchar_t* minors=L"abebbbf c g d a e b f#c#g#d#a#"; -const wchar_t* majors=L"CbGbDbAbEbBbF C G D A E B F#C#"; -double fpoffsets[]={1,18,28,50,55,82,98,109,130,137,161,164,191}; -double froffsets[]={0,18,33,50,65,82,98,113,130,145,161,176,191}; -DWORD iccolors[]={0XFFFF0000,0XFFFF8000,0XFFFFBF00,0XFFF0F000, - 0XFFB2EE00,0XFF80FF00,0XFF00FF00,0XFF00EEB2, - 0XFF00EEEE,0XFF333333,0XFF00BFFF,0XFF007FFF, - 0XFF0000FF,0XFF7F00FF,0XFFBF00FF,0XFFFF00BF}; -DWORD accolors[]={0XFFFF9999,0XFFFFCC99,0XFFFFF4D4,0XFFFFFFDD, - 0XFFF0FFC2,0XFFDDFFBB,0XFFBBFFBB,0XFFAAFFEA, - 0XFFBBFFFF,0XFF999999,0XFF99EEFF,0XFF99CCFF, - 0XFF9999FF,0XFFCC99FF,0XFFEE99FF,0XFFFF99EE}; +int viewdist = 100; +int notestretch = 100; //length of quarter note +int minnotelength = 100; +int noteappearance = 1, showpiano = 1, stairpiano = 1, savevp = 1, showlabel = 1; +int wwidth = 800, wheight = 600, wsupersample = 1, wmultisample = 0, showparticle = 1; +int horizontal = 1, flat = 0, osdpos = 0, fontsize = 16, showmeasure = 1; +int fov = 60, vsync = 1, tfps = 60, usespectrum = 0; +DWORD chkrtint = 0xFF999999; +const wchar_t *minors = L"abebbbf c g d a e b f#c#g#d#a#"; +const wchar_t *majors = L"CbGbDbAbEbBbF C G D A E B F#C#"; +double fpoffsets[] = {1, 18, 28, 50, 55, 82, 98, 109, 130, 137, 161, 164, 191}; +double froffsets[] = {0, 18, 33, 50, 65, 82, 98, 113, 130, 145, 161, 176, 191}; +DWORD iccolors[] = {0XFFFF0000, 0XFFFF8000, 0XFFFFBF00, 0XFFF0F000, + 0XFFB2EE00, 0XFF80FF00, 0XFF00FF00, 0XFF00EEB2, + 0XFF00EEEE, 0XFF333333, 0XFF00BFFF, 0XFF007FFF, + 0XFF0000FF, 0XFF7F00FF, 0XFFBF00FF, 0XFFFF00BF + }; +DWORD accolors[] = {0XFFFF9999, 0XFFFFCC99, 0XFFFFF4D4, 0XFFFFFFDD, + 0XFFF0FFC2, 0XFFDDFFBB, 0XFFBBFFBB, 0XFFAAFFEA, + 0XFFBBFFFF, 0XFF999999, 0XFF99EEFF, 0XFF99CCFF, + 0XFF9999FF, 0XFFCC99FF, 0XFFEE99FF, 0XFFFF99EE + }; -std::set sustaininst={16,17,18,19,20,21,22,23, - 40,41,42,43,44,45,48,49, - 50,51,52,53,54,56,57,58, - 59,60,61,62,63,64,65,66, - 67,68,69,70,71,72,73,74, - 75,76,77,78,79,80,81,82, - 83,84,85,86,87,89,90,91, - 92,93,94,95,97,101,109,110,111}; +std::set sustaininst = {16, 17, 18, 19, 20, 21, 22, 23, + 40, 41, 42, 43, 44, 45, 48, 49, + 50, 51, 52, 53, 54, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 89, 90, 91, + 92, 93, 94, 95, 97, 101, 109, 110, 111 + }; -bool cmp(MidiVisualEvent* a,MidiVisualEvent* b) +bool cmp(MidiVisualEvent *a, MidiVisualEvent *b) { - if(a->tcstcs)return true;if(a->tcs>b->tcs)return false; - if(a->tcetce)return true;return false; + if (a->tcs < b->tcs) + return true; + if (a->tcs > b->tcs) + return false; + if (a->tce < b->tce) + return true; + return false; } void qmpVisualization::showThread() { - wwidth=api->getOptionInt("Visualization/wwidth"); - wheight=api->getOptionInt("Visualization/wheight"); - wsupersample=api->getOptionInt("Visualization/supersampling"); - wmultisample=api->getOptionInt("Visualization/multisampling"); - fov=api->getOptionInt("Visualization/fov"); - noteappearance=api->getOptionBool("Visualization/3dnotes"); - showpiano=api->getOptionBool("Visualization/showpiano"); - stairpiano=api->getOptionBool("Visualization/stairpiano"); - showlabel=api->getOptionBool("Visualization/showlabel"); - showparticle=api->getOptionBool("Visualization/showparticle"); - horizontal=api->getOptionBool("Visualization/horizontal"); - flat=api->getOptionBool("Visualization/flat"); - showmeasure=api->getOptionBool("Visualization/showmeasure"); - savevp=api->getOptionBool("Visualization/savevp"); - vsync=api->getOptionBool("Visualization/vsync"); - tfps=api->getOptionInt("Visualization/tfps"); - osdpos=api->getOptionEnumInt("Visualization/osdpos"); - fontsize=api->getOptionInt("Visualization/fontsize"); - viewdist=api->getOptionInt("Visualization/viewdist"); - notestretch=api->getOptionInt("Visualization/notestretch"); - minnotelength=api->getOptionInt("Visualization/minnotelen"); - chkrtint=api->getOptionUint("Visualization/chkrtint"); - usespectrum=api->getOptionBool("Visualization/usespectrum"); - for(int i=0;i<16;++i) - { - accolors[i]=api->getOptionUint("Visualization/chActiveColor"+std::to_string(i)); - iccolors[i]=api->getOptionUint("Visualization/chInactiveColor"+std::to_string(i)); - } - sm=smGetInterface(SMELT_APILEVEL); - sm->smVidMode(wwidth,wheight,true,!hidewindow); - sm->smUpdateFunc(h);sm->smQuitFunc(closeh); - sm->smWinTitle("QMidiPlayer Visualization"); - sm->smSetFPS(vsync?FPS_VSYNC:tfps); - sm->smNoSuspend(true); - sm->smInit();shouldclose=false; - sm->smTextureOpt(TPOT_POT,TFLT_LINEAR); - chequer=sm->smTextureLoad("chequerboard.png");if(!chequer) - chequer=sm->smTextureLoad("/usr/share/qmidiplayer/img/chequerboard.png"); - pianotex=sm->smTextureLoad("kb_128.png");if(!pianotex) - pianotex=sm->smTextureLoad("/usr/share/qmidiplayer/img/kb_128.png"); - particletex=sm->smTextureLoad("particle.png");if(!particletex) - particletex=sm->smTextureLoad("/usr/share/qmidiplayer/img/particle.png"); - bgtex=sm->smTextureLoad(api->getOptionString("Visualization/background").c_str()); - if(rendermode) - fbcont=new DWORD[wwidth*wheight]; - if(showparticle&&!horizontal) - { - smParticleSystemInfo psinfo; - psinfo.acc=smvec3d(0,0,-0.05);psinfo.accvar=smvec3d(0,0,0.005); - psinfo.vel=smvec3d(0,0,0.5);psinfo.velvar=smvec3d(0.1,0.1,0.2); - psinfo.rotv=psinfo.rota=psinfo.rotavar=smvec3d(0,0,0);psinfo.rotvvar=smvec3d(0.04,0.04,0.04); - psinfo.lifespan=1;psinfo.lifespanvar=0.5;psinfo.maxcount=1000;psinfo.emissioncount=5;psinfo.ecvar=2; - psinfo.emissiondelay=0.1;psinfo.edvar=0;psinfo.initsize=0.8;psinfo.initsizevar=0.1; - psinfo.finalsize=0.1;psinfo.finalsizevar=0.05;psinfo.initcolor=0xFFFFFFFF;psinfo.finalcolor=0x00FFFFFF; - psinfo.initcolorvar=psinfo.finalcolorvar=0;psinfo.texture=particletex;psinfo.blend=BLEND_ALPHAADD; - psepg=new smXLinePSGenerator(.6); - for(int i=0;i<16;++i)for(int j=0;j<128;++j) - { - pss[i][j]=new smParticleSystem(); - pss[i][j]->setPSEmissionPosGen(psepg); - psinfo.initcolor=accolors[i];psinfo.finalcolor=SETA(accolors[i],0); - pss[i][j]->setParticleSystemInfo(psinfo); - pss[i][j]->setPos(smvec3d(0.756*((double)j-64)+.48,(stairpiano?(56-i*7.):(64-i*8.)),stairpiano*i*2+0.1)); - } - }else memset(pss,0,sizeof(pss)); - if(showpiano&&!horizontal)for(int i=0;i<16;++i)p3d[i]=new qmpVirtualPiano3D(); - memset(traveld,0,sizeof(traveld)); - nebuf=new smEntity3DBuffer(); - tdscn=sm->smTargetCreate(wwidth*wsupersample,wheight*wsupersample,wmultisample); - tdparticles=sm->smTargetCreate(wwidth*wsupersample,wheight*wsupersample,wmultisample); - if(!api->getOptionString("Visualization/font2").length()||!font.loadTTF(api->getOptionString("Visualization/font2").c_str(),fontsize)) - if(!font.loadTTF("/usr/share/fonts/truetype/freefont/FreeMono.ttf",fontsize)) - if(!font.loadTTF("/usr/share/fonts/gnu-free/FreeMono.otf",fontsize)) - if(!font.loadTTF((std::string(getenv("windir")?getenv("windir"):"")+"/Fonts/cour.ttf").c_str(),fontsize)) - fprintf(stderr,"W: Font load failed.\n"); - if(!api->getOptionString("Visualization/font2").length()||!fonthdpi.loadTTF(api->getOptionString("Visualization/font2").c_str(),180)) - if(!fonthdpi.loadTTF("/usr/share/fonts/truetype/freefont/FreeMono.ttf",180)) - if(!fonthdpi.loadTTF("/usr/share/fonts/gnu-free/FreeMono.otf",180)) - if(!fonthdpi.loadTTF((std::string(getenv("windir")?getenv("windir"):"")+"/Fonts/cour.ttf").c_str(),180)) - fprintf(stderr,"W: Font load failed.\n"); - if(!api->getOptionString("Visualization/font1").length()||!font2.loadTTF(api->getOptionString("Visualization/font1").c_str(),fontsize)) - if(!font2.loadTTF("/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",fontsize)) - if(!font2.loadTTF("/usr/share/fonts/wenquanyi/wqy-microhei/wqy-microhei.ttc",fontsize)) - if(!font2.loadTTF((std::string(getenv("windir")?getenv("windir"):"")+"/Fonts/msyh.ttc").c_str(),fontsize)) - if(!font2.loadTTF((std::string(getenv("windir")?getenv("windir"):"")+"/Fonts/segoeui.ttf").c_str(),fontsize)) - fprintf(stderr,"W: Font load failed.\n"); - if(pos[0]<-1e8) - { - if(horizontal) - { - pos[0]=-20;pos[1]=45;pos[2]=0; - rot[0]=0;rot[1]=90;rot[2]=90; - } - else - { - pos[0]=0;pos[1]=120;pos[2]=70; - rot[0]=0;rot[1]=75;rot[2]=90; - } - } - debug=false; - ctk=api->getCurrentTimeStamp(); - lst=std::chrono::steady_clock::now(); - sm->smMainLoop(); - sm->smFinale(); + wwidth = api->getOptionInt("Visualization/wwidth"); + wheight = api->getOptionInt("Visualization/wheight"); + wsupersample = api->getOptionInt("Visualization/supersampling"); + wmultisample = api->getOptionInt("Visualization/multisampling"); + fov = api->getOptionInt("Visualization/fov"); + noteappearance = api->getOptionBool("Visualization/3dnotes"); + showpiano = api->getOptionBool("Visualization/showpiano"); + stairpiano = api->getOptionBool("Visualization/stairpiano"); + showlabel = api->getOptionBool("Visualization/showlabel"); + showparticle = api->getOptionBool("Visualization/showparticle"); + horizontal = api->getOptionBool("Visualization/horizontal"); + flat = api->getOptionBool("Visualization/flat"); + showmeasure = api->getOptionBool("Visualization/showmeasure"); + savevp = api->getOptionBool("Visualization/savevp"); + vsync = api->getOptionBool("Visualization/vsync"); + tfps = api->getOptionInt("Visualization/tfps"); + osdpos = api->getOptionEnumInt("Visualization/osdpos"); + fontsize = api->getOptionInt("Visualization/fontsize"); + viewdist = api->getOptionInt("Visualization/viewdist"); + notestretch = api->getOptionInt("Visualization/notestretch"); + minnotelength = api->getOptionInt("Visualization/minnotelen"); + chkrtint = api->getOptionUint("Visualization/chkrtint"); + usespectrum = api->getOptionBool("Visualization/usespectrum"); + for (int i = 0; i < 16; ++i) + { + accolors[i] = api->getOptionUint("Visualization/chActiveColor" + std::to_string(i)); + iccolors[i] = api->getOptionUint("Visualization/chInactiveColor" + std::to_string(i)); + } + sm = smGetInterface(SMELT_APILEVEL); + sm->smVidMode(wwidth, wheight, true, !hidewindow); + sm->smUpdateFunc(h); + sm->smQuitFunc(closeh); + sm->smWinTitle("QMidiPlayer Visualization"); + sm->smSetFPS(vsync ? FPS_VSYNC : tfps); + sm->smNoSuspend(true); + sm->smInit(); + shouldclose = false; + sm->smTextureOpt(TPOT_POT, TFLT_LINEAR); + chequer = sm->smTextureLoad("chequerboard.png"); + if (!chequer) + chequer = sm->smTextureLoad("/usr/share/qmidiplayer/img/chequerboard.png"); + pianotex = sm->smTextureLoad("kb_128.png"); + if (!pianotex) + pianotex = sm->smTextureLoad("/usr/share/qmidiplayer/img/kb_128.png"); + particletex = sm->smTextureLoad("particle.png"); + if (!particletex) + particletex = sm->smTextureLoad("/usr/share/qmidiplayer/img/particle.png"); + bgtex = sm->smTextureLoad(api->getOptionString("Visualization/background").c_str()); + if (rendermode) + fbcont = new DWORD[wwidth * wheight]; + if (showparticle && !horizontal) + { + smParticleSystemInfo psinfo; + psinfo.acc = smvec3d(0, 0, -0.05); + psinfo.accvar = smvec3d(0, 0, 0.005); + psinfo.vel = smvec3d(0, 0, 0.5); + psinfo.velvar = smvec3d(0.1, 0.1, 0.2); + psinfo.rotv = psinfo.rota = psinfo.rotavar = smvec3d(0, 0, 0); + psinfo.rotvvar = smvec3d(0.04, 0.04, 0.04); + psinfo.lifespan = 1; + psinfo.lifespanvar = 0.5; + psinfo.maxcount = 1000; + psinfo.emissioncount = 5; + psinfo.ecvar = 2; + psinfo.emissiondelay = 0.1; + psinfo.edvar = 0; + psinfo.initsize = 0.8; + psinfo.initsizevar = 0.1; + psinfo.finalsize = 0.1; + psinfo.finalsizevar = 0.05; + psinfo.initcolor = 0xFFFFFFFF; + psinfo.finalcolor = 0x00FFFFFF; + psinfo.initcolorvar = psinfo.finalcolorvar = 0; + psinfo.texture = particletex; + psinfo.blend = BLEND_ALPHAADD; + psepg = new smXLinePSGenerator(.6); + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 128; ++j) + { + pss[i][j] = new smParticleSystem(); + pss[i][j]->setPSEmissionPosGen(psepg); + psinfo.initcolor = accolors[i]; + psinfo.finalcolor = SETA(accolors[i], 0); + pss[i][j]->setParticleSystemInfo(psinfo); + pss[i][j]->setPos(smvec3d(0.756 * ((double)j - 64) + .48, (stairpiano ? (56 - i * 7.) : (64 - i * 8.)), stairpiano * i * 2 + 0.1)); + } + } + else memset(pss, 0, sizeof(pss)); + if (showpiano && !horizontal) + for (int i = 0; i < 16; ++i) + p3d[i] = new qmpVirtualPiano3D(); + memset(traveld, 0, sizeof(traveld)); + nebuf = new smEntity3DBuffer(); + tdscn = sm->smTargetCreate(wwidth * wsupersample, wheight * wsupersample, wmultisample); + tdparticles = sm->smTargetCreate(wwidth * wsupersample, wheight * wsupersample, wmultisample); + if (!api->getOptionString("Visualization/font2").length() || !font.loadTTF(api->getOptionString("Visualization/font2").c_str(), fontsize)) + if (!font.loadTTF("/usr/share/fonts/truetype/freefont/FreeMono.ttf", fontsize)) + if (!font.loadTTF("/usr/share/fonts/gnu-free/FreeMono.otf", fontsize)) + if (!font.loadTTF((std::string(getenv("windir") ? getenv("windir") : "") + "/Fonts/cour.ttf").c_str(), fontsize)) + fprintf(stderr, "W: Font load failed.\n"); + if (!api->getOptionString("Visualization/font2").length() || !fonthdpi.loadTTF(api->getOptionString("Visualization/font2").c_str(), 180)) + if (!fonthdpi.loadTTF("/usr/share/fonts/truetype/freefont/FreeMono.ttf", 180)) + if (!fonthdpi.loadTTF("/usr/share/fonts/gnu-free/FreeMono.otf", 180)) + if (!fonthdpi.loadTTF((std::string(getenv("windir") ? getenv("windir") : "") + "/Fonts/cour.ttf").c_str(), 180)) + fprintf(stderr, "W: Font load failed.\n"); + if (!api->getOptionString("Visualization/font1").length() || !font2.loadTTF(api->getOptionString("Visualization/font1").c_str(), fontsize)) + if (!font2.loadTTF("/usr/share/fonts/truetype/wqy/wqy-microhei.ttc", fontsize)) + if (!font2.loadTTF("/usr/share/fonts/wenquanyi/wqy-microhei/wqy-microhei.ttc", fontsize)) + if (!font2.loadTTF((std::string(getenv("windir") ? getenv("windir") : "") + "/Fonts/msyh.ttc").c_str(), fontsize)) + if (!font2.loadTTF((std::string(getenv("windir") ? getenv("windir") : "") + "/Fonts/segoeui.ttf").c_str(), fontsize)) + fprintf(stderr, "W: Font load failed.\n"); + if (pos[0] < -1e8) + { + if (horizontal) + { + pos[0] = -20; + pos[1] = 45; + pos[2] = 0; + rot[0] = 0; + rot[1] = 90; + rot[2] = 90; + } + else + { + pos[0] = 0; + pos[1] = 120; + pos[2] = 70; + rot[0] = 0; + rot[1] = 75; + rot[2] = 90; + } + } + debug = false; + ctk = api->getCurrentTimeStamp(); + lst = std::chrono::steady_clock::now(); + sm->smMainLoop(); + sm->smFinale(); } void qmpVisualization::show() { - rendererTh=new std::thread(&qmpVisualization::showThread,this); + rendererTh = new std::thread(&qmpVisualization::showThread, this); } void qmpVisualization::close() { - shouldclose=true; - if(rendererTh) - { - rendererTh->join(); - delete rendererTh; - rendererTh=nullptr; - }else return; + shouldclose = true; + if (rendererTh) + { + rendererTh->join(); + delete rendererTh; + rendererTh = nullptr; + } + else return; - if(showpiano&&!horizontal)for(int i=0;i<16;++i)delete p3d[i]; - if(showparticle&&!horizontal)for(int i=0;i>16;++i)for(int j=0;j<128;++j){delete pss[i][j];pss[i][j]=0;} - delete nebuf; - if(savevp) - { - api->setOptionDouble("Visualization/px",pos[0]); - api->setOptionDouble("Visualization/py",pos[1]); - api->setOptionDouble("Visualization/pz",pos[2]); - api->setOptionDouble("Visualization/rx",rot[0]); - api->setOptionDouble("Visualization/ry",rot[1]); - api->setOptionDouble("Visualization/rz",rot[2]); - } - if(rendermode) - delete[] fbcont; - font.releaseTTF(); - font2.releaseTTF(); - fonthdpi.releaseTTF(); - sm->smTextureFree(chequer); - sm->smTextureFree(pianotex); - sm->smTextureFree(particletex); - if(bgtex)sm->smTextureFree(bgtex); - sm->smTargetFree(tdscn); - sm->smTargetFree(tdparticles); - sm->smRelease(); + if (showpiano && !horizontal) + for (int i = 0; i < 16; ++i) + delete p3d[i]; + if (showparticle && !horizontal) + for (int i = 0; i > 16; ++i) + for (int j = 0; j < 128; ++j) + { + delete pss[i][j]; + pss[i][j] = 0; + } + delete nebuf; + if (savevp) + { + api->setOptionDouble("Visualization/px", pos[0]); + api->setOptionDouble("Visualization/py", pos[1]); + api->setOptionDouble("Visualization/pz", pos[2]); + api->setOptionDouble("Visualization/rx", rot[0]); + api->setOptionDouble("Visualization/ry", rot[1]); + api->setOptionDouble("Visualization/rz", rot[2]); + } + if (rendermode) + delete[] fbcont; + font.releaseTTF(); + font2.releaseTTF(); + fonthdpi.releaseTTF(); + sm->smTextureFree(chequer); + sm->smTextureFree(pianotex); + sm->smTextureFree(particletex); + if (bgtex) + sm->smTextureFree(bgtex); + sm->smTargetFree(tdscn); + sm->smTargetFree(tdparticles); + sm->smRelease(); } void qmpVisualization::reset() { - for(unsigned i=0;istopPS(); - while(!pendingt[i][j].empty())pendingt[i][j].pop(); - while(!pendingv[i][j].empty())pendingv[i][j].pop(); - } + for (unsigned i = 0; i < pool.size(); ++i) + delete pool[i]; + pool.clear(); + elb = ctk = lstk = cfr = 0; + tspool.clear(); + cts = 0x0402; + cks = 0; + ctp = 500000; + for (int i = 0; i < 16; ++i) + { + cpbr[i] = 2; + cpw[i] = 8192; + } + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 128; ++j) + { + if (showparticle && !horizontal && pss[i][j]) + pss[i][j]->stopPS(); + while (!pendingt[i][j].empty()) + pendingt[i][j].pop(); + while (!pendingv[i][j].empty()) + pendingv[i][j].pop(); + } } -void qmpVisualization::switchToRenderMode(void(*frameCallback)(void*,size_t,uint32_t,uint32_t),bool _hidewindow) +void qmpVisualization::switchToRenderMode(void(*frameCallback)(void *, size_t, uint32_t, uint32_t), bool _hidewindow) { - rendermode=true; - framecb=frameCallback; - hidewindow=_hidewindow; + rendermode = true; + framecb = frameCallback; + hidewindow = _hidewindow; +} +void qmpVisualization::start() +{ + playing = true; +} +void qmpVisualization::stop() +{ + playing = false; +} +void qmpVisualization::pause() +{ + playing = !playing; } -void qmpVisualization::start(){playing=true;} -void qmpVisualization::stop(){playing=false;} -void qmpVisualization::pause(){playing=!playing;} void qmpVisualization::updateVisualization3D() { - smQuad q; - if(!rendermode) - { - if(sm->smGetKeyState(SMK_D))pos[0]+=cos(smMath::deg2rad(rot[2]-90)),pos[1]+=sin(smMath::deg2rad(rot[2]-90)); - if(sm->smGetKeyState(SMK_A))pos[0]-=cos(smMath::deg2rad(rot[2]-90)),pos[1]-=sin(smMath::deg2rad(rot[2]-90)); - if(sm->smGetKeyState(SMK_S))pos[0]+=cos(smMath::deg2rad(rot[2])),pos[1]+=sin(smMath::deg2rad(rot[2])); - if(sm->smGetKeyState(SMK_W))pos[0]-=cos(smMath::deg2rad(rot[2])),pos[1]-=sin(smMath::deg2rad(rot[2])); - if(sm->smGetKeyState(SMK_Q))pos[2]+=1; - if(sm->smGetKeyState(SMK_E))pos[2]-=1; - if(sm->smGetKeyState(SMK_R)) - { - if(horizontal) - { - pos[0]=-20;pos[1]=45;pos[2]=0; - rot[0]=0;rot[1]=90;rot[2]=90; - } - else - { - pos[0]=0;pos[1]=120;pos[2]=70; - rot[0]=0;rot[1]=75;rot[2]=90; - } - } - if(sm->smGetKeyState(SMK_LBUTTON)==SMKST_HIT) - sm->smSetMouseGrab(true),sm->smGetMouse2f(&lastx,&lasty); - if(sm->smGetKeyState(SMK_LBUTTON)==SMKST_KEEP) - { - float x,y; - sm->smGetMouse2f(&x,&y); - rot[1]-=(y-lasty)*0.01; - rot[2]+=(x-lastx)*0.01; - while(rot[1]>360)rot[1]-=360; - while(rot[1]<0)rot[1]+=360; - while(rot[2]>360)rot[2]-=360; - while(rot[2]<0)rot[2]+=360; - } - if(sm->smGetKeyState(SMK_LBUTTON)==SMKST_RELEASE) - { - sm->smSetMouseGrab(false); - sm->smSetMouse2f(wwidth/2,wheight/2); - } - if(sm->smGetKeyState(SMK_I))rot[1]+=1; - if(sm->smGetKeyState(SMK_K))rot[1]-=1; - if(sm->smGetKeyState(SMK_L))rot[0]+=1; - if(sm->smGetKeyState(SMK_J))rot[0]-=1; - if(sm->smGetKeyState(SMK_U))rot[2]+=1; - if(sm->smGetKeyState(SMK_O))rot[2]-=1; - } - for(int i=0;i<4;++i) - {q.v[i].col=chkrtint;q.v[i].z=(showpiano&&!horizontal)?-5:0;} - q.tex=chequer;q.blend=BLEND_ALPHABLEND; - q.v[0].x=q.v[3].x=-120;q.v[1].x=q.v[2].x=120; - q.v[0].y=q.v[1].y=-120;q.v[2].y=q.v[3].y=120; - if(horizontal) - { - for(int i=0;i<4;++i)q.v[i].x=-20; - q.v[0].y=q.v[3].y=-120;q.v[1].y=q.v[2].y=120; - q.v[0].z=q.v[1].z=-120;q.v[2].z=q.v[3].z=120; - } - q.v[0].tx=q.v[3].tx=0;q.v[1].tx=q.v[2].tx=30; - q.v[0].ty=q.v[1].ty=0;q.v[2].ty=q.v[3].ty=30; - sm->smRenderBegin3D(fov,true,tdscn); - sm->sm3DCamera6f2v(pos,rot); - sm->smClrscr(0,1,1); - sm->smRenderQuad(&q); - double lpt=(double)notestretch/api->getDivision()/10.*(horizontal?0.25:1); - memcpy(lastnotestatus,notestatus,sizeof(notestatus)); - memset(notestatus,0,sizeof(notestatus)); - for(uint32_t i=elb;itcs-ctk)*lpt>viewdist*2)break; - if(fabs((double)pool[i]->tcs-ctk)*lpttce-ctk)*lptch==999){ - smvec3d a(0.63*(-64)+.1-10,(stairpiano?(56-0*7.):(64-0*8.))+10,((double)pool[i]->tcs-ctk)*lpt-minnotelength*.005); - smvec3d b(0.63*64+.7+10,(stairpiano?(56-15*7.):(64-15*8.))+.4-10,((double)pool[i]->tcs-ctk)*lpt+minnotelength*.005); - if(horizontal){ - a=smvec3d(((double)pool[i]->tcs-ctk)*lpt-20-minnotelength*.001,(16- 0*2.)+2.4,0.63*(-64)+.1); - b=smvec3d(((double)pool[i]->tcs-ctk)*lpt-20+minnotelength*.001,(16-15*2.)+0.4,0.63*64+.7); - } - smMatrix I;I.loadIdentity(); - smEntity3D c=smEntity3D::cube(a,b,0xFF000000,horizontal?51:60); - if(stairpiano&&showpiano&&!horizontal) - { - std::vector il={2,3,6,7}; - for(size_t ti:il) - { - smVertex t=c.vertex(ti); - t.z+=30; - c.setVertex(ti,t); - } - } - if(showmeasure) - nebuf->addTransformedEntity(&c,I,smvec3d(0,0,0)); - continue; - } - if(pool[i]->ch>=990)continue; - if(api->getChannelMask(pool[i]->ch))continue; - smvec3d a(0.63*((double)pool[i]->key-64)+.1,(stairpiano?(56-pool[i]->ch*7.):(64-pool[i]->ch*8.)),((double)pool[i]->tce-ctk)*lpt+(stairpiano&&showpiano&&!horizontal)*pool[i]->ch*2.); - smvec3d b(0.63*((double)pool[i]->key-64)+.7,(stairpiano?(56-pool[i]->ch*7.):(64-pool[i]->ch*8.))+.4,((double)pool[i]->tcs-ctk)*lpt+(stairpiano&&showpiano&&!horizontal)*pool[i]->ch*2.); - bool isnoteon=pool[i]->tcs<=ctk&&pool[i]->tce>=ctk; - double pb=((int)cpw[pool[i]->ch]-8192)/8192.*cpbr[pool[i]->ch]; - if(isnoteon) - { - a.x=0.63*((double)pool[i]->key-64+pb)+.1; - b.x=0.63*((double)pool[i]->key-64+pb)+.7; - } - notestatus[pool[i]->ch][pool[i]->key]|=isnoteon;a.x*=1.2;b.x*=1.2; - if(horizontal) - { - a=smvec3d(((double)pool[i]->tcs-ctk)*lpt-20,(16-pool[i]->ch*2.),0.63*((double)pool[i]->key-64)+.1); - b=smvec3d(((double)pool[i]->tce-ctk)*lpt-20,(16-pool[i]->ch*2.)+.4,0.63*((double)pool[i]->key-64)+.7); - if(isnoteon) - { - a.z=0.63*((double)pool[i]->key-64+pb)+.1; - b.z=0.63*((double)pool[i]->key-64+pb)+.7; - } - } - if(showparticle&&!horizontal) - { - if(notestatus[pool[i]->ch][pool[i]->key]&&!lastnotestatus[pool[i]->ch][pool[i]->key]) - { - pss[pool[i]->ch][pool[i]->key]->startPS(); - pss[pool[i]->ch][pool[i]->key]->setPos(smvec3d(0.756*((double)pool[i]->key-64)+.48,(stairpiano?(56-pool[i]->ch*7.):(64-pool[i]->ch*8.)),stairpiano*pool[i]->ch*2+0.1)); - } - else pss[pool[i]->ch][pool[i]->key]->stopPS(); - } - if(((double)pool[i]->tce-pool[i]->tcs)*lpttcs-ctk)*lpt-minnotelength/400.-20; - else - a.z=((double)pool[i]->tcs-ctk)*lpt-minnotelength/100.+stairpiano*pool[i]->ch*2; - } - if(usespectrum) - { - if(notestatus[pool[i]->ch][pool[i]->key]&&!lastnotestatus[pool[i]->ch][pool[i]->key]) - spectra[pool[i]->ch][pool[i]->key]=pool[i]->vel*(api->getChannelCC(pool[i]->ch,7)/127.); - } - else - { - smColor col=smColor::fromHWColor(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch]); - drawCube(a,b,col.lighter(37+pool[i]->vel/2).toHWColor(),0); - } - } - } - if(usespectrum&&playing) - for(int i=0;i<16;++i)for(int j=0;j<128;++j) - { - if(sustaininst.find(api->getChannelPreset(i))!=sustaininst.end()) - { - if(!notestatus[i][j]&&spectra[i][j]) - spectra[i][j]=.95*spectra[i][j]; - }else if(spectra[i][j])spectra[i][j]=.95*spectra[i][j]; - if(spectrar[i][j]smGetTime()*32))+(stairpiano&&showpiano&&!horizontal)*i*2.); - smvec3d b(0.756*((double)j-64+pb)+.84, - (stairpiano?(56-i*7.):(64-i*8.))+.4, - (stairpiano&&showpiano&&!horizontal)*i*2.); - drawCube(a,b,SETA(iccolors[i],204),0); - } - } - nebuf->drawBatch(); - if(showpiano&&!horizontal) - for(int i=0;i<16;++i) - { - for(int j=0;j<128;++j) - { - if(notestatus[i][j]) - if(traveld[i][j]<10)traveld[i][j]+=2;else traveld[i][j]=10; - else - if(traveld[i][j]>0)traveld[i][j]-=2;else traveld[i][j]=0; - p3d[i]->setKeyTravelDist(j,traveld[i][j]/10.); - } - double pb=((int)cpw[i]-8192)/8192.*cpbr[i]; - p3d[i]->render(smvec3d(0.756*pb,stairpiano?55-i*7:62-i*8,stairpiano*i*2)); - } - for(int i=0;i<16;++i) - if(showlabel) - { - std::string s=api->getChannelPresetString(i); - wchar_t ws[1024];mbstowcs(ws,s.c_str(),1024); - fonthdpi.updateString(ws); - fonthdpi.render(-49,stairpiano?56-i*7:63-i*8,stairpiano*i*2+0.1,0xFFFFFFFF,ALIGN_RIGHT,.008,0.01); - fonthdpi.render(-49.05,stairpiano?56.05-i*7:63.05-i*8,stairpiano*i*2+0.2,0xFF000000,ALIGN_RIGHT,.008,0.01); - } - while(pool.size()&&elbtce)*lpt>viewdist*2)++elb; - sm->smRenderEnd(); - if(showparticle&&!horizontal) - { - sm->smRenderBegin3D(fov,false,tdparticles); - sm->sm3DCamera6f2v(pos,rot); - sm->smClrscr(0,1,1); - for(int i=0;i<16;++i)for(int j=0;j<128;++j) - { - pss[i][j]->setPSLookAt(smvec3d(pos[0],pos[1],pos[2])); - pss[i][j]->updatePS();pss[i][j]->renderPS(); - } - sm->smRenderEnd(); - } + smQuad q; + if (!rendermode) + { + if (sm->smGetKeyState(SMK_D)) + pos[0] += cos(smMath::deg2rad(rot[2] - 90)), pos[1] += sin(smMath::deg2rad(rot[2] - 90)); + if (sm->smGetKeyState(SMK_A)) + pos[0] -= cos(smMath::deg2rad(rot[2] - 90)), pos[1] -= sin(smMath::deg2rad(rot[2] - 90)); + if (sm->smGetKeyState(SMK_S)) + pos[0] += cos(smMath::deg2rad(rot[2])), pos[1] += sin(smMath::deg2rad(rot[2])); + if (sm->smGetKeyState(SMK_W)) + pos[0] -= cos(smMath::deg2rad(rot[2])), pos[1] -= sin(smMath::deg2rad(rot[2])); + if (sm->smGetKeyState(SMK_Q)) + pos[2] += 1; + if (sm->smGetKeyState(SMK_E)) + pos[2] -= 1; + if (sm->smGetKeyState(SMK_R)) + { + if (horizontal) + { + pos[0] = -20; + pos[1] = 45; + pos[2] = 0; + rot[0] = 0; + rot[1] = 90; + rot[2] = 90; + } + else + { + pos[0] = 0; + pos[1] = 120; + pos[2] = 70; + rot[0] = 0; + rot[1] = 75; + rot[2] = 90; + } + } + if (sm->smGetKeyState(SMK_LBUTTON) == SMKST_HIT) + sm->smSetMouseGrab(true), sm->smGetMouse2f(&lastx, &lasty); + if (sm->smGetKeyState(SMK_LBUTTON) == SMKST_KEEP) + { + float x, y; + sm->smGetMouse2f(&x, &y); + rot[1] -= (y - lasty) * 0.01; + rot[2] += (x - lastx) * 0.01; + while (rot[1] > 360) + rot[1] -= 360; + while (rot[1] < 0) + rot[1] += 360; + while (rot[2] > 360) + rot[2] -= 360; + while (rot[2] < 0) + rot[2] += 360; + } + if (sm->smGetKeyState(SMK_LBUTTON) == SMKST_RELEASE) + { + sm->smSetMouseGrab(false); + sm->smSetMouse2f(wwidth / 2, wheight / 2); + } + if (sm->smGetKeyState(SMK_I)) + rot[1] += 1; + if (sm->smGetKeyState(SMK_K)) + rot[1] -= 1; + if (sm->smGetKeyState(SMK_L)) + rot[0] += 1; + if (sm->smGetKeyState(SMK_J)) + rot[0] -= 1; + if (sm->smGetKeyState(SMK_U)) + rot[2] += 1; + if (sm->smGetKeyState(SMK_O)) + rot[2] -= 1; + } + for (int i = 0; i < 4; ++i) + { + q.v[i].col = chkrtint; + q.v[i].z = (showpiano && !horizontal) ? -5 : 0; + } + q.tex = chequer; + q.blend = BLEND_ALPHABLEND; + q.v[0].x = q.v[3].x = -120; + q.v[1].x = q.v[2].x = 120; + q.v[0].y = q.v[1].y = -120; + q.v[2].y = q.v[3].y = 120; + if (horizontal) + { + for (int i = 0; i < 4; ++i) + q.v[i].x = -20; + q.v[0].y = q.v[3].y = -120; + q.v[1].y = q.v[2].y = 120; + q.v[0].z = q.v[1].z = -120; + q.v[2].z = q.v[3].z = 120; + } + q.v[0].tx = q.v[3].tx = 0; + q.v[1].tx = q.v[2].tx = 30; + q.v[0].ty = q.v[1].ty = 0; + q.v[2].ty = q.v[3].ty = 30; + sm->smRenderBegin3D(fov, true, tdscn); + sm->sm3DCamera6f2v(pos, rot); + sm->smClrscr(0, 1, 1); + sm->smRenderQuad(&q); + double lpt = (double)notestretch / api->getDivision() / 10.*(horizontal ? 0.25 : 1); + memcpy(lastnotestatus, notestatus, sizeof(notestatus)); + memset(notestatus, 0, sizeof(notestatus)); + for (uint32_t i = elb; i < pool.size(); ++i) + { + if (((double)pool[i]->tcs - ctk)*lpt > viewdist * 2) + break; + if (fabs((double)pool[i]->tcs - ctk)*lpt < viewdist * 2 || fabs((double)pool[i]->tce - ctk)*lpt < viewdist * 2) + { + if (pool[i]->ch == 999) + { + smvec3d a(0.63 * (-64) + .1 - 10, (stairpiano ? (56 - 0 * 7.) : (64 - 0 * 8.)) + 10, ((double)pool[i]->tcs - ctk)*lpt - minnotelength * .005); + smvec3d b(0.63 * 64 + .7 + 10, (stairpiano ? (56 - 15 * 7.) : (64 - 15 * 8.)) + .4 - 10, ((double)pool[i]->tcs - ctk)*lpt + minnotelength * .005); + if (horizontal) + { + a = smvec3d(((double)pool[i]->tcs - ctk) * lpt - 20 - minnotelength * .001, (16 - 0 * 2.) + 2.4, 0.63 * (-64) + .1); + b = smvec3d(((double)pool[i]->tcs - ctk) * lpt - 20 + minnotelength * .001, (16 - 15 * 2.) + 0.4, 0.63 * 64 + .7); + } + smMatrix I; + I.loadIdentity(); + smEntity3D c = smEntity3D::cube(a, b, 0xFF000000, horizontal ? 51 : 60); + if (stairpiano && showpiano && !horizontal) + { + std::vector il = {2, 3, 6, 7}; + for (size_t ti : il) + { + smVertex t = c.vertex(ti); + t.z += 30; + c.setVertex(ti, t); + } + } + if (showmeasure) + nebuf->addTransformedEntity(&c, I, smvec3d(0, 0, 0)); + continue; + } + if (pool[i]->ch >= 990) + continue; + if (api->getChannelMask(pool[i]->ch)) + continue; + smvec3d a(0.63 * ((double)pool[i]->key - 64) + .1, (stairpiano ? (56 - pool[i]->ch * 7.) : (64 - pool[i]->ch * 8.)), ((double)pool[i]->tce - ctk)*lpt + (stairpiano && showpiano && !horizontal)*pool[i]->ch * 2.); + smvec3d b(0.63 * ((double)pool[i]->key - 64) + .7, (stairpiano ? (56 - pool[i]->ch * 7.) : (64 - pool[i]->ch * 8.)) + .4, ((double)pool[i]->tcs - ctk)*lpt + (stairpiano && showpiano && !horizontal)*pool[i]->ch * 2.); + bool isnoteon = pool[i]->tcs <= ctk && pool[i]->tce >= ctk; + double pb = ((int)cpw[pool[i]->ch] - 8192) / 8192.*cpbr[pool[i]->ch]; + if (isnoteon) + { + a.x = 0.63 * ((double)pool[i]->key - 64 + pb) + .1; + b.x = 0.63 * ((double)pool[i]->key - 64 + pb) + .7; + } + notestatus[pool[i]->ch][pool[i]->key] |= isnoteon; + a.x *= 1.2; + b.x *= 1.2; + if (horizontal) + { + a = smvec3d(((double)pool[i]->tcs - ctk) * lpt - 20, (16 - pool[i]->ch * 2.), 0.63 * ((double)pool[i]->key - 64) + .1); + b = smvec3d(((double)pool[i]->tce - ctk) * lpt - 20, (16 - pool[i]->ch * 2.) + .4, 0.63 * ((double)pool[i]->key - 64) + .7); + if (isnoteon) + { + a.z = 0.63 * ((double)pool[i]->key - 64 + pb) + .1; + b.z = 0.63 * ((double)pool[i]->key - 64 + pb) + .7; + } + } + if (showparticle && !horizontal) + { + if (notestatus[pool[i]->ch][pool[i]->key] && !lastnotestatus[pool[i]->ch][pool[i]->key]) + { + pss[pool[i]->ch][pool[i]->key]->startPS(); + pss[pool[i]->ch][pool[i]->key]->setPos(smvec3d(0.756 * ((double)pool[i]->key - 64) + .48, (stairpiano ? (56 - pool[i]->ch * 7.) : (64 - pool[i]->ch * 8.)), stairpiano * pool[i]->ch * 2 + 0.1)); + } + else pss[pool[i]->ch][pool[i]->key]->stopPS(); + } + if (((double)pool[i]->tce - pool[i]->tcs)*lpt < minnotelength * (horizontal ? 0.0025 : 0.01)) + { + if (horizontal) + a.x = ((double)pool[i]->tcs - ctk) * lpt - minnotelength / 400. - 20; + else + a.z = ((double)pool[i]->tcs - ctk) * lpt - minnotelength / 100. + stairpiano * pool[i]->ch * 2; + } + if (usespectrum) + { + if (notestatus[pool[i]->ch][pool[i]->key] && !lastnotestatus[pool[i]->ch][pool[i]->key]) + spectra[pool[i]->ch][pool[i]->key] = pool[i]->vel * (api->getChannelCC(pool[i]->ch, 7) / 127.); + } + else + { + smColor col = smColor::fromHWColor(isnoteon ? accolors[pool[i]->ch] : iccolors[pool[i]->ch]); + drawCube(a, b, col.lighter(37 + pool[i]->vel / 2).toHWColor(), 0); + } + } + } + if (usespectrum && playing) + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 128; ++j) + { + if (sustaininst.find(api->getChannelPreset(i)) != sustaininst.end()) + { + if (!notestatus[i][j] && spectra[i][j]) + spectra[i][j] = .95 * spectra[i][j]; + } + else if (spectra[i][j]) + spectra[i][j] = .95 * spectra[i][j]; + if (spectrar[i][j] < spectra[i][j] * 0.9) + spectrar[i][j] += spectra[i][j] * 0.2; + else spectrar[i][j] = spectra[i][j]; + if (spectrar[i][j]) + { + double pb = ((int)cpw[i] - 8192) / 8192.*cpbr[i]; + smvec3d a(0.756 * ((double)j - 64 + pb) + .12, + (stairpiano ? (56 - i * 7.) : (64 - i * 8.)), + spectrar[i][j] * 1.2 * (1 + 0.02 * sin(sm->smGetTime() * 32)) + (stairpiano && showpiano && !horizontal)*i * 2.); + smvec3d b(0.756 * ((double)j - 64 + pb) + .84, + (stairpiano ? (56 - i * 7.) : (64 - i * 8.)) + .4, + (stairpiano && showpiano && !horizontal)*i * 2.); + drawCube(a, b, SETA(iccolors[i], 204), 0); + } + } + nebuf->drawBatch(); + if (showpiano && !horizontal) + for (int i = 0; i < 16; ++i) + { + for (int j = 0; j < 128; ++j) + { + if (notestatus[i][j]) + if (traveld[i][j] < 10) + traveld[i][j] += 2; + else traveld[i][j] = 10; + else if (traveld[i][j] > 0) + traveld[i][j] -= 2; + else traveld[i][j] = 0; + p3d[i]->setKeyTravelDist(j, traveld[i][j] / 10.); + } + double pb = ((int)cpw[i] - 8192) / 8192.*cpbr[i]; + p3d[i]->render(smvec3d(0.756 * pb, stairpiano ? 55 - i * 7 : 62 - i * 8, stairpiano * i * 2)); + } + for (int i = 0; i < 16; ++i) + if (showlabel) + { + std::string s = api->getChannelPresetString(i); + wchar_t ws[1024]; + mbstowcs(ws, s.c_str(), 1024); + fonthdpi.updateString(ws); + fonthdpi.render(-49, stairpiano ? 56 - i * 7 : 63 - i * 8, stairpiano * i * 2 + 0.1, 0xFFFFFFFF, ALIGN_RIGHT, .008, 0.01); + fonthdpi.render(-49.05, stairpiano ? 56.05 - i * 7 : 63.05 - i * 8, stairpiano * i * 2 + 0.2, 0xFF000000, ALIGN_RIGHT, .008, 0.01); + } + while (pool.size() && elb < pool.size() && ((double)ctk - pool[elb]->tce)*lpt > viewdist * 2)++elb; + sm->smRenderEnd(); + if (showparticle && !horizontal) + { + sm->smRenderBegin3D(fov, false, tdparticles); + sm->sm3DCamera6f2v(pos, rot); + sm->smClrscr(0, 1, 1); + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 128; ++j) + { + pss[i][j]->setPSLookAt(smvec3d(pos[0], pos[1], pos[2])); + pss[i][j]->updatePS(); + pss[i][j]->renderPS(); + } + sm->smRenderEnd(); + } } void qmpVisualization::updateVisualization2D() { - double lpt=-(double)notestretch/api->getDivision()/2.; - memset(notestatus,0,sizeof(notestatus)); - double notew=wwidth/128,nh=showpiano?wwidth/2048.*172.:0; - if(horizontal){notew=wheight/128;nh=showpiano?wheight/2048.*172.:0;lpt=-lpt;} - smQuad nq;nq.blend=BLEND_ALPHABLEND;nq.tex=0; - for(int i=0;i<4;++i)nq.v[i].z=0,nq.v[i].tx=nq.v[i].ty=0; - for(uint32_t i=elb;itcs-ctk)*lpt+wheight-nh<0; - bool lowerbound=fabs((double)pool[i]->tce-ctk)*lpt+wheight-nhtcs-ctk)*lpt+nh>wwidth; - lowerbound=fabs((double)pool[i]->tce-ctk)*lpt+nh>0; - } - if(upperbound)break; - if(!upperbound||lowerbound) - { - if(pool[i]->ch==999){ - smvec2d a(0,((double)pool[i]->tcs-ctk)*lpt+wheight-nh-minnotelength*0.02); - smvec2d b(wwidth,((double)pool[i]->tcs-ctk)*lpt+wheight-nh); - if(horizontal) - { - a=smvec2d(((double)pool[i]->tcs-ctk)*lpt+nh-minnotelength*0.02,0); - b=smvec2d(((double)pool[i]->tcs-ctk)*lpt+nh,wheight); - } - nq.v[0].x=nq.v[3].x=a.x;nq.v[0].y=nq.v[1].y=a.y; - nq.v[1].x=nq.v[2].x=b.x;nq.v[2].y=nq.v[3].y=b.y; - for(int j=0;j<4;++j)nq.v[j].col=0xC0000000; - if(showmeasure)sm->smRenderQuad(&nq); - continue; - } - if(pool[i]->ch>=990)continue; - if(api->getChannelMask(pool[i]->ch))continue; - smvec2d a((froffsets[12]*(pool[i]->key/12)+froffsets[pool[i]->key%12])*wwidth/2048.,((double)pool[i]->tce-ctk)*lpt+wheight-nh); - smvec2d b(a.x+notew*0.9,((double)pool[i]->tcs-ctk)*lpt+wheight-nh); - if(horizontal) - { - a=smvec2d(((double)pool[i]->tce-ctk)*lpt+nh,(froffsets[12]*(pool[i]->key/12)+froffsets[pool[i]->key%12])*wheight/2048.); - b=smvec2d(((double)pool[i]->tcs-ctk)*lpt+nh,a.y+notew*0.9); - } - bool isnoteon=pool[i]->tcs<=ctk&&pool[i]->tce>=ctk; - if(isnoteon) - { - double pb=((int)cpw[pool[i]->ch]-8192)/8192.*cpbr[pool[i]->ch]; - uint32_t newkey=pool[i]->key+(int)floor(pb); - double fpb=pb-floor(pb); - if(horizontal) - { - a.y=(froffsets[12]*(newkey/12)+froffsets[newkey%12])*wheight/2048.+notew*fpb; - b.y=a.y+notew*0.9; - } - else - { - a.x=(froffsets[12]*(newkey/12)+froffsets[newkey%12])*wwidth/2048.+notew*fpb; - b.x=a.x+notew*0.9; - } - } - if(horizontal)a.y=wheight-a.y,b.y=wheight-b.y; - notestatus[pool[i]->ch][pool[i]->key]|=isnoteon; - if(horizontal) - { - if(((double)pool[i]->tce-pool[i]->tcs)*lpttcs-ctk)*lpt+nh-minnotelength*0.04; - } - else - { - if(((double)pool[i]->tcs-pool[i]->tce)*lpttcs-ctk)*lpt+wheight-nh-minnotelength*0.04; - } - nq.v[0].x=nq.v[3].x=a.x;nq.v[0].y=nq.v[1].y=a.y; - nq.v[1].x=nq.v[2].x=b.x;nq.v[2].y=nq.v[3].y=b.y; - for(int j=0;j<4;++j) - nq.v[j].col=SETA(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch],int(pool[i]->vel*1.6+(isnoteon?52:32))); - if(usespectrum) - { - if(notestatus[pool[i]->ch][pool[i]->key]&&!lastnotestatus[pool[i]->ch][pool[i]->key]) - spectra[pool[i]->ch][pool[i]->key]=pool[i]->vel*(api->getChannelCC(pool[i]->ch,7)/127.); - }else sm->smRenderQuad(&nq); - } - } - if(horizontal) - while(pool.size()&&elbtce-ctk)*lpt+nh<0)++elb; - else - while(pool.size()&&elbtce-ctk)*lpt+wheight-nh>wheight)++elb; - smQuad q; - q.tex=pianotex;q.blend=BLEND_ALPHABLEND; - for(int i=0;i<4;++i)q.v[i].col=0xFFFFFFFF,q.v[i].z=0; - q.v[0].ty=q.v[3].ty=0;q.v[1].ty=q.v[2].ty=172./256.; - q.v[0].tx=q.v[1].tx=0;q.v[2].tx=q.v[3].tx=1.; - q.v[0].x=q.v[1].x=0;q.v[2].x=q.v[3].x=wwidth; - q.v[0].y=q.v[3].y=wheight-nh;q.v[1].y=q.v[2].y=wheight; - if(horizontal) - { - q.v[0].tx=q.v[3].tx=0;q.v[1].tx=q.v[2].tx=1; - q.v[0].ty=q.v[1].ty=0;q.v[2].ty=q.v[3].ty=172./256.; - q.v[0].x=q.v[1].x=nh;q.v[2].x=q.v[3].x=0; - q.v[0].y=q.v[3].y=wheight;q.v[1].y=q.v[2].y=0; - } - sm->smRenderQuad(&q); - for(int i=0,j;i<128;++i) - { - DWORD c=0;for(j=0;j<16;++j)if(notestatus[j][i]){c=SETA(iccolors[j],0xFF);break;} - if(horizontal) - { - q.v[0].y=q.v[1].y=(fpoffsets[12]*(i/12)+fpoffsets[i%12])*wheight/2048.; - q.v[2].y=q.v[3].y=q.v[0].y; - q.v[0].x=q.v[3].x=nh;q.v[1].x=q.v[2].x=0; - } - else - { - q.v[0].x=q.v[1].x=(fpoffsets[12]*(i/12)+fpoffsets[i%12])*wwidth/2048.; - q.v[2].x=q.v[3].x=q.v[0].x; - q.v[0].y=q.v[3].y=wheight-nh;q.v[1].y=q.v[2].y=wheight; - } - if(!c)continue;for(int j=0;j<4;++j)q.v[j].col=c; - switch(i%12) - { - case 1:case 3:case 6:case 8:case 10: - if(horizontal) - { - q.v[1].x=q.v[2].x=nh-115*wheight/2048.; - q.v[2].y+=15.*wheight/2048;q.v[3].y+=15.*wheight/2048; - } - else - { - q.v[1].y=q.v[2].y=wheight-nh+115*wwidth/2048.; - q.v[2].x+=15.*wwidth/2048;q.v[3].x+=15.*wwidth/2048; - } - q.v[0].ty=q.v[1].ty=1.;q.v[2].ty=q.v[3].ty=1.-15/256.; - q.v[0].tx=q.v[3].tx=1344/2048.;q.v[1].tx=q.v[2].tx=1459/2048.; - break; - case 0: - if(horizontal) - {q.v[2].y+=27.*wheight/2048;q.v[3].y+=27.*wheight/2048;} - else - {q.v[2].x+=27.*wwidth/2048;q.v[3].x+=27.*wwidth/2048;} - q.v[0].ty=q.v[1].ty=1.;q.v[2].ty=q.v[3].ty=1.-27/256.; - q.v[0].tx=q.v[3].tx=0/2048.;q.v[1].tx=q.v[2].tx=172/2048.; - break; - case 2: - if(horizontal) - {q.v[2].y+=29.*wheight/2048;q.v[3].y+=29.*wheight/2048;} - else - {q.v[2].x+=29.*wwidth/2048;q.v[3].x+=29.*wwidth/2048;} - q.v[0].ty=q.v[1].ty=1.;q.v[2].ty=q.v[3].ty=1.-29/256.; - q.v[0].tx=q.v[3].tx=192/2048.;q.v[1].tx=q.v[2].tx=364/2048.; - break; - case 4: - if(horizontal) - {q.v[2].y+=28.*wheight/2048;q.v[3].y+=28.*wheight/2048;} - else - {q.v[2].x+=28.*wwidth/2048;q.v[3].x+=28.*wwidth/2048;} - q.v[0].ty=q.v[1].ty=1.;q.v[2].ty=q.v[3].ty=1.-28/256.; - q.v[0].tx=q.v[3].tx=384/2048.;q.v[1].tx=q.v[2].tx=556/2048.; - break; - case 5: - if(horizontal) - {q.v[2].y+=28.*wheight/2048;q.v[3].y+=28.*wheight/2048;} - else - {q.v[2].x+=28.*wwidth/2048;q.v[3].x+=28.*wwidth/2048;} - q.v[0].ty=q.v[1].ty=1.;q.v[2].ty=q.v[3].ty=1.-28/256.; - q.v[0].tx=q.v[3].tx=576/2048.;q.v[1].tx=q.v[2].tx=748/2048.; - break; - case 7: - if(horizontal) - {q.v[2].y+=29.*wheight/2048;q.v[3].y+=29.*wheight/2048;} - else - {q.v[2].x+=29.*wwidth/2048;q.v[3].x+=29.*wwidth/2048;} - q.v[0].ty=q.v[1].ty=1.;q.v[2].ty=q.v[3].ty=1.-29/256.; - q.v[0].tx=q.v[3].tx=768/2048.;q.v[1].tx=q.v[2].tx=940/2048.; - break; - case 9: - if(horizontal) - {q.v[2].y+=28.*wheight/2048;q.v[3].y+=28.*wheight/2048;} - else - {q.v[2].x+=28.*wwidth/2048;q.v[3].x+=28.*wwidth/2048;} - q.v[0].ty=q.v[1].ty=1.;q.v[2].ty=q.v[3].ty=1.-28/256.; - q.v[0].tx=q.v[3].tx=960/2048.;q.v[1].tx=q.v[2].tx=1132/2048.; - break; - case 11: - if(horizontal) - {q.v[2].y+=28.*wheight/2048;q.v[3].y+=28.*wheight/2048;} - else - {q.v[2].x+=28.*wwidth/2048;q.v[3].x+=28.*wwidth/2048;} - q.v[0].ty=q.v[1].ty=1.;q.v[2].ty=q.v[3].ty=1.-28/256.; - q.v[0].tx=q.v[3].tx=1152/2048.;q.v[1].tx=q.v[2].tx=1324/2048.; - break; - } - if(horizontal)for(int j=0;j<4;++j)q.v[j].y=wheight-q.v[j].y; - sm->smRenderQuad(&q); - } - if(usespectrum&&playing) - for(int i=0;i<16;++i)for(int j=0;j<128;++j) - { - if(sustaininst.find(api->getChannelPreset(i))!=sustaininst.end()) - { - if(!notestatus[i][j]&&spectra[i][j]) - spectra[i][j]=.95*spectra[i][j]; - }else if(spectra[i][j])spectra[i][j]=.95*spectra[i][j]; - if(spectrar[i][j]smGetTime()*32))+wheight-nh); - smvec2d b(a.x+notew*0.9,lpt+wheight-nh); - double pb=((int)cpw[i]-8192)/8192.*cpbr[i]; - uint32_t newkey=j+(int)floor(pb); - double fpb=pb-floor(pb); - if(horizontal) - { - a=smvec2d(spectrar[i][j]/128.*(wwidth-nh)*(1+0.02*sin(sm->smGetTime()*32))+nh,(froffsets[12]*(j/12)+froffsets[j%12])*wheight/2048.); - b=smvec2d(nh,a.y+notew*0.9); - a.y=(froffsets[12]*(newkey/12)+froffsets[newkey%12])*wheight/2048.+notew*fpb; - b.y=a.y+notew*0.9; - a.y=wheight-a.y;b.y=wheight-b.y; - } - else - { - a.x=(froffsets[12]*(newkey/12)+froffsets[newkey%12])*wwidth/2048.+notew*fpb; - b.x=a.x+notew*0.9; - } - nq.v[0].x=nq.v[3].x=a.x;nq.v[0].y=nq.v[1].y=a.y; - nq.v[1].x=nq.v[2].x=b.x;nq.v[2].y=nq.v[3].y=b.y;for(int j=0;j<4;++j) - nq.v[j].col=SETA(iccolors[i],204); - sm->smRenderQuad(&nq); - } - } + double lpt = -(double)notestretch / api->getDivision() / 2.; + memset(notestatus, 0, sizeof(notestatus)); + double notew = wwidth / 128, nh = showpiano ? wwidth / 2048.*172. : 0; + if (horizontal) + { + notew = wheight / 128; + nh = showpiano ? wheight / 2048.*172. : 0; + lpt = -lpt; + } + smQuad nq; + nq.blend = BLEND_ALPHABLEND; + nq.tex = 0; + for (int i = 0; i < 4; ++i) + nq.v[i].z = 0, nq.v[i].tx = nq.v[i].ty = 0; + for (uint32_t i = elb; i < pool.size(); ++i) + { + bool upperbound = ((double)pool[i]->tcs - ctk) * lpt + wheight - nh < 0; + bool lowerbound = fabs((double)pool[i]->tce - ctk) * lpt + wheight - nh < wheight; + if (horizontal) + { + upperbound = ((double)pool[i]->tcs - ctk) * lpt + nh > wwidth; + lowerbound = fabs((double)pool[i]->tce - ctk) * lpt + nh > 0; + } + if (upperbound) + break; + if (!upperbound || lowerbound) + { + if (pool[i]->ch == 999) + { + smvec2d a(0, ((double)pool[i]->tcs - ctk)*lpt + wheight - nh - minnotelength * 0.02); + smvec2d b(wwidth, ((double)pool[i]->tcs - ctk)*lpt + wheight - nh); + if (horizontal) + { + a = smvec2d(((double)pool[i]->tcs - ctk) * lpt + nh - minnotelength * 0.02, 0); + b = smvec2d(((double)pool[i]->tcs - ctk) * lpt + nh, wheight); + } + nq.v[0].x = nq.v[3].x = a.x; + nq.v[0].y = nq.v[1].y = a.y; + nq.v[1].x = nq.v[2].x = b.x; + nq.v[2].y = nq.v[3].y = b.y; + for (int j = 0; j < 4; ++j) + nq.v[j].col = 0xC0000000; + if (showmeasure) + sm->smRenderQuad(&nq); + continue; + } + if (pool[i]->ch >= 990) + continue; + if (api->getChannelMask(pool[i]->ch)) + continue; + smvec2d a((froffsets[12] * (pool[i]->key / 12) + froffsets[pool[i]->key % 12])*wwidth / 2048., ((double)pool[i]->tce - ctk)*lpt + wheight - nh); + smvec2d b(a.x + notew * 0.9, ((double)pool[i]->tcs - ctk)*lpt + wheight - nh); + if (horizontal) + { + a = smvec2d(((double)pool[i]->tce - ctk) * lpt + nh, (froffsets[12] * (pool[i]->key / 12) + froffsets[pool[i]->key % 12]) * wheight / 2048.); + b = smvec2d(((double)pool[i]->tcs - ctk) * lpt + nh, a.y + notew * 0.9); + } + bool isnoteon = pool[i]->tcs <= ctk && pool[i]->tce >= ctk; + if (isnoteon) + { + double pb = ((int)cpw[pool[i]->ch] - 8192) / 8192.*cpbr[pool[i]->ch]; + uint32_t newkey = pool[i]->key + (int)floor(pb); + double fpb = pb - floor(pb); + if (horizontal) + { + a.y = (froffsets[12] * (newkey / 12) + froffsets[newkey % 12]) * wheight / 2048. + notew * fpb; + b.y = a.y + notew * 0.9; + } + else + { + a.x = (froffsets[12] * (newkey / 12) + froffsets[newkey % 12]) * wwidth / 2048. + notew * fpb; + b.x = a.x + notew * 0.9; + } + } + if (horizontal) + a.y = wheight - a.y, b.y = wheight - b.y; + notestatus[pool[i]->ch][pool[i]->key] |= isnoteon; + if (horizontal) + { + if (((double)pool[i]->tce - pool[i]->tcs)*lpt < minnotelength * 0.04) + a.x = ((double)pool[i]->tcs - ctk) * lpt + nh - minnotelength * 0.04; + } + else + { + if (((double)pool[i]->tcs - pool[i]->tce)*lpt < minnotelength * 0.04) + a.y = ((double)pool[i]->tcs - ctk) * lpt + wheight - nh - minnotelength * 0.04; + } + nq.v[0].x = nq.v[3].x = a.x; + nq.v[0].y = nq.v[1].y = a.y; + nq.v[1].x = nq.v[2].x = b.x; + nq.v[2].y = nq.v[3].y = b.y; + for (int j = 0; j < 4; ++j) + nq.v[j].col = SETA(isnoteon ? accolors[pool[i]->ch] : iccolors[pool[i]->ch], int(pool[i]->vel * 1.6 + (isnoteon ? 52 : 32))); + if (usespectrum) + { + if (notestatus[pool[i]->ch][pool[i]->key] && !lastnotestatus[pool[i]->ch][pool[i]->key]) + spectra[pool[i]->ch][pool[i]->key] = pool[i]->vel * (api->getChannelCC(pool[i]->ch, 7) / 127.); + } + else sm->smRenderQuad(&nq); + } + } + if (horizontal) + while (pool.size() && elb < pool.size() && fabs((double)pool[elb]->tce - ctk)*lpt + nh < 0)++elb; + else + while (pool.size() && elb < pool.size() && fabs((double)pool[elb]->tce - ctk)*lpt + wheight - nh > wheight)++elb; + smQuad q; + q.tex = pianotex; + q.blend = BLEND_ALPHABLEND; + for (int i = 0; i < 4; ++i) + q.v[i].col = 0xFFFFFFFF, q.v[i].z = 0; + q.v[0].ty = q.v[3].ty = 0; + q.v[1].ty = q.v[2].ty = 172. / 256.; + q.v[0].tx = q.v[1].tx = 0; + q.v[2].tx = q.v[3].tx = 1.; + q.v[0].x = q.v[1].x = 0; + q.v[2].x = q.v[3].x = wwidth; + q.v[0].y = q.v[3].y = wheight - nh; + q.v[1].y = q.v[2].y = wheight; + if (horizontal) + { + q.v[0].tx = q.v[3].tx = 0; + q.v[1].tx = q.v[2].tx = 1; + q.v[0].ty = q.v[1].ty = 0; + q.v[2].ty = q.v[3].ty = 172. / 256.; + q.v[0].x = q.v[1].x = nh; + q.v[2].x = q.v[3].x = 0; + q.v[0].y = q.v[3].y = wheight; + q.v[1].y = q.v[2].y = 0; + } + sm->smRenderQuad(&q); + for (int i = 0, j; i < 128; ++i) + { + DWORD c = 0; + for (j = 0; j < 16; ++j) + if (notestatus[j][i]) + { + c = SETA(iccolors[j], 0xFF); + break; + } + if (horizontal) + { + q.v[0].y = q.v[1].y = (fpoffsets[12] * (i / 12) + fpoffsets[i % 12]) * wheight / 2048.; + q.v[2].y = q.v[3].y = q.v[0].y; + q.v[0].x = q.v[3].x = nh; + q.v[1].x = q.v[2].x = 0; + } + else + { + q.v[0].x = q.v[1].x = (fpoffsets[12] * (i / 12) + fpoffsets[i % 12]) * wwidth / 2048.; + q.v[2].x = q.v[3].x = q.v[0].x; + q.v[0].y = q.v[3].y = wheight - nh; + q.v[1].y = q.v[2].y = wheight; + } + if (!c) + continue; + for (int j = 0; j < 4; ++j) + q.v[j].col = c; + switch (i % 12) + { + case 1: + case 3: + case 6: + case 8: + case 10: + if (horizontal) + { + q.v[1].x = q.v[2].x = nh - 115 * wheight / 2048.; + q.v[2].y += 15.*wheight / 2048; + q.v[3].y += 15.*wheight / 2048; + } + else + { + q.v[1].y = q.v[2].y = wheight - nh + 115 * wwidth / 2048.; + q.v[2].x += 15.*wwidth / 2048; + q.v[3].x += 15.*wwidth / 2048; + } + q.v[0].ty = q.v[1].ty = 1.; + q.v[2].ty = q.v[3].ty = 1. - 15 / 256.; + q.v[0].tx = q.v[3].tx = 1344 / 2048.; + q.v[1].tx = q.v[2].tx = 1459 / 2048.; + break; + case 0: + if (horizontal) + { + q.v[2].y += 27.*wheight / 2048; + q.v[3].y += 27.*wheight / 2048; + } + else + { + q.v[2].x += 27.*wwidth / 2048; + q.v[3].x += 27.*wwidth / 2048; + } + q.v[0].ty = q.v[1].ty = 1.; + q.v[2].ty = q.v[3].ty = 1. - 27 / 256.; + q.v[0].tx = q.v[3].tx = 0 / 2048.; + q.v[1].tx = q.v[2].tx = 172 / 2048.; + break; + case 2: + if (horizontal) + { + q.v[2].y += 29.*wheight / 2048; + q.v[3].y += 29.*wheight / 2048; + } + else + { + q.v[2].x += 29.*wwidth / 2048; + q.v[3].x += 29.*wwidth / 2048; + } + q.v[0].ty = q.v[1].ty = 1.; + q.v[2].ty = q.v[3].ty = 1. - 29 / 256.; + q.v[0].tx = q.v[3].tx = 192 / 2048.; + q.v[1].tx = q.v[2].tx = 364 / 2048.; + break; + case 4: + if (horizontal) + { + q.v[2].y += 28.*wheight / 2048; + q.v[3].y += 28.*wheight / 2048; + } + else + { + q.v[2].x += 28.*wwidth / 2048; + q.v[3].x += 28.*wwidth / 2048; + } + q.v[0].ty = q.v[1].ty = 1.; + q.v[2].ty = q.v[3].ty = 1. - 28 / 256.; + q.v[0].tx = q.v[3].tx = 384 / 2048.; + q.v[1].tx = q.v[2].tx = 556 / 2048.; + break; + case 5: + if (horizontal) + { + q.v[2].y += 28.*wheight / 2048; + q.v[3].y += 28.*wheight / 2048; + } + else + { + q.v[2].x += 28.*wwidth / 2048; + q.v[3].x += 28.*wwidth / 2048; + } + q.v[0].ty = q.v[1].ty = 1.; + q.v[2].ty = q.v[3].ty = 1. - 28 / 256.; + q.v[0].tx = q.v[3].tx = 576 / 2048.; + q.v[1].tx = q.v[2].tx = 748 / 2048.; + break; + case 7: + if (horizontal) + { + q.v[2].y += 29.*wheight / 2048; + q.v[3].y += 29.*wheight / 2048; + } + else + { + q.v[2].x += 29.*wwidth / 2048; + q.v[3].x += 29.*wwidth / 2048; + } + q.v[0].ty = q.v[1].ty = 1.; + q.v[2].ty = q.v[3].ty = 1. - 29 / 256.; + q.v[0].tx = q.v[3].tx = 768 / 2048.; + q.v[1].tx = q.v[2].tx = 940 / 2048.; + break; + case 9: + if (horizontal) + { + q.v[2].y += 28.*wheight / 2048; + q.v[3].y += 28.*wheight / 2048; + } + else + { + q.v[2].x += 28.*wwidth / 2048; + q.v[3].x += 28.*wwidth / 2048; + } + q.v[0].ty = q.v[1].ty = 1.; + q.v[2].ty = q.v[3].ty = 1. - 28 / 256.; + q.v[0].tx = q.v[3].tx = 960 / 2048.; + q.v[1].tx = q.v[2].tx = 1132 / 2048.; + break; + case 11: + if (horizontal) + { + q.v[2].y += 28.*wheight / 2048; + q.v[3].y += 28.*wheight / 2048; + } + else + { + q.v[2].x += 28.*wwidth / 2048; + q.v[3].x += 28.*wwidth / 2048; + } + q.v[0].ty = q.v[1].ty = 1.; + q.v[2].ty = q.v[3].ty = 1. - 28 / 256.; + q.v[0].tx = q.v[3].tx = 1152 / 2048.; + q.v[1].tx = q.v[2].tx = 1324 / 2048.; + break; + } + if (horizontal) + for (int j = 0; j < 4; ++j) + q.v[j].y = wheight - q.v[j].y; + sm->smRenderQuad(&q); + } + if (usespectrum && playing) + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 128; ++j) + { + if (sustaininst.find(api->getChannelPreset(i)) != sustaininst.end()) + { + if (!notestatus[i][j] && spectra[i][j]) + spectra[i][j] = .95 * spectra[i][j]; + } + else if (spectra[i][j]) + spectra[i][j] = .95 * spectra[i][j]; + if (spectrar[i][j] < spectra[i][j] * 0.9) + spectrar[i][j] += spectra[i][j] * 0.2; + else spectrar[i][j] = spectra[i][j]; + if (spectrar[i][j]) + { + smvec2d a((froffsets[12] * (j / 12) + froffsets[j % 12])*wwidth / 2048., spectrar[i][j] / -128.*(wheight - nh) * (1 + 0.02 * sin(sm->smGetTime() * 32)) + wheight - nh); + smvec2d b(a.x + notew * 0.9, lpt + wheight - nh); + double pb = ((int)cpw[i] - 8192) / 8192.*cpbr[i]; + uint32_t newkey = j + (int)floor(pb); + double fpb = pb - floor(pb); + if (horizontal) + { + a = smvec2d(spectrar[i][j] / 128.*(wwidth - nh) * (1 + 0.02 * sin(sm->smGetTime() * 32)) + nh, (froffsets[12] * (j / 12) + froffsets[j % 12]) * wheight / 2048.); + b = smvec2d(nh, a.y + notew * 0.9); + a.y = (froffsets[12] * (newkey / 12) + froffsets[newkey % 12]) * wheight / 2048. + notew * fpb; + b.y = a.y + notew * 0.9; + a.y = wheight - a.y; + b.y = wheight - b.y; + } + else + { + a.x = (froffsets[12] * (newkey / 12) + froffsets[newkey % 12]) * wwidth / 2048. + notew * fpb; + b.x = a.x + notew * 0.9; + } + nq.v[0].x = nq.v[3].x = a.x; + nq.v[0].y = nq.v[1].y = a.y; + nq.v[1].x = nq.v[2].x = b.x; + nq.v[2].y = nq.v[3].y = b.y; + for (int j = 0; j < 4; ++j) + nq.v[j].col = SETA(iccolors[i], 204); + sm->smRenderQuad(&nq); + } + } } bool qmpVisualization::update() { - smQuad q; - if(!rendermode) - { - if(sm->smGetKeyState(SMK_RIGHT)==SMKST_HIT) - api->playerSeek(api->getCurrentPlaybackPercentage()+(sm->smGetKeyState(SMK_SHIFT)?5:1)); - if(sm->smGetKeyState(SMK_LEFT)==SMKST_HIT) - api->playerSeek(api->getCurrentPlaybackPercentage()-(sm->smGetKeyState(SMK_SHIFT)?5:1)); - if(sm->smGetKeyState(SMK_B)==SMKST_HIT) - debug^=1; - } - if(playing) - { - if(rendermode) - { - ctk=1e6*(cfr)/tfps/ctp*api->getDivision()+lstk; - ++cfr; - } - else - ctk=lstk+std::chrono::duration_cast>(std::chrono::steady_clock::now()-lst).count()/api->getRawTempo()*api->getDivision(); - } - if(!flat) - updateVisualization3D(); - sm->smRenderBegin2D(); - sm->smClrscr(0xFF666666);q.blend=BLEND_ALPHABLEND; - for(int i=0;i<4;++i){q.v[i].col=0xFFFFFFFF;q.v[i].z=0;} - if(bgtex) - { - q.tex=bgtex; - q.v[0].x=q.v[3].x=0;q.v[1].x=q.v[2].x=wwidth; - q.v[0].y=q.v[1].y=0;q.v[2].y=q.v[3].y=wheight; - q.v[0].tx=q.v[3].tx=0;q.v[1].tx=q.v[2].tx=1; - q.v[0].ty=q.v[1].ty=0;q.v[2].ty=q.v[3].ty=1; - sm->smRenderQuad(&q); - } - if(flat) - updateVisualization2D(); - else - { - q.tex=sm->smTargetTexture(tdscn); - q.v[0].tx=q.v[3].tx=0;q.v[1].tx=q.v[2].tx=1; - q.v[0].ty=q.v[1].ty=0;q.v[2].ty=q.v[3].ty=1; - q.v[0].x=q.v[1].x=0;q.v[2].x=q.v[3].x=wwidth; - q.v[0].y=q.v[3].y=0;q.v[1].y=q.v[2].y=wheight; - sm->smRenderQuad(&q); - if(showparticle&&!horizontal) - { - q.tex=sm->smTargetTexture(tdparticles); - sm->smRenderQuad(&q); - } - } - if(osdpos==4){sm->smRenderEnd();return shouldclose;} - uint32_t ltpc=~0u; - for(uint32_t i=elb;itcs>ctk)break; - if(pool[i]->ch==998)cts=pool[i]->key; - if(pool[i]->ch==997)cks=pool[i]->key; - if(pool[i]->ch==996) - ltpc=i; - if(pool[i]->ch==995)cpbr[pool[i]->vel]=pool[i]->key; - if(pool[i]->ch==994)cpw[pool[i]->vel]=pool[i]->key; - } - if(~ltpc&&ctp!=pool[ltpc]->key) - { - ctp=pool[ltpc]->key; - if(rendermode) - { - lstk=pool[ltpc]->tcs; - cfr=1; - } - } - int t,r;t=cks;r=(int8_t)((t>>8)&0xFF)+7;t&=0xFF; - std::wstring ts(t?minors:majors,2*r,2); - int step=int(1.33*fontsize); - int xp=(osdpos&1)?wwidth-step-1:1; - int yp=osdpos<2?wheight-step*5-4:step+4; - int align=osdpos&1?ALIGN_RIGHT:ALIGN_LEFT; - font2.updateString(L"Title: %ls",api->getWTitle().c_str()); - font2.render(xp,yp,0.5,0xFFFFFFFF,align); - font2.render(xp-1,yp-1,0.5,0xFF000000,align); - font.updateString(L"Time Sig: %d/%d",cts>>8,1<<(cts&0xFF)); - font.render(xp,yp+=step,0.5,0xFFFFFFFF,align); - font.render(xp-1,yp-1,0.5,0xFF000000,align); - font.updateString(L"Key Sig: %ls",ts.c_str()); - font.render(xp,yp+=step,0.5,0xFFFFFFFF,align); - font.render(xp-1,yp-1,0.5,0xFF000000,align); - font.updateString(L"Tempo: %.2f",60./(ctp/1e6)); - font.render(xp,yp+=step,0.5,0xFFFFFFFF,align); - font.render(xp-1,yp-1,0.5,0xFF000000,align); - font.updateString(L"Current tick: %d",ctk); - font.render(xp,yp+=step,0.5,0xFFFFFFFF,align); - font.render(xp-1,yp-1,0.5,0xFF000000,align); - if(!rendermode) - { - font.updateString(L"FPS: %.2f",sm->smGetFPS()); - font.render(xp,yp+=step,0.5,0xFFFFFFFF,align); - font.render(xp-1,yp-1,0.5,0xFF000000,align); - } - if(debug) - { - int dosdpos=(osdpos+1)%4; - xp=(dosdpos&1)?wwidth-step-1:1; - yp=dosdpos<2?wheight-step*5-4:step+4; - align=dosdpos&1?ALIGN_RIGHT:ALIGN_LEFT; - std::string tstr; - tstr=std::string(sm->smGetOSInfo()); - font.updateString(L"OS: %ls",std::wstring({std::begin(tstr),std::end(tstr)}).c_str()); - font.render(xp,yp,0.5,0xFFFFFFFF,align); - font.render(xp-1,yp-1,0.5,0xFF000000,align); - tstr=std::string(sm->smGetCPUModel()); - font.updateString(L"CPU: %ls",std::wstring({std::begin(tstr),std::end(tstr)}).c_str()); - font.render(xp,yp+=step,0.5,0xFFFFFFFF,align); - font.render(xp-1,yp-1,0.5,0xFF000000,align); - tstr=std::string(sm->smGetDispDriver()); - font.updateString(L"Display %ls",std::wstring({std::begin(tstr),std::end(tstr)}).c_str()); - font.render(xp,yp+=3*step,0.5,0xFFFFFFFF,align); - font.render(xp-1,yp-1,0.5,0xFF000000,align); - } - sm->smRenderEnd(); - if(rendermode) - { - if(ctk>api->getMaxTick()) - framecb(nullptr,0,ctk,api->getMaxTick()); - else - { - sm->smPixelCopy(0,0,wwidth,wheight,4*wwidth*wheight,fbcont); - framecb(fbcont,4*wwidth*wheight,ctk,api->getMaxTick()); - } - } - return shouldclose; + smQuad q; + if (!rendermode) + { + if (sm->smGetKeyState(SMK_RIGHT) == SMKST_HIT) + api->playerSeek(api->getCurrentPlaybackPercentage() + (sm->smGetKeyState(SMK_SHIFT) ? 5 : 1)); + if (sm->smGetKeyState(SMK_LEFT) == SMKST_HIT) + api->playerSeek(api->getCurrentPlaybackPercentage() - (sm->smGetKeyState(SMK_SHIFT) ? 5 : 1)); + if (sm->smGetKeyState(SMK_B) == SMKST_HIT) + debug ^= 1; + } + if (playing) + { + if (rendermode) + { + ctk = 1e6 * (cfr) / tfps / ctp * api->getDivision() + lstk; + ++cfr; + } + else + ctk = lstk + std::chrono::duration_cast>(std::chrono::steady_clock::now() - lst).count() / api->getRawTempo() * api->getDivision(); + } + if (!flat) + updateVisualization3D(); + sm->smRenderBegin2D(); + sm->smClrscr(0xFF666666); + q.blend = BLEND_ALPHABLEND; + for (int i = 0; i < 4; ++i) + { + q.v[i].col = 0xFFFFFFFF; + q.v[i].z = 0; + } + if (bgtex) + { + q.tex = bgtex; + q.v[0].x = q.v[3].x = 0; + q.v[1].x = q.v[2].x = wwidth; + q.v[0].y = q.v[1].y = 0; + q.v[2].y = q.v[3].y = wheight; + q.v[0].tx = q.v[3].tx = 0; + q.v[1].tx = q.v[2].tx = 1; + q.v[0].ty = q.v[1].ty = 0; + q.v[2].ty = q.v[3].ty = 1; + sm->smRenderQuad(&q); + } + if (flat) + updateVisualization2D(); + else + { + q.tex = sm->smTargetTexture(tdscn); + q.v[0].tx = q.v[3].tx = 0; + q.v[1].tx = q.v[2].tx = 1; + q.v[0].ty = q.v[1].ty = 0; + q.v[2].ty = q.v[3].ty = 1; + q.v[0].x = q.v[1].x = 0; + q.v[2].x = q.v[3].x = wwidth; + q.v[0].y = q.v[3].y = 0; + q.v[1].y = q.v[2].y = wheight; + sm->smRenderQuad(&q); + if (showparticle && !horizontal) + { + q.tex = sm->smTargetTexture(tdparticles); + sm->smRenderQuad(&q); + } + } + if (osdpos == 4) + { + sm->smRenderEnd(); + return shouldclose; + } + uint32_t ltpc = ~0u; + for (uint32_t i = elb; i < pool.size(); ++i) + { + if (pool[i]->tcs > ctk) + break; + if (pool[i]->ch == 998) + cts = pool[i]->key; + if (pool[i]->ch == 997) + cks = pool[i]->key; + if (pool[i]->ch == 996) + ltpc = i; + if (pool[i]->ch == 995) + cpbr[pool[i]->vel] = pool[i]->key; + if (pool[i]->ch == 994) + cpw[pool[i]->vel] = pool[i]->key; + } + if (~ltpc && ctp != pool[ltpc]->key) + { + ctp = pool[ltpc]->key; + if (rendermode) + { + lstk = pool[ltpc]->tcs; + cfr = 1; + } + } + int t, r; + t = cks; + r = (int8_t)((t >> 8) & 0xFF) + 7; + t &= 0xFF; + std::wstring ts(t ? minors : majors, 2 * r, 2); + int step = int(1.33 * fontsize); + int xp = (osdpos & 1) ? wwidth - step - 1 : 1; + int yp = osdpos < 2 ? wheight - step * 5 - 4 : step + 4; + int align = osdpos & 1 ? ALIGN_RIGHT : ALIGN_LEFT; + font2.updateString(L"Title: %ls", api->getWTitle().c_str()); + font2.render(xp, yp, 0.5, 0xFFFFFFFF, align); + font2.render(xp - 1, yp - 1, 0.5, 0xFF000000, align); + font.updateString(L"Time Sig: %d/%d", cts >> 8, 1 << (cts & 0xFF)); + font.render(xp, yp += step, 0.5, 0xFFFFFFFF, align); + font.render(xp - 1, yp - 1, 0.5, 0xFF000000, align); + font.updateString(L"Key Sig: %ls", ts.c_str()); + font.render(xp, yp += step, 0.5, 0xFFFFFFFF, align); + font.render(xp - 1, yp - 1, 0.5, 0xFF000000, align); + font.updateString(L"Tempo: %.2f", 60. / (ctp / 1e6)); + font.render(xp, yp += step, 0.5, 0xFFFFFFFF, align); + font.render(xp - 1, yp - 1, 0.5, 0xFF000000, align); + font.updateString(L"Current tick: %d", ctk); + font.render(xp, yp += step, 0.5, 0xFFFFFFFF, align); + font.render(xp - 1, yp - 1, 0.5, 0xFF000000, align); + if (!rendermode) + { + font.updateString(L"FPS: %.2f", sm->smGetFPS()); + font.render(xp, yp += step, 0.5, 0xFFFFFFFF, align); + font.render(xp - 1, yp - 1, 0.5, 0xFF000000, align); + } + if (debug) + { + int dosdpos = (osdpos + 1) % 4; + xp = (dosdpos & 1) ? wwidth - step - 1 : 1; + yp = dosdpos < 2 ? wheight - step * 5 - 4 : step + 4; + align = dosdpos & 1 ? ALIGN_RIGHT : ALIGN_LEFT; + std::string tstr; + tstr = std::string(sm->smGetOSInfo()); + font.updateString(L"OS: %ls", std::wstring({std::begin(tstr), std::end(tstr)}).c_str()); + font.render(xp, yp, 0.5, 0xFFFFFFFF, align); + font.render(xp - 1, yp - 1, 0.5, 0xFF000000, align); + tstr = std::string(sm->smGetCPUModel()); + font.updateString(L"CPU: %ls", std::wstring({std::begin(tstr), std::end(tstr)}).c_str()); + font.render(xp, yp += step, 0.5, 0xFFFFFFFF, align); + font.render(xp - 1, yp - 1, 0.5, 0xFF000000, align); + tstr = std::string(sm->smGetDispDriver()); + font.updateString(L"Display %ls", std::wstring({std::begin(tstr), std::end(tstr)}).c_str()); + font.render(xp, yp += 3 * step, 0.5, 0xFFFFFFFF, align); + font.render(xp - 1, yp - 1, 0.5, 0xFF000000, align); + } + sm->smRenderEnd(); + if (rendermode) + { + if (ctk > api->getMaxTick()) + framecb(nullptr, 0, ctk, api->getMaxTick()); + else + { + sm->smPixelCopy(0, 0, wwidth, wheight, 4 * wwidth * wheight, fbcont); + framecb(fbcont, 4 * wwidth * wheight, ctk, api->getMaxTick()); + } + } + return shouldclose; } -void qmpVisualization::drawCube(smvec3d a,smvec3d b,DWORD col,SMTEX tex,int faces) +void qmpVisualization::drawCube(smvec3d a, smvec3d b, DWORD col, SMTEX tex, int faces) { - smQuad q;q.blend=BLEND_ALPHABLEND; - q.tex=tex;for(int i=0;i<4;++i)q.v[i].col=col; - if(noteappearance==1) - { - smMatrix I;I.loadIdentity();smEntity3D c=smEntity3D::cube(a,b,col,faces); - nebuf->addTransformedEntity(&c,I,smvec3d(0,0,0)); - } - else - { - q.v[0].x=a.x;q.v[0].y=b.y;q.v[0].z=a.z; - q.v[1].x=b.x;q.v[1].y=b.y;q.v[1].z=a.z; - q.v[2].x=b.x;q.v[2].y=b.y;q.v[2].z=b.z; - q.v[3].x=a.x;q.v[3].y=b.y;q.v[3].z=b.z; - sm->smRenderQuad(&q); - } + smQuad q; + q.blend = BLEND_ALPHABLEND; + q.tex = tex; + for (int i = 0; i < 4; ++i) + q.v[i].col = col; + if (noteappearance == 1) + { + smMatrix I; + I.loadIdentity(); + smEntity3D c = smEntity3D::cube(a, b, col, faces); + nebuf->addTransformedEntity(&c, I, smvec3d(0, 0, 0)); + } + else + { + q.v[0].x = a.x; + q.v[0].y = b.y; + q.v[0].z = a.z; + q.v[1].x = b.x; + q.v[1].y = b.y; + q.v[1].z = a.z; + q.v[2].x = b.x; + q.v[2].y = b.y; + q.v[2].z = b.z; + q.v[3].x = a.x; + q.v[3].y = b.y; + q.v[3].z = b.z; + sm->smRenderQuad(&q); + } } -qmpVisualization* qmpVisualization::inst=nullptr; +qmpVisualization *qmpVisualization::inst = nullptr; -qmpVisualization::qmpVisualization(qmpPluginAPI* _api) +qmpVisualization::qmpVisualization(qmpPluginAPI *_api) { - api=_api; - inst=this; - rendermode=false; - hidewindow=false; + api = _api; + inst = this; + rendermode = false; + hidewindow = false; } qmpVisualization::~qmpVisualization() { - api=nullptr; - inst=nullptr; + api = nullptr; + inst = nullptr; } void qmpVisualization::init() { - h=new CMidiVisualHandler(this); - closeh=new CloseHandler(this); - rendererTh=nullptr;playing=false; - memset(rpnid,0xFF,sizeof(rpnid)); - memset(rpnval,0xFF,sizeof(rpnval)); - memset(spectra,0,sizeof(spectra)); - memset(spectrar,0,sizeof(spectrar)); - api->registerFunctionality(this,"Visualization","Visualization",api->isDarkTheme()?":/img/visualization_i.svg":":/img/visualization.svg",0,true); - uihb=api->registerUIHook("main.start",[this](const void*,void*){this->start();},nullptr); - uihs=api->registerUIHook("main.stop",[this](const void*,void*){this->stop();},nullptr); - uihp=api->registerUIHook("main.pause",[this](const void*,void*){this->pause();},nullptr); - uihr=api->registerUIHook("main.reset",[this](const void*,void*){this->reset();},nullptr); - uihk=api->registerUIHook("main.seek",[this](const void*,void*){ - cts=api->getTimeSig(); - cks=api->getKeySig(); - ctp=api->getRawTempo(); - for(int i=0;i<16;++i) - api->getPitchBendRaw(i,&cpw[i],&cpbr[i]); - },nullptr); - herh=api->registerEventReadHandler( - [this](const void *ee,void*){ - const SEvent* e=(const SEvent*)ee; - switch(e->type&0xF0) - { - case 0x80: - this->pushNoteOff(e->time,e->type&0x0F,e->p1); - break; - case 0x90: - if(e->p2) - this->pushNoteOn(e->time,e->type&0x0F,e->p1,e->p2); - else - this->pushNoteOff(e->time,e->type&0x0F,e->p1); - break; - case 0xB0: - if(e->p1==100)rpnid[e->type&0x0F]=e->p2; - if(e->p1==6)rpnval[e->type&0x0F]=e->p2; - if(~rpnid[e->type&0x0F]&&~rpnval[e->type&0x0F]) - { - if(rpnid[e->type&0x0F]==0) - this->pool.push_back(new MidiVisualEvent{e->time,e->time,rpnval[e->type&0x0F],e->type&0x0Fu,995}); - rpnval[e->type&0x0F]=~0u; - } - break; - case 0xE0: - this->pool.push_back(new MidiVisualEvent{e->time,e->time,(e->p1|(e->p2<<7))&0x3FFFu,e->type&0x0Fu,994}); - break; - case 0xF0: - if(e->type==0xFF&&e->p1==0x58) - { - this->tspool.push_back(std::make_pair(e->time,(e->str[0]<<24)|(e->str[1]<<16))); - this->pool.push_back(new MidiVisualEvent{e->time,e->time,(e->str[0]&0xffu)<<8|(e->str[1]&0xffu),0,998}); - } - else if(e->type==0xFF&&e->p1==0x59) - this->pool.push_back(new MidiVisualEvent{e->time,e->time,(e->str[0]&0xffu)<<8|(e->str[1]&0xffu),0,997}); - else if(e->type==0xFF&&e->p1==0x51) - this->pool.push_back(new MidiVisualEvent{e->time,e->time,(e->str[0]&0xffu)<<16|(e->str[1]&0xffu)<<8|(e->str[2]&0xffu),0,996}); - break; - } - } - ,nullptr); - heh=api->registerEventHandler( - [this](const void*,void*){ - if(this->ctk>this->api->getCurrentTimeStamp()+this->api->getDivision()/3) - this->elb=0; - /*if(abs((int)this->ctk-(int)this->api->getCurrentTimeStamp())>this->api->getDivision()/4) - fprintf(stderr,"Visualization: out of sync! %u vs %u ad: %u\n",this->ctk,this->api->getCurrentTimeStamp());*/ - this->ctk=this->api->getCurrentTimeStamp(); - this->lstk=this->ctk; - this->lst=std::chrono::steady_clock::now(); - } - ,nullptr); - hfrf=api->registerFileReadFinishHook( - [this](const void*,void*){ - memset(rpnval,0xFF,sizeof(rpnval)); - memset(rpnid,0xFF,sizeof(rpnid)); - std::sort(this->tspool.begin(),this->tspool.end()); - for(uint32_t tk=0,n=4,s=0;tk<=this->api->getMaxTick();){ - while(tk<(s>=this->tspool.size()?this->api->getMaxTick():this->tspool[s].first)){ - this->pool.push_back(new MidiVisualEvent{tk,tk,0,0,999}); - tk+=n*this->api->getDivision(); - } - tk=(s>=this->tspool.size()?this->api->getMaxTick():this->tspool[s].first); - if(tk==this->api->getMaxTick()){ - this->pool.push_back(new MidiVisualEvent{tk,tk,0,0,999}); - ++tk;break; - } - else n=this->tspool[s++].second>>24; - } - std::sort(this->pool.begin(),this->pool.end(),cmp); - } - ,nullptr); - api->registerOptionBool("Visualization-Appearance","Show Piano","Visualization/showpiano",true); - api->registerOptionBool("Visualization-Appearance","3D Notes","Visualization/3dnotes",true); - api->registerOptionBool("Visualization-Appearance","Arrange channels on a stair","Visualization/stairpiano",true); - api->registerOptionBool("Visualization-Appearance","Show channel labels","Visualization/showlabel",true); - api->registerOptionBool("Visualization-Appearance","Show Particles","Visualization/showparticle",false); - api->registerOptionBool("Visualization-Appearance","Horizontal Visualization","Visualization/horizontal",false); - api->registerOptionBool("Visualization-Appearance","2D Visualization","Visualization/flat",false); - api->registerOptionBool("Visualization-Appearance","Show Measure Indicator","Visualization/showmeasure",true); - api->registerOptionBool("Visualization-Appearance","Use spectrum instead of piano roll","Visualization/usespectrum",false); - api->registerOptionBool("Visualization-Video","Enable VSync","Visualization/vsync",true); - api->registerOptionBool("Visualization-Video","Save Viewport","Visualization/savevp",true); - api->registerOptionInt("Visualization-Video","Window Width","Visualization/wwidth",320,3200,800); - api->registerOptionInt("Visualization-Video","Window Height","Visualization/wheight",320,3200,600); - api->registerOptionInt("Visualization-Video","Target FPS","Visualization/tfps",5,1000,60); - api->registerOptionInt("Visualization-Video","Supersampling","Visualization/supersampling",1,16,0); - api->registerOptionInt("Visualization-Video","Multisampling","Visualization/multisampling",0,16,0); - api->registerOptionInt("Visualization-Video","FOV","Visualization/fov",30,180,60); - std::vector tv;tv.push_back("Bottom left");tv.push_back("Bottom right");tv.push_back("Top left");tv.push_back("Top right");tv.push_back("Hidden"); - api->registerOptionEnumInt("Visualization-Video","OSD Position","Visualization/osdpos",tv,0); - api->registerOptionInt("Visualization-Video","Font Size","Visualization/fontsize",6,180,16); - api->registerOptionString("Visualization-Video","Custom Sans Font","Visualization/font1","",true); - api->registerOptionString("Visualization-Video","Custom Monospace Font","Visualization/font2","",true); - api->registerOptionInt("Visualization-Appearance","View distance","Visualization/viewdist",20,1000,100); - api->registerOptionInt("Visualization-Appearance","Note stretch","Visualization/notestretch",20,500,100); - api->registerOptionInt("Visualization-Appearance","Minimum note length","Visualization/minnotelen",20,500,100); - api->registerOptionUint("Visualization-Appearance","Chequer board tint (AARRGGBB)","Visualization/chkrtint",0,0xFFFFFFFF,0xFF999999); - api->registerOptionString("Visualization-Appearance","Background Image","Visualization/background","",true); - api->registerOptionDouble("","","Visualization/px",-999999999,999999999,-1e9); - api->registerOptionDouble("","","Visualization/py",-999999999,999999999,-1e9); - api->registerOptionDouble("","","Visualization/pz",-999999999,999999999,-1e9); - api->registerOptionDouble("","","Visualization/rx",-999999999,999999999,-1e9); - api->registerOptionDouble("","","Visualization/ry",-999999999,999999999,-1e9); - api->registerOptionDouble("","","Visualization/rz",-999999999,999999999,-1e9); - for(int i=0;i<16;++i) - { - api->registerOptionUint("","","Visualization/chActiveColor"+std::to_string(i),0,0xFFFFFFFF,accolors[i]); - api->registerOptionUint("","","Visualization/chInactiveColor"+std::to_string(i),0,0xFFFFFFFF,iccolors[i]); - } - wwidth=api->getOptionInt("Visualization/wwidth"); - wheight=api->getOptionInt("Visualization/wheight"); - wsupersample=api->getOptionInt("Visualization/supersampling"); - wmultisample=api->getOptionInt("Visualization/multisampling"); - fov=api->getOptionInt("Visualization/fov"); - noteappearance=api->getOptionBool("Visualization/3dnotes"); - showpiano=api->getOptionBool("Visualization/showpiano"); - stairpiano=api->getOptionBool("Visualization/stairpiano"); - showlabel=api->getOptionBool("Visualization/showlabel"); - showparticle=api->getOptionBool("Visualization/showparticle"); - horizontal=api->getOptionBool("Visualization/horizontal"); - flat=api->getOptionBool("Visualization/flat"); - savevp=api->getOptionBool("Visualization/savevp"); - vsync=api->getOptionBool("Visualization/vsync"); - tfps=api->getOptionInt("Visualization/tfps"); - osdpos=api->getOptionEnumInt("Visualization/osdpos"); - fontsize=api->getOptionInt("Visualization/fontsize"); - viewdist=api->getOptionInt("Visualization/viewdist"); - notestretch=api->getOptionInt("Visualization/notestretch"); - minnotelength=api->getOptionInt("Visualization/minnotelen"); - chkrtint=api->getOptionUint("Visualization/chkrtint"); - for(int i=0;i<16;++i) - { - accolors[i]=api->getOptionUint("Visualization/chActiveColor"+std::to_string(i)); - iccolors[i]=api->getOptionUint("Visualization/chInactiveColor"+std::to_string(i)); - } - if(savevp) - { - pos[0]=api->getOptionDouble("Visualization/px"); - pos[1]=api->getOptionDouble("Visualization/py"); - pos[2]=api->getOptionDouble("Visualization/pz"); - rot[0]=api->getOptionDouble("Visualization/rx"); - rot[1]=api->getOptionDouble("Visualization/ry"); - rot[2]=api->getOptionDouble("Visualization/rz"); - } - memset(pss,0,sizeof(pss)); + h = new CMidiVisualHandler(this); + closeh = new CloseHandler(this); + rendererTh = nullptr; + playing = false; + memset(rpnid, 0xFF, sizeof(rpnid)); + memset(rpnval, 0xFF, sizeof(rpnval)); + memset(spectra, 0, sizeof(spectra)); + memset(spectrar, 0, sizeof(spectrar)); + api->registerFunctionality(this, "Visualization", "Visualization", api->isDarkTheme() ? ":/img/visualization_i.svg" : ":/img/visualization.svg", 0, true); + uihb = api->registerUIHook("main.start", [this](const void *, void *) + { + this->start(); + }, nullptr); + uihs = api->registerUIHook("main.stop", [this](const void *, void *) + { + this->stop(); + }, nullptr); + uihp = api->registerUIHook("main.pause", [this](const void *, void *) + { + this->pause(); + }, nullptr); + uihr = api->registerUIHook("main.reset", [this](const void *, void *) + { + this->reset(); + }, nullptr); + uihk = api->registerUIHook("main.seek", [this](const void *, void *) + { + cts = api->getTimeSig(); + cks = api->getKeySig(); + ctp = api->getRawTempo(); + for (int i = 0; i < 16; ++i) + api->getPitchBendRaw(i, &cpw[i], &cpbr[i]); + }, nullptr); + herh = api->registerEventReadHandler( + [this](const void *ee, void *) + { + const SEvent *e = (const SEvent *)ee; + switch (e->type & 0xF0) + { + case 0x80: + this->pushNoteOff(e->time, e->type & 0x0F, e->p1); + break; + case 0x90: + if (e->p2) + this->pushNoteOn(e->time, e->type & 0x0F, e->p1, e->p2); + else + this->pushNoteOff(e->time, e->type & 0x0F, e->p1); + break; + case 0xB0: + if (e->p1 == 100) + rpnid[e->type & 0x0F] = e->p2; + if (e->p1 == 6) + rpnval[e->type & 0x0F] = e->p2; + if (~rpnid[e->type & 0x0F] && ~rpnval[e->type & 0x0F]) + { + if (rpnid[e->type & 0x0F] == 0) + this->pool.push_back(new MidiVisualEvent{e->time, e->time, rpnval[e->type & 0x0F], e->type & 0x0Fu, 995}); + rpnval[e->type & 0x0F] = ~0u; + } + break; + case 0xE0: + this->pool.push_back(new MidiVisualEvent{e->time, e->time, (e->p1 | (e->p2 << 7)) & 0x3FFFu, e->type & 0x0Fu, 994}); + break; + case 0xF0: + if (e->type == 0xFF && e->p1 == 0x58) + { + this->tspool.push_back(std::make_pair(e->time, (e->str[0] << 24) | (e->str[1] << 16))); + this->pool.push_back(new MidiVisualEvent{e->time, e->time, (e->str[0] & 0xffu) << 8 | (e->str[1] & 0xffu), 0, 998}); + } + else if (e->type == 0xFF && e->p1 == 0x59) + this->pool.push_back(new MidiVisualEvent{e->time, e->time, (e->str[0] & 0xffu) << 8 | (e->str[1] & 0xffu), 0, 997}); + else if (e->type == 0xFF && e->p1 == 0x51) + this->pool.push_back(new MidiVisualEvent{e->time, e->time, (e->str[0] & 0xffu) << 16 | (e->str[1] & 0xffu) << 8 | (e->str[2] & 0xffu), 0, 996}); + break; + } + } + , nullptr); + heh = api->registerEventHandler( + [this](const void *, void *) + { + if (this->ctk > this->api->getCurrentTimeStamp() + this->api->getDivision() / 3) + this->elb = 0; + /*if(abs((int)this->ctk-(int)this->api->getCurrentTimeStamp())>this->api->getDivision()/4) + fprintf(stderr,"Visualization: out of sync! %u vs %u ad: %u\n",this->ctk,this->api->getCurrentTimeStamp());*/ + this->ctk = this->api->getCurrentTimeStamp(); + this->lstk = this->ctk; + this->lst = std::chrono::steady_clock::now(); + } + , nullptr); + hfrf = api->registerFileReadFinishHook( + [this](const void *, void *) + { + memset(rpnval, 0xFF, sizeof(rpnval)); + memset(rpnid, 0xFF, sizeof(rpnid)); + std::sort(this->tspool.begin(), this->tspool.end()); + for (uint32_t tk = 0, n = 4, s = 0; tk <= this->api->getMaxTick();) + { + while (tk < (s >= this->tspool.size() ? this->api->getMaxTick() : this->tspool[s].first)) + { + this->pool.push_back(new MidiVisualEvent{tk, tk, 0, 0, 999}); + tk += n * this->api->getDivision(); + } + tk = (s >= this->tspool.size() ? this->api->getMaxTick() : this->tspool[s].first); + if (tk == this->api->getMaxTick()) + { + this->pool.push_back(new MidiVisualEvent{tk, tk, 0, 0, 999}); + ++tk; + break; + } + else n = this->tspool[s++].second >> 24; + } + std::sort(this->pool.begin(), this->pool.end(), cmp); + } + , nullptr); + api->registerOptionBool("Visualization-Appearance", "Show Piano", "Visualization/showpiano", true); + api->registerOptionBool("Visualization-Appearance", "3D Notes", "Visualization/3dnotes", true); + api->registerOptionBool("Visualization-Appearance", "Arrange channels on a stair", "Visualization/stairpiano", true); + api->registerOptionBool("Visualization-Appearance", "Show channel labels", "Visualization/showlabel", true); + api->registerOptionBool("Visualization-Appearance", "Show Particles", "Visualization/showparticle", false); + api->registerOptionBool("Visualization-Appearance", "Horizontal Visualization", "Visualization/horizontal", false); + api->registerOptionBool("Visualization-Appearance", "2D Visualization", "Visualization/flat", false); + api->registerOptionBool("Visualization-Appearance", "Show Measure Indicator", "Visualization/showmeasure", true); + api->registerOptionBool("Visualization-Appearance", "Use spectrum instead of piano roll", "Visualization/usespectrum", false); + api->registerOptionBool("Visualization-Video", "Enable VSync", "Visualization/vsync", true); + api->registerOptionBool("Visualization-Video", "Save Viewport", "Visualization/savevp", true); + api->registerOptionInt("Visualization-Video", "Window Width", "Visualization/wwidth", 320, 3200, 800); + api->registerOptionInt("Visualization-Video", "Window Height", "Visualization/wheight", 320, 3200, 600); + api->registerOptionInt("Visualization-Video", "Target FPS", "Visualization/tfps", 5, 1000, 60); + api->registerOptionInt("Visualization-Video", "Supersampling", "Visualization/supersampling", 1, 16, 0); + api->registerOptionInt("Visualization-Video", "Multisampling", "Visualization/multisampling", 0, 16, 0); + api->registerOptionInt("Visualization-Video", "FOV", "Visualization/fov", 30, 180, 60); + std::vector tv; + tv.push_back("Bottom left"); + tv.push_back("Bottom right"); + tv.push_back("Top left"); + tv.push_back("Top right"); + tv.push_back("Hidden"); + api->registerOptionEnumInt("Visualization-Video", "OSD Position", "Visualization/osdpos", tv, 0); + api->registerOptionInt("Visualization-Video", "Font Size", "Visualization/fontsize", 6, 180, 16); + api->registerOptionString("Visualization-Video", "Custom Sans Font", "Visualization/font1", "", true); + api->registerOptionString("Visualization-Video", "Custom Monospace Font", "Visualization/font2", "", true); + api->registerOptionInt("Visualization-Appearance", "View distance", "Visualization/viewdist", 20, 1000, 100); + api->registerOptionInt("Visualization-Appearance", "Note stretch", "Visualization/notestretch", 20, 500, 100); + api->registerOptionInt("Visualization-Appearance", "Minimum note length", "Visualization/minnotelen", 20, 500, 100); + api->registerOptionUint("Visualization-Appearance", "Chequer board tint (AARRGGBB)", "Visualization/chkrtint", 0, 0xFFFFFFFF, 0xFF999999); + api->registerOptionString("Visualization-Appearance", "Background Image", "Visualization/background", "", true); + api->registerOptionDouble("", "", "Visualization/px", -999999999, 999999999, -1e9); + api->registerOptionDouble("", "", "Visualization/py", -999999999, 999999999, -1e9); + api->registerOptionDouble("", "", "Visualization/pz", -999999999, 999999999, -1e9); + api->registerOptionDouble("", "", "Visualization/rx", -999999999, 999999999, -1e9); + api->registerOptionDouble("", "", "Visualization/ry", -999999999, 999999999, -1e9); + api->registerOptionDouble("", "", "Visualization/rz", -999999999, 999999999, -1e9); + for (int i = 0; i < 16; ++i) + { + api->registerOptionUint("", "", "Visualization/chActiveColor" + std::to_string(i), 0, 0xFFFFFFFF, accolors[i]); + api->registerOptionUint("", "", "Visualization/chInactiveColor" + std::to_string(i), 0, 0xFFFFFFFF, iccolors[i]); + } + wwidth = api->getOptionInt("Visualization/wwidth"); + wheight = api->getOptionInt("Visualization/wheight"); + wsupersample = api->getOptionInt("Visualization/supersampling"); + wmultisample = api->getOptionInt("Visualization/multisampling"); + fov = api->getOptionInt("Visualization/fov"); + noteappearance = api->getOptionBool("Visualization/3dnotes"); + showpiano = api->getOptionBool("Visualization/showpiano"); + stairpiano = api->getOptionBool("Visualization/stairpiano"); + showlabel = api->getOptionBool("Visualization/showlabel"); + showparticle = api->getOptionBool("Visualization/showparticle"); + horizontal = api->getOptionBool("Visualization/horizontal"); + flat = api->getOptionBool("Visualization/flat"); + savevp = api->getOptionBool("Visualization/savevp"); + vsync = api->getOptionBool("Visualization/vsync"); + tfps = api->getOptionInt("Visualization/tfps"); + osdpos = api->getOptionEnumInt("Visualization/osdpos"); + fontsize = api->getOptionInt("Visualization/fontsize"); + viewdist = api->getOptionInt("Visualization/viewdist"); + notestretch = api->getOptionInt("Visualization/notestretch"); + minnotelength = api->getOptionInt("Visualization/minnotelen"); + chkrtint = api->getOptionUint("Visualization/chkrtint"); + for (int i = 0; i < 16; ++i) + { + accolors[i] = api->getOptionUint("Visualization/chActiveColor" + std::to_string(i)); + iccolors[i] = api->getOptionUint("Visualization/chInactiveColor" + std::to_string(i)); + } + if (savevp) + { + pos[0] = api->getOptionDouble("Visualization/px"); + pos[1] = api->getOptionDouble("Visualization/py"); + pos[2] = api->getOptionDouble("Visualization/pz"); + rot[0] = api->getOptionDouble("Visualization/rx"); + rot[1] = api->getOptionDouble("Visualization/ry"); + rot[2] = api->getOptionDouble("Visualization/rz"); + } + memset(pss, 0, sizeof(pss)); } void qmpVisualization::deinit() { - if(!api)return;close();tspool.clear(); - for(unsigned i=0;iunregisterUIHook("main.start",uihb); - api->unregisterUIHook("main.stop",uihs); - api->unregisterUIHook("main.pause",uihp); - api->unregisterUIHook("main.reset",uihr); - api->unregisterFunctionality("Visualization"); - api->unregisterEventReadHandler(herh); - api->unregisterEventHandler(heh); - api->unregisterFileReadFinishHook(hfrf); - delete h;delete closeh; + if (!api) + return; + close(); + tspool.clear(); + for (unsigned i = 0; i < pool.size(); ++i) + delete pool[i]; + pool.clear(); + api->unregisterUIHook("main.start", uihb); + api->unregisterUIHook("main.stop", uihs); + api->unregisterUIHook("main.pause", uihp); + api->unregisterUIHook("main.reset", uihr); + api->unregisterFunctionality("Visualization"); + api->unregisterEventReadHandler(herh); + api->unregisterEventHandler(heh); + api->unregisterFileReadFinishHook(hfrf); + delete h; + delete closeh; +} +const char *qmpVisualization::pluginGetName() +{ + return "QMidiPlayer Default Visualization Plugin"; +} +const char *qmpVisualization::pluginGetVersion() +{ + return PLUGIN_VERSION; } -const char* qmpVisualization::pluginGetName() -{return "QMidiPlayer Default Visualization Plugin";} -const char* qmpVisualization::pluginGetVersion() -{return PLUGIN_VERSION;} qmpVisualization *qmpVisualization::instance() -{return inst;} +{ + return inst; +} -void qmpVisualization::pushNoteOn(uint32_t tc,uint32_t ch,uint32_t key,uint32_t vel) +void qmpVisualization::pushNoteOn(uint32_t tc, uint32_t ch, uint32_t key, uint32_t vel) { - pendingt[ch][key].push(tc); - pendingv[ch][key].push(vel); + pendingt[ch][key].push(tc); + pendingv[ch][key].push(vel); } -void qmpVisualization::pushNoteOff(uint32_t tc,uint32_t ch,uint32_t key) +void qmpVisualization::pushNoteOff(uint32_t tc, uint32_t ch, uint32_t key) { - if(pendingt[ch][key].size()<1)return; - MidiVisualEvent *ne=new MidiVisualEvent(); - ne->tcs=pendingt[ch][key].top();pendingt[ch][key].pop(); - ne->tce=tc;ne->ch=ch;ne->key=key; - ne->vel=pendingv[ch][key].top();pendingv[ch][key].pop(); - pool.push_back(ne); + if (pendingt[ch][key].size() < 1) + return; + MidiVisualEvent *ne = new MidiVisualEvent(); + ne->tcs = pendingt[ch][key].top(); + pendingt[ch][key].pop(); + ne->tce = tc; + ne->ch = ch; + ne->key = key; + ne->vel = pendingv[ch][key].top(); + pendingv[ch][key].pop(); + pool.push_back(ne); } diff --git a/visualization/qmpvisualization.hpp b/visualization/qmpvisualization.hpp index 8a8d832..c0bc067 100644 --- a/visualization/qmpvisualization.hpp +++ b/visualization/qmpvisualization.hpp @@ -15,105 +15,121 @@ class qmpVisualization; struct MidiVisualEvent { - uint32_t tcs,tce; - uint32_t key,vel; - uint32_t ch; + uint32_t tcs, tce; + uint32_t key, vel; + uint32_t ch; }; -class qmpVisualization:public qmpPluginIntf,public qmpFuncBaseIntf +class qmpVisualization: public qmpPluginIntf, public qmpFuncBaseIntf { - friend class CloseHandler; - private: - qmpPluginAPI* api; - std::thread* rendererTh; - std::vectorpool; - smHandler *h,*closeh; - std::stack pendingt[16][128],pendingv[16][128]; - SMELT *sm; - SMTRG tdscn,tdparticles; - SMTEX chequer,bgtex,particletex,pianotex; - smTTFont font,font2,fonthdpi; - qmpVirtualPiano3D* p3d[16]; - smEntity3DBuffer* nebuf; - smParticleSystem* pss[16][128]; - smPSEmissionPositionGenerator* psepg; - float pos[3],rot[3],lastx,lasty; - uint32_t ctc,ctk,elb,lstk,cfr; - uint32_t cts,cks,ctp,cpbr[16],cpw[16]; - uint32_t rpnid[16],rpnval[16]; - std::chrono::steady_clock::time_point lst; - double etps; - bool shouldclose,playing,debug; - bool rendermode,hidewindow; - int herh,heh,hfrf; - int uihb,uihs,uihp,uihr,uihk; - void(*framecb)(void*,size_t,uint32_t,uint32_t); - DWORD* fbcont; - std::vector>tspool; - int traveld[16][128];bool notestatus[16][128],lastnotestatus[16][128]; - int spectra[16][128],spectrar[16][128]; - void drawCube(smvec3d a,smvec3d b,DWORD col,SMTEX tex,int faces=63); - void showThread(); - void pushNoteOn(uint32_t tc,uint32_t ch,uint32_t key,uint32_t vel); - void pushNoteOff(uint32_t tc,uint32_t ch,uint32_t key); - void updateVisualization3D(); - void updateVisualization2D(); + friend class CloseHandler; +private: + qmpPluginAPI *api; + std::thread *rendererTh; + std::vectorpool; + smHandler *h, *closeh; + std::stack pendingt[16][128], pendingv[16][128]; + SMELT *sm; + SMTRG tdscn, tdparticles; + SMTEX chequer, bgtex, particletex, pianotex; + smTTFont font, font2, fonthdpi; + qmpVirtualPiano3D *p3d[16]; + smEntity3DBuffer *nebuf; + smParticleSystem *pss[16][128]; + smPSEmissionPositionGenerator *psepg; + float pos[3], rot[3], lastx, lasty; + uint32_t ctc, ctk, elb, lstk, cfr; + uint32_t cts, cks, ctp, cpbr[16], cpw[16]; + uint32_t rpnid[16], rpnval[16]; + std::chrono::steady_clock::time_point lst; + double etps; + bool shouldclose, playing, debug; + bool rendermode, hidewindow; + int herh, heh, hfrf; + int uihb, uihs, uihp, uihr, uihk; + void(*framecb)(void *, size_t, uint32_t, uint32_t); + DWORD *fbcont; + std::vector>tspool; + int traveld[16][128]; + bool notestatus[16][128], lastnotestatus[16][128]; + int spectra[16][128], spectrar[16][128]; + void drawCube(smvec3d a, smvec3d b, DWORD col, SMTEX tex, int faces = 63); + void showThread(); + void pushNoteOn(uint32_t tc, uint32_t ch, uint32_t key, uint32_t vel); + void pushNoteOff(uint32_t tc, uint32_t ch, uint32_t key); + void updateVisualization3D(); + void updateVisualization2D(); - static qmpVisualization* inst; - public: - qmpVisualization(qmpPluginAPI* _api); - ~qmpVisualization(); - void show(); - void close(); - bool update(); - void start(); - void stop(); - void pause(); - void reset(); - void switchToRenderMode(void(*frameCallback)(void*,size_t,uint32_t,uint32_t),bool _hidewindow); + static qmpVisualization *inst; +public: + qmpVisualization(qmpPluginAPI *_api); + ~qmpVisualization(); + void show(); + void close(); + bool update(); + void start(); + void stop(); + void pause(); + void reset(); + void switchToRenderMode(void(*frameCallback)(void *, size_t, uint32_t, uint32_t), bool _hidewindow); - void init(); - void deinit(); - const char* pluginGetName(); - const char* pluginGetVersion(); + void init(); + void deinit(); + const char *pluginGetName(); + const char *pluginGetVersion(); - static qmpVisualization* instance(); + static qmpVisualization *instance(); }; -class CMidiVisualHandler:public smHandler +class CMidiVisualHandler: public smHandler { - private: - qmpVisualization *p; - public: - CMidiVisualHandler(qmpVisualization* par){p=par;} - bool handlerFunc(){return p->update();} +private: + qmpVisualization *p; +public: + CMidiVisualHandler(qmpVisualization *par) + { + p = par; + } + bool handlerFunc() + { + return p->update(); + } }; -class CloseHandler:public smHandler +class CloseHandler: public smHandler { - private: - qmpVisualization *p; - public: - CloseHandler(qmpVisualization* par){p=par;} - public: - bool handlerFunc() - { - std::thread ([this]{ - p->api->setFuncState("Visualization",false); - p->close();}).detach(); - return false; - } +private: + qmpVisualization *p; +public: + CloseHandler(qmpVisualization *par) + { + p = par; + } +public: + bool handlerFunc() + { + std::thread([this] + { + p->api->setFuncState("Visualization", false); + p->close(); + }).detach(); + return false; + } }; -extern "C"{ - EXPORTSYM qmpPluginIntf* qmpPluginGetInterface(qmpPluginAPI* api) - {return new qmpVisualization(api);} - EXPORTSYM const char* qmpPluginGetAPIRev() - {return QMP_PLUGIN_API_REV;} - EXPORTSYM void switchToRenderMode(void(*frameCallback)(void*,size_t,uint32_t,uint32_t),bool hidewindow) - { - if(qmpVisualization::instance()) - qmpVisualization::instance()->switchToRenderMode(frameCallback,hidewindow); - } +extern "C" { + EXPORTSYM qmpPluginIntf *qmpPluginGetInterface(qmpPluginAPI *api) + { + return new qmpVisualization(api); + } + EXPORTSYM const char *qmpPluginGetAPIRev() + { + return QMP_PLUGIN_API_REV; + } + EXPORTSYM void switchToRenderMode(void(*frameCallback)(void *, size_t, uint32_t, uint32_t), bool hidewindow) + { + if (qmpVisualization::instance()) + qmpVisualization::instance()->switchToRenderMode(frameCallback, hidewindow); + } } #endif // QMPVISUALIZATION_H diff --git a/visualization/renderer/main.cpp b/visualization/renderer/main.cpp index c651c54..7f25578 100644 --- a/visualization/renderer/main.cpp +++ b/visualization/renderer/main.cpp @@ -4,44 +4,46 @@ #include "qmpvisrendercore.hpp" #include "qmpsettingsro.hpp" -int main(int argc,char **argv) +int main(int argc, char **argv) { - QCoreApplication::setApplicationName("qmpvisrender"); - QCoreApplication::setApplicationVersion("0.0.0"); - QCoreApplication a(argc,argv); - QCommandLineParser clp; - clp.setApplicationDescription("Renderer a visualization of a midi file."); - clp.addHelpOption(); - clp.addVersionOption(); - clp.addOption({{"f","output-file"},"File name of the output file.","filename","output.mp4"}); - clp.addOption({ - "receiver", - "Specify a program and its arguments to process the rendered frames. Supports parameter substitution. See documentation for details.", - "command", - "ffmpeg %i -vf vflip -pix_fmt yuv420p -c:v libx264 -preset slow -crf 22 %o" - }); - clp.addOption({ - {"e","receiver-execution"}, - "Execution mode of the receiver command. Valid options are 'one-shot' and 'per-frame'", - "mode", - "one-shot" - }); - clp.addOption({{"s","show-window"},"Do not hide the visualization window."}); - clp.addOption({{"c","config"},"Load options from the configuration file.","qmprc file"}); - clp.addOption({{"o","option"},"Set option for the visualization module.","key-value pair"}); - clp.addOption({"list-options","Show a list of recognized options and quit."}); - clp.addPositionalArgument("file","MIDI file to render"); - clp.process(a.arguments()); - qmpVisRenderCore core(&clp); - if(clp.positionalArguments().empty()&&!clp.isSet("list-options")) - clp.showHelp(1); - core.loadSettings(); - if(!core.loadVisualizationLibrary()) - return 1; - if(clp.positionalArguments().size()) - core.setMIDIFile(clp.positionalArguments().front().toStdString().c_str()); - core.startRender(); - int retval=a.exec(); - core.unloadVisualizationLibrary(); - return retval; + QCoreApplication::setApplicationName("qmpvisrender"); + QCoreApplication::setApplicationVersion("0.0.0"); + QCoreApplication a(argc, argv); + QCommandLineParser clp; + clp.setApplicationDescription("Renderer a visualization of a midi file."); + clp.addHelpOption(); + clp.addVersionOption(); + clp.addOption({{"f", "output-file"}, "File name of the output file.", "filename", "output.mp4"}); + clp.addOption( + { + "receiver", + "Specify a program and its arguments to process the rendered frames. Supports parameter substitution. See documentation for details.", + "command", + "ffmpeg %i -vf vflip -pix_fmt yuv420p -c:v libx264 -preset slow -crf 22 %o" + }); + clp.addOption( + { + {"e", "receiver-execution"}, + "Execution mode of the receiver command. Valid options are 'one-shot' and 'per-frame'", + "mode", + "one-shot" + }); + clp.addOption({{"s", "show-window"}, "Do not hide the visualization window."}); + clp.addOption({{"c", "config"}, "Load options from the configuration file.", "qmprc file"}); + clp.addOption({{"o", "option"}, "Set option for the visualization module.", "key-value pair"}); + clp.addOption({"list-options", "Show a list of recognized options and quit."}); + clp.addPositionalArgument("file", "MIDI file to render"); + clp.process(a.arguments()); + qmpVisRenderCore core(&clp); + if (clp.positionalArguments().empty() && !clp.isSet("list-options")) + clp.showHelp(1); + core.loadSettings(); + if (!core.loadVisualizationLibrary()) + return 1; + if (clp.positionalArguments().size()) + core.setMIDIFile(clp.positionalArguments().front().toStdString().c_str()); + core.startRender(); + int retval = a.exec(); + core.unloadVisualizationLibrary(); + return retval; } diff --git a/visualization/renderer/qmppluginapistub.cpp b/visualization/renderer/qmppluginapistub.cpp index 1be4880..b84a2b6 100644 --- a/visualization/renderer/qmppluginapistub.cpp +++ b/visualization/renderer/qmppluginapistub.cpp @@ -6,197 +6,245 @@ #include qmpPluginAPIStub::qmpPluginAPIStub(qmpVisRenderCore *_core): - core(_core) + core(_core) { } qmpPluginAPIStub::~qmpPluginAPIStub() { - core=nullptr; + core = nullptr; } uint32_t qmpPluginAPIStub::getDivision() { - return core->player->getDivision(); + return core->player->getDivision(); +} +uint32_t qmpPluginAPIStub::getRawTempo() +{ + return 0; +} +double qmpPluginAPIStub::getRealTempo() +{ + return 0; +} +uint32_t qmpPluginAPIStub::getTimeSig() +{ + return 0; +} +int qmpPluginAPIStub::getKeySig() +{ + return 0; +} +uint32_t qmpPluginAPIStub::getNoteCount() +{ + return 0; } -uint32_t qmpPluginAPIStub::getRawTempo(){return 0;} -double qmpPluginAPIStub::getRealTempo(){return 0;} -uint32_t qmpPluginAPIStub::getTimeSig(){return 0;} -int qmpPluginAPIStub::getKeySig(){return 0;} -uint32_t qmpPluginAPIStub::getNoteCount(){return 0;} uint32_t qmpPluginAPIStub::getMaxTick() { - return core->player->getMaxTick(); -} -uint32_t qmpPluginAPIStub::getCurrentPolyphone(){return 0;} -uint32_t qmpPluginAPIStub::getMaxPolyphone(){return 0;} -uint32_t qmpPluginAPIStub::getCurrentTimeStamp(){return 0;} -uint32_t qmpPluginAPIStub::getCurrentPlaybackPercentage(){return 0;} -int qmpPluginAPIStub::getChannelCC(int ch, int cc){return 0;} -int qmpPluginAPIStub::getChannelPreset(int ch){return 0;} -void qmpPluginAPIStub::playerSeek(uint32_t percentage){} -double qmpPluginAPIStub::getPitchBend(int ch){return 0;} -void qmpPluginAPIStub::getPitchBendRaw(int ch,uint32_t *pb,uint32_t *pbr){} -bool qmpPluginAPIStub::getChannelMask(int ch){return 0;} + return core->player->getMaxTick(); +} +uint32_t qmpPluginAPIStub::getCurrentPolyphone() +{ + return 0; +} +uint32_t qmpPluginAPIStub::getMaxPolyphone() +{ + return 0; +} +uint32_t qmpPluginAPIStub::getCurrentTimeStamp() +{ + return 0; +} +uint32_t qmpPluginAPIStub::getCurrentPlaybackPercentage() +{ + return 0; +} +int qmpPluginAPIStub::getChannelCC(int ch, int cc) +{ + return 0; +} +int qmpPluginAPIStub::getChannelPreset(int ch) +{ + return 0; +} +void qmpPluginAPIStub::playerSeek(uint32_t percentage) {} +double qmpPluginAPIStub::getPitchBend(int ch) +{ + return 0; +} +void qmpPluginAPIStub::getPitchBendRaw(int ch, uint32_t *pb, uint32_t *pbr) {} +bool qmpPluginAPIStub::getChannelMask(int ch) +{ + return 0; +} std::string qmpPluginAPIStub::getTitle() { - if(core->settings()->getOptionEnumIntOptName("Midi/TextEncoding")=="Unicode") - return std::string(core->player->getTitle()); - return QTextCodec::codecForName( - core->settings()->getOptionEnumIntOptName("Midi/TextEncoding").c_str())-> - toUnicode(core->player->getTitle()).toStdString(); + if (core->settings()->getOptionEnumIntOptName("Midi/TextEncoding") == "Unicode") + return std::string(core->player->getTitle()); + return QTextCodec::codecForName( + core->settings()->getOptionEnumIntOptName("Midi/TextEncoding").c_str())-> + toUnicode(core->player->getTitle()).toStdString(); } std::wstring qmpPluginAPIStub::getWTitle() { - if(core->settings()->getOptionEnumIntOptName("Midi/TextEncoding")=="Unicode") - return QString(core->player->getTitle()).toStdWString(); - return QTextCodec::codecForName( - core->settings()->getOptionEnumIntOptName("Midi/TextEncoding").c_str())-> - toUnicode(core->player->getTitle()).toStdWString(); -} -std::string qmpPluginAPIStub::getChannelPresetString(int ch){return std::string();} -bool qmpPluginAPIStub::isDarkTheme(){return false;} -void *qmpPluginAPIStub::getMainWindow(){return nullptr;} -void qmpPluginAPIStub::discardCurrentEvent(){} -void qmpPluginAPIStub::commitEventChange(SEvent d){} -void qmpPluginAPIStub::callEventReaderCB(SEvent d){} -void qmpPluginAPIStub::setFuncState(std::string name,bool state){} + if (core->settings()->getOptionEnumIntOptName("Midi/TextEncoding") == "Unicode") + return QString(core->player->getTitle()).toStdWString(); + return QTextCodec::codecForName( + core->settings()->getOptionEnumIntOptName("Midi/TextEncoding").c_str())-> + toUnicode(core->player->getTitle()).toStdWString(); +} +std::string qmpPluginAPIStub::getChannelPresetString(int ch) +{ + return std::string(); +} +bool qmpPluginAPIStub::isDarkTheme() +{ + return false; +} +void *qmpPluginAPIStub::getMainWindow() +{ + return nullptr; +} +void qmpPluginAPIStub::discardCurrentEvent() {} +void qmpPluginAPIStub::commitEventChange(SEvent d) {} +void qmpPluginAPIStub::callEventReaderCB(SEvent d) {} +void qmpPluginAPIStub::setFuncState(std::string name, bool state) {} void qmpPluginAPIStub::setFuncEnabled(std::string name, bool enable) {} void qmpPluginAPIStub::registerFunctionality(qmpFuncBaseIntf *i, std::string name, std::string desc, const char *icon, int iconlen, bool checkable) { - if(name=="Visualization") - core->vf=i; + if (name == "Visualization") + core->vf = i; } void qmpPluginAPIStub::unregisterFunctionality(std::string name) { - if(name=="Visualization") - core->vf=nullptr; + if (name == "Visualization") + core->vf = nullptr; } -int qmpPluginAPIStub::registerUIHook(std::string e, ICallBack *cb, void *userdat){} +int qmpPluginAPIStub::registerUIHook(std::string e, ICallBack *cb, void *userdat) {} int qmpPluginAPIStub::registerUIHook(std::string e, callback_t cb, void *userdat) { - if(e=="main.start") - core->startcb=cb; - if(e=="main.reset") - core->resetcb=cb; - return 0; + if (e == "main.start") + core->startcb = cb; + if (e == "main.reset") + core->resetcb = cb; + return 0; } void qmpPluginAPIStub::unregisterUIHook(std::string e, int hook) { - if(e=="main.start") - core->startcb=nullptr; - if(e=="main.reset") - core->resetcb=nullptr; + if (e == "main.start") + core->startcb = nullptr; + if (e == "main.reset") + core->resetcb = nullptr; } -void qmpPluginAPIStub::registerMidiOutDevice(qmpMidiOutDevice *dev, std::string name){} -void qmpPluginAPIStub::unregisterMidiOutDevice(std::string name){} +void qmpPluginAPIStub::registerMidiOutDevice(qmpMidiOutDevice *dev, std::string name) {} +void qmpPluginAPIStub::unregisterMidiOutDevice(std::string name) {} -int qmpPluginAPIStub::registerEventReaderIntf(ICallBack *cb, void *userdata){} -void qmpPluginAPIStub::unregisterEventReaderIntf(int intfhandle){} -int qmpPluginAPIStub::registerEventHandlerIntf(ICallBack *cb, void *userdata){} -void qmpPluginAPIStub::unregisterEventHandlerIntf(int intfhandle){} -int qmpPluginAPIStub::registerFileReadFinishedHandlerIntf(ICallBack *cb, void *userdata){} -void qmpPluginAPIStub::unregisterFileReadFinishedHandlerIntf(int intfhandle){} +int qmpPluginAPIStub::registerEventReaderIntf(ICallBack *cb, void *userdata) {} +void qmpPluginAPIStub::unregisterEventReaderIntf(int intfhandle) {} +int qmpPluginAPIStub::registerEventHandlerIntf(ICallBack *cb, void *userdata) {} +void qmpPluginAPIStub::unregisterEventHandlerIntf(int intfhandle) {} +int qmpPluginAPIStub::registerFileReadFinishedHandlerIntf(ICallBack *cb, void *userdata) {} +void qmpPluginAPIStub::unregisterFileReadFinishedHandlerIntf(int intfhandle) {} -int qmpPluginAPIStub::registerEventHandler(callback_t cb, void *userdata, bool post){} -void qmpPluginAPIStub::unregisterEventHandler(int id){} +int qmpPluginAPIStub::registerEventHandler(callback_t cb, void *userdata, bool post) {} +void qmpPluginAPIStub::unregisterEventHandler(int id) {} int qmpPluginAPIStub::registerEventReadHandler(callback_t cb, void *userdata) { - return core->player->registerEventReadHandler(cb,userdata); + return core->player->registerEventReadHandler(cb, userdata); } void qmpPluginAPIStub::unregisterEventReadHandler(int id) { - core->player->unregisterEventReadHandler(id); + core->player->unregisterEventReadHandler(id); } int qmpPluginAPIStub::registerFileReadFinishHook(callback_t cb, void *userdata) { - return core->player->registerFileReadFinishHook(cb,userdata); + return core->player->registerFileReadFinishHook(cb, userdata); } void qmpPluginAPIStub::unregisterFileReadFinishHook(int id) { - core->player->unregisterFileReadFinishHook(id); + core->player->unregisterFileReadFinishHook(id); } -void qmpPluginAPIStub::registerFileReader(qmpFileReader *reader, std::string name){} -void qmpPluginAPIStub::unregisterFileReader(std::string name){} +void qmpPluginAPIStub::registerFileReader(qmpFileReader *reader, std::string name) {} +void qmpPluginAPIStub::unregisterFileReader(std::string name) {} void qmpPluginAPIStub::registerOptionInt(std::string tab, std::string desc, std::string key, int min, int max, int defaultval) { - core->settings()->registerOptionInt(tab,desc,key,min,max,defaultval); + core->settings()->registerOptionInt(tab, desc, key, min, max, defaultval); } int qmpPluginAPIStub::getOptionInt(std::string key) { - return core->settings()->getOptionInt(key); + return core->settings()->getOptionInt(key); } void qmpPluginAPIStub::setOptionInt(std::string key, int val) { - core->settings()->setOptionInt(key,val); + core->settings()->setOptionInt(key, val); } void qmpPluginAPIStub::registerOptionUint(std::string tab, std::string desc, std::string key, unsigned min, unsigned max, unsigned defaultval) { - core->settings()->registerOptionUint(tab,desc,key,min,max,defaultval); + core->settings()->registerOptionUint(tab, desc, key, min, max, defaultval); } unsigned qmpPluginAPIStub::getOptionUint(std::string key) { - return core->settings()->getOptionUint(key); + return core->settings()->getOptionUint(key); } void qmpPluginAPIStub::setOptionUint(std::string key, unsigned val) { - return core->settings()->setOptionUint(key,val); + return core->settings()->setOptionUint(key, val); } void qmpPluginAPIStub::registerOptionBool(std::string tab, std::string desc, std::string key, bool defaultval) { - core->settings()->registerOptionBool(tab,desc,key,defaultval); + core->settings()->registerOptionBool(tab, desc, key, defaultval); } bool qmpPluginAPIStub::getOptionBool(std::string key) { - return core->settings()->getOptionBool(key); + return core->settings()->getOptionBool(key); } void qmpPluginAPIStub::setOptionBool(std::string key, bool val) { - core->settings()->setOptionBool(key,val); + core->settings()->setOptionBool(key, val); } void qmpPluginAPIStub::registerOptionDouble(std::string tab, std::string desc, std::string key, double min, double max, double defaultval) { - core->settings()->registerOptionDouble(tab,desc,key,min,max,defaultval); + core->settings()->registerOptionDouble(tab, desc, key, min, max, defaultval); } double qmpPluginAPIStub::getOptionDouble(std::string key) { - return core->settings()->getOptionDouble(key); + return core->settings()->getOptionDouble(key); } void qmpPluginAPIStub::setOptionDouble(std::string key, double val) { - core->settings()->setOptionDouble(key,val); + core->settings()->setOptionDouble(key, val); } void qmpPluginAPIStub::registerOptionString(std::string tab, std::string desc, std::string key, std::string defaultval, bool ispath) { - core->settings()->registerOptionString(tab,desc,key,defaultval,ispath); + core->settings()->registerOptionString(tab, desc, key, defaultval, ispath); } std::string qmpPluginAPIStub::getOptionString(std::string key) { - return core->settings()->getOptionString(key); + return core->settings()->getOptionString(key); } void qmpPluginAPIStub::setOptionString(std::string key, std::string val) { - core->settings()->setOptionString(key,val); + core->settings()->setOptionString(key, val); } void qmpPluginAPIStub::registerOptionEnumInt(std::string tab, std::string desc, std::string key, std::vector options, int defaultval) { - core->settings()->registerOptionEnumInt(tab,desc,key,options,defaultval); + core->settings()->registerOptionEnumInt(tab, desc, key, options, defaultval); } int qmpPluginAPIStub::getOptionEnumInt(std::string key) { - return core->settings()->getOptionEnumInt(key); + return core->settings()->getOptionEnumInt(key); } void qmpPluginAPIStub::setOptionEnumInt(std::string key, int val) { - core->settings()->setOptionEnumInt(key,val); + core->settings()->setOptionEnumInt(key, val); } diff --git a/visualization/renderer/qmppluginapistub.hpp b/visualization/renderer/qmppluginapistub.hpp index d96cfca..4a9024d 100644 --- a/visualization/renderer/qmppluginapistub.hpp +++ b/visualization/renderer/qmppluginapistub.hpp @@ -4,82 +4,82 @@ #include "qmpcorepublic.hpp" class qmpVisRenderCore; -class qmpPluginAPIStub:public qmpPluginAPI +class qmpPluginAPIStub: public qmpPluginAPI { public: - qmpPluginAPIStub(qmpVisRenderCore *_core); - ~qmpPluginAPIStub(); - uint32_t getDivision(); - uint32_t getRawTempo(); - double getRealTempo(); - uint32_t getTimeSig(); - int getKeySig(); - uint32_t getNoteCount(); - uint32_t getMaxTick(); - uint32_t getCurrentPolyphone(); - uint32_t getMaxPolyphone(); - uint32_t getCurrentTimeStamp(); - uint32_t getCurrentPlaybackPercentage(); - int getChannelCC(int ch,int cc); - int getChannelPreset(int ch); - void playerSeek(uint32_t percentage); - double getPitchBend(int ch); - void getPitchBendRaw(int ch,uint32_t *pb,uint32_t *pbr); - bool getChannelMask(int ch); - std::string getTitle(); - std::wstring getWTitle(); - std::string getChannelPresetString(int ch); - bool isDarkTheme(); - void* getMainWindow(); + qmpPluginAPIStub(qmpVisRenderCore *_core); + ~qmpPluginAPIStub(); + uint32_t getDivision(); + uint32_t getRawTempo(); + double getRealTempo(); + uint32_t getTimeSig(); + int getKeySig(); + uint32_t getNoteCount(); + uint32_t getMaxTick(); + uint32_t getCurrentPolyphone(); + uint32_t getMaxPolyphone(); + uint32_t getCurrentTimeStamp(); + uint32_t getCurrentPlaybackPercentage(); + int getChannelCC(int ch, int cc); + int getChannelPreset(int ch); + void playerSeek(uint32_t percentage); + double getPitchBend(int ch); + void getPitchBendRaw(int ch, uint32_t *pb, uint32_t *pbr); + bool getChannelMask(int ch); + std::string getTitle(); + std::wstring getWTitle(); + std::string getChannelPresetString(int ch); + bool isDarkTheme(); + void *getMainWindow(); - void discardCurrentEvent(); - void commitEventChange(SEvent d); - void callEventReaderCB(SEvent d); - void setFuncState(std::string name,bool state); - void setFuncEnabled(std::string name,bool enable); + void discardCurrentEvent(); + void commitEventChange(SEvent d); + void callEventReaderCB(SEvent d); + void setFuncState(std::string name, bool state); + void setFuncEnabled(std::string name, bool enable); - void registerFunctionality(qmpFuncBaseIntf* i,std::string name,std::string desc,const char* icon,int iconlen,bool checkable); - void unregisterFunctionality(std::string name); - int registerUIHook(std::string e,ICallBack* cb,void* userdat); - int registerUIHook(std::string e,callback_t cb,void* userdat); - void unregisterUIHook(std::string e,int hook); - void registerMidiOutDevice(qmpMidiOutDevice* dev,std::string name); - void unregisterMidiOutDevice(std::string name); - int registerEventReaderIntf(ICallBack* cb,void* userdata); - void unregisterEventReaderIntf(int intfhandle); - int registerEventHandlerIntf(ICallBack* cb,void* userdata); - void unregisterEventHandlerIntf(int intfhandle); - int registerFileReadFinishedHandlerIntf(ICallBack* cb,void* userdata); - void unregisterFileReadFinishedHandlerIntf(int intfhandle); - int registerEventHandler(callback_t cb,void *userdata,bool post=false); - void unregisterEventHandler(int id); - int registerEventReadHandler(callback_t cb,void *userdata); - void unregisterEventReadHandler(int id); - int registerFileReadFinishHook(callback_t cb,void *userdata); - void unregisterFileReadFinishHook(int id); - void registerFileReader(qmpFileReader* reader,std::string name); - void unregisterFileReader(std::string name); + void registerFunctionality(qmpFuncBaseIntf *i, std::string name, std::string desc, const char *icon, int iconlen, bool checkable); + void unregisterFunctionality(std::string name); + int registerUIHook(std::string e, ICallBack *cb, void *userdat); + int registerUIHook(std::string e, callback_t cb, void *userdat); + void unregisterUIHook(std::string e, int hook); + void registerMidiOutDevice(qmpMidiOutDevice *dev, std::string name); + void unregisterMidiOutDevice(std::string name); + int registerEventReaderIntf(ICallBack *cb, void *userdata); + void unregisterEventReaderIntf(int intfhandle); + int registerEventHandlerIntf(ICallBack *cb, void *userdata); + void unregisterEventHandlerIntf(int intfhandle); + int registerFileReadFinishedHandlerIntf(ICallBack *cb, void *userdata); + void unregisterFileReadFinishedHandlerIntf(int intfhandle); + int registerEventHandler(callback_t cb, void *userdata, bool post = false); + void unregisterEventHandler(int id); + int registerEventReadHandler(callback_t cb, void *userdata); + void unregisterEventReadHandler(int id); + int registerFileReadFinishHook(callback_t cb, void *userdata); + void unregisterFileReadFinishHook(int id); + void registerFileReader(qmpFileReader *reader, std::string name); + void unregisterFileReader(std::string name); - void registerOptionInt(std::string tab,std::string desc,std::string key,int min,int max,int defaultval); - int getOptionInt(std::string key); - void setOptionInt(std::string key,int val); - void registerOptionUint(std::string tab,std::string desc,std::string key,unsigned min,unsigned max,unsigned defaultval); - unsigned getOptionUint(std::string key); - void setOptionUint(std::string key,unsigned val); - void registerOptionBool(std::string tab,std::string desc,std::string key,bool defaultval); - bool getOptionBool(std::string key); - void setOptionBool(std::string key,bool val); - void registerOptionDouble(std::string tab,std::string desc,std::string key,double min,double max,double defaultval); - double getOptionDouble(std::string key); - void setOptionDouble(std::string key,double val); - void registerOptionString(std::string tab,std::string desc,std::string key,std::string defaultval,bool ispath=false); - std::string getOptionString(std::string key); - void setOptionString(std::string key,std::string val); - void registerOptionEnumInt(std::string tab,std::string desc,std::string key,std::vector options,int defaultval); - int getOptionEnumInt(std::string key); - void setOptionEnumInt(std::string key,int val); + void registerOptionInt(std::string tab, std::string desc, std::string key, int min, int max, int defaultval); + int getOptionInt(std::string key); + void setOptionInt(std::string key, int val); + void registerOptionUint(std::string tab, std::string desc, std::string key, unsigned min, unsigned max, unsigned defaultval); + unsigned getOptionUint(std::string key); + void setOptionUint(std::string key, unsigned val); + void registerOptionBool(std::string tab, std::string desc, std::string key, bool defaultval); + bool getOptionBool(std::string key); + void setOptionBool(std::string key, bool val); + void registerOptionDouble(std::string tab, std::string desc, std::string key, double min, double max, double defaultval); + double getOptionDouble(std::string key); + void setOptionDouble(std::string key, double val); + void registerOptionString(std::string tab, std::string desc, std::string key, std::string defaultval, bool ispath = false); + std::string getOptionString(std::string key); + void setOptionString(std::string key, std::string val); + void registerOptionEnumInt(std::string tab, std::string desc, std::string key, std::vector options, int defaultval); + int getOptionEnumInt(std::string key); + void setOptionEnumInt(std::string key, int val); private: - qmpVisRenderCore* core; + qmpVisRenderCore *core; }; #endif // QMPPLUGINAPISTUB_HPP diff --git a/visualization/renderer/qmpsettingsro.cpp b/visualization/renderer/qmpsettingsro.cpp index 034f073..67dc257 100644 --- a/visualization/renderer/qmpsettingsro.cpp +++ b/visualization/renderer/qmpsettingsro.cpp @@ -9,218 +9,218 @@ qmpSettingsRO::qmpSettingsRO() { } -void qmpSettingsRO::registerOptionInt(std::string tab,std::string desc,std::string key,int min,int max,int defaultval) +void qmpSettingsRO::registerOptionInt(std::string tab, std::string desc, std::string key, int min, int max, int defaultval) { - Q_UNUSED(tab) - optionlist.push_back(key); - options[key]=qmpOptionR(desc,qmpOptionR::ParameterType::parameter_int,defaultval,min,max); + Q_UNUSED(tab) + optionlist.push_back(key); + options[key] = qmpOptionR(desc, qmpOptionR::ParameterType::parameter_int, defaultval, min, max); } int qmpSettingsRO::getOptionInt(std::string key) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_int) - return settings.value(QString(key.c_str()),options[key].defaultval).toInt(); - return options[key].defaultval.toInt(); + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_int) + return settings.value(QString(key.c_str()), options[key].defaultval).toInt(); + return options[key].defaultval.toInt(); } -void qmpSettingsRO::setOptionInt(std::string key,int val) +void qmpSettingsRO::setOptionInt(std::string key, int val) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_int) - settings.insert(QString(key.c_str()),val); + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_int) + settings.insert(QString(key.c_str()), val); } -void qmpSettingsRO::registerOptionUint(std::string tab,std::string desc,std::string key,unsigned min,unsigned max,unsigned defaultval) +void qmpSettingsRO::registerOptionUint(std::string tab, std::string desc, std::string key, unsigned min, unsigned max, unsigned defaultval) { - Q_UNUSED(tab) - optionlist.push_back(key); - options[key]=qmpOptionR(desc,qmpOptionR::ParameterType::parameter_uint,defaultval,min,max); + Q_UNUSED(tab) + optionlist.push_back(key); + options[key] = qmpOptionR(desc, qmpOptionR::ParameterType::parameter_uint, defaultval, min, max); } unsigned qmpSettingsRO::getOptionUint(std::string key) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_uint) - return settings.value(QString(key.c_str()),options[key].defaultval).toUInt(); - return options[key].defaultval.toUInt(); + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_uint) + return settings.value(QString(key.c_str()), options[key].defaultval).toUInt(); + return options[key].defaultval.toUInt(); } -void qmpSettingsRO::setOptionUint(std::string key,unsigned val) +void qmpSettingsRO::setOptionUint(std::string key, unsigned val) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_uint) - settings.insert(QString(key.c_str()),val); + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_uint) + settings.insert(QString(key.c_str()), val); } -void qmpSettingsRO::registerOptionBool(std::string tab,std::string desc,std::string key,bool defaultval) +void qmpSettingsRO::registerOptionBool(std::string tab, std::string desc, std::string key, bool defaultval) { - Q_UNUSED(tab) - optionlist.push_back(key); - options[key]=qmpOptionR(desc,qmpOptionR::ParameterType::parameter_bool,defaultval); + Q_UNUSED(tab) + optionlist.push_back(key); + options[key] = qmpOptionR(desc, qmpOptionR::ParameterType::parameter_bool, defaultval); } bool qmpSettingsRO::getOptionBool(std::string key) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_bool) - return settings.value(QString(key.c_str()),options[key].defaultval).toBool(); - return options[key].defaultval.toBool(); + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_bool) + return settings.value(QString(key.c_str()), options[key].defaultval).toBool(); + return options[key].defaultval.toBool(); } -void qmpSettingsRO::setOptionBool(std::string key,bool val) +void qmpSettingsRO::setOptionBool(std::string key, bool val) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_bool) - settings.insert(QString(key.c_str()),val); + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_bool) + settings.insert(QString(key.c_str()), val); } -void qmpSettingsRO::registerOptionDouble(std::string tab,std::string desc,std::string key,double min,double max,double defaultval) +void qmpSettingsRO::registerOptionDouble(std::string tab, std::string desc, std::string key, double min, double max, double defaultval) { - Q_UNUSED(tab) - optionlist.push_back(key); - options[key]=qmpOptionR(desc,qmpOptionR::ParameterType::parameter_double,defaultval,min,max); + Q_UNUSED(tab) + optionlist.push_back(key); + options[key] = qmpOptionR(desc, qmpOptionR::ParameterType::parameter_double, defaultval, min, max); } double qmpSettingsRO::getOptionDouble(std::string key) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_double) - return settings.value(QString(key.c_str()),options[key].defaultval).toDouble(); - return options[key].defaultval.toDouble(); + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_double) + return settings.value(QString(key.c_str()), options[key].defaultval).toDouble(); + return options[key].defaultval.toDouble(); } -void qmpSettingsRO::setOptionDouble(std::string key,double val) +void qmpSettingsRO::setOptionDouble(std::string key, double val) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_double) - settings.insert(QString(key.c_str()),val); + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_double) + settings.insert(QString(key.c_str()), val); } -void qmpSettingsRO::registerOptionString(std::string tab,std::string desc,std::string key,std::string defaultval,bool is_url) +void qmpSettingsRO::registerOptionString(std::string tab, std::string desc, std::string key, std::string defaultval, bool is_url) { - Q_UNUSED(tab) - optionlist.push_back(key); - options[key]=qmpOptionR(desc, - is_url?qmpOptionR::ParameterType::parameter_url:qmpOptionR::ParameterType::parameter_str, - QString(defaultval.c_str())); + Q_UNUSED(tab) + optionlist.push_back(key); + options[key] = qmpOptionR(desc, + is_url ? qmpOptionR::ParameterType::parameter_url : qmpOptionR::ParameterType::parameter_str, + QString(defaultval.c_str())); } std::string qmpSettingsRO::getOptionString(std::string key) { - if(options.find(key)!=options.end()&& - (options[key].type==qmpOptionR::ParameterType::parameter_str||options[key].type==qmpOptionR::ParameterType::parameter_url)) - return settings.value(QString(key.c_str()),options[key].defaultval).toString().toStdString(); - return options[key].defaultval.toString().toStdString(); + if (options.find(key) != options.end() && + (options[key].type == qmpOptionR::ParameterType::parameter_str || options[key].type == qmpOptionR::ParameterType::parameter_url)) + return settings.value(QString(key.c_str()), options[key].defaultval).toString().toStdString(); + return options[key].defaultval.toString().toStdString(); } -void qmpSettingsRO::setOptionString(std::string key,std::string val) +void qmpSettingsRO::setOptionString(std::string key, std::string val) { - if(options.find(key)!=options.end()&& - (options[key].type==qmpOptionR::ParameterType::parameter_str||options[key].type==qmpOptionR::ParameterType::parameter_url)) - settings.insert(QString(key.c_str()),QString(val.c_str())); + if (options.find(key) != options.end() && + (options[key].type == qmpOptionR::ParameterType::parameter_str || options[key].type == qmpOptionR::ParameterType::parameter_url)) + settings.insert(QString(key.c_str()), QString(val.c_str())); } -void qmpSettingsRO::registerOptionEnumInt(std::string tab,std::string desc,std::string key,std::vector enumlist,int defaultval) +void qmpSettingsRO::registerOptionEnumInt(std::string tab, std::string desc, std::string key, std::vector enumlist, int defaultval) { - Q_UNUSED(tab) - optionlist.push_back(key); - options[key]=qmpOptionR(desc,qmpOptionR::ParameterType::parameter_enum,defaultval); - options[key].enumlist=enumlist; + Q_UNUSED(tab) + optionlist.push_back(key); + options[key] = qmpOptionR(desc, qmpOptionR::ParameterType::parameter_enum, defaultval); + options[key].enumlist = enumlist; } int qmpSettingsRO::getOptionEnumInt(std::string key) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_enum) - { - std::string curitm=settings.value(QString(key.c_str()),options[key].defaultval).toString().toStdString(); - auto curidx=std::find(options[key].enumlist.begin(),options[key].enumlist.end(),curitm); - if(curidx!=options[key].enumlist.end()) - return static_cast(curidx-options[key].enumlist.begin()); - else - { - return options[key].defaultval.toInt(); - } - } - return options[key].defaultval.toInt(); + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_enum) + { + std::string curitm = settings.value(QString(key.c_str()), options[key].defaultval).toString().toStdString(); + auto curidx = std::find(options[key].enumlist.begin(), options[key].enumlist.end(), curitm); + if (curidx != options[key].enumlist.end()) + return static_cast(curidx - options[key].enumlist.begin()); + else + { + return options[key].defaultval.toInt(); + } + } + return options[key].defaultval.toInt(); } std::string qmpSettingsRO::getOptionEnumIntOptName(std::string key) { - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_enum) - { - std::string curitm=settings.value(QString(key.c_str()),options[key].defaultval).toString().toStdString(); - auto curidx=std::find(options[key].enumlist.begin(),options[key].enumlist.end(),curitm); - if(curidx!=options[key].enumlist.end()) - return curitm; - else - { - return options[key].enumlist[static_cast(options[key].defaultval.toInt())]; - } - } - return options[key].enumlist[static_cast(options[key].defaultval.toInt())]; -} -void qmpSettingsRO::setOptionEnumInt(std::string key,int val) -{ - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_enum) - { - if(static_cast(val)(val)].c_str())); - } -} -void qmpSettingsRO::setOptionEnumIntOptName(std::string key,std::string valname) -{ - if(options.find(key)!=options.end()&&options[key].type==qmpOptionR::ParameterType::parameter_enum) - { - auto curidx=std::find(options[key].enumlist.begin(),options[key].enumlist.end(),valname); - if(curidx!=options[key].enumlist.end()) - settings.insert(QString(key.c_str()),QString(valname.c_str())); - } + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_enum) + { + std::string curitm = settings.value(QString(key.c_str()), options[key].defaultval).toString().toStdString(); + auto curidx = std::find(options[key].enumlist.begin(), options[key].enumlist.end(), curitm); + if (curidx != options[key].enumlist.end()) + return curitm; + else + { + return options[key].enumlist[static_cast(options[key].defaultval.toInt())]; + } + } + return options[key].enumlist[static_cast(options[key].defaultval.toInt())]; +} +void qmpSettingsRO::setOptionEnumInt(std::string key, int val) +{ + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_enum) + { + if (static_cast(val) < options[key].enumlist.size()) + settings.insert(QString(key.c_str()), QString(options[key].enumlist[static_cast(val)].c_str())); + } +} +void qmpSettingsRO::setOptionEnumIntOptName(std::string key, std::string valname) +{ + if (options.find(key) != options.end() && options[key].type == qmpOptionR::ParameterType::parameter_enum) + { + auto curidx = std::find(options[key].enumlist.begin(), options[key].enumlist.end(), valname); + if (curidx != options[key].enumlist.end()) + settings.insert(QString(key.c_str()), QString(valname.c_str())); + } } void qmpSettingsRO::load(const char *path) { - QScopedPointer qsettings(new QSettings(path,QSettings::Format::IniFormat)); - settings.clear(); - for(QString&k:qsettings->allKeys()) - { - settings.insert(k,qsettings->value(k)); - } + QScopedPointer qsettings(new QSettings(path, QSettings::Format::IniFormat)); + settings.clear(); + for (QString &k : qsettings->allKeys()) + { + settings.insert(k, qsettings->value(k)); + } } void qmpSettingsRO::setopt(std::string key, std::string val) { - settings.insert(QString(key.c_str()),QString(val.c_str())); - if(key.find("Visualization/")!=0) - settings.insert("Visualization/"+QString(key.c_str()),QString(val.c_str())); + settings.insert(QString(key.c_str()), QString(val.c_str())); + if (key.find("Visualization/") != 0) + settings.insert("Visualization/" + QString(key.c_str()), QString(val.c_str())); } void qmpSettingsRO::listopt() { - for(auto&k:optionlist) - { - printf("Option key: %s\n",k.c_str()); - if(options[k].desc.length()) - printf("Description: %s\n",options[k].desc.c_str()); - switch(options[k].type) - { - case qmpOptionR::ParameterType::parameter_int: - printf("Type: int\n"); - printf("Range: [%d,%d]\n",options[k].minv.toInt(),options[k].maxv.toInt()); - printf("Default value: %d\n",options[k].defaultval.toInt()); - break; - case qmpOptionR::ParameterType::parameter_uint: - printf("Type: uint\n"); - printf("Range: [%u,%u]\n",options[k].minv.toUInt(),options[k].maxv.toUInt()); - printf("Default value: %u\n",options[k].defaultval.toUInt()); - break; - case qmpOptionR::ParameterType::parameter_double: - printf("Type: double\n"); - printf("Range: [%.2f,%.2f]\n",options[k].minv.toDouble(),options[k].maxv.toDouble()); - printf("Default value: %.f2\n",options[k].defaultval.toDouble()); - break; - case qmpOptionR::ParameterType::parameter_bool: - printf("Type: bool\n"); - printf("Default value: %s\n",options[k].defaultval.toBool()?"true":"false"); - break; - case qmpOptionR::ParameterType::parameter_str: - printf("Type: str\n"); - printf("Default value: %s\n",options[k].defaultval.toString().toStdString().c_str()); - break; - case qmpOptionR::ParameterType::parameter_url: - printf("Type: url\n"); - printf("Default value: %s\n",options[k].defaultval.toString().toStdString().c_str()); - break; - case qmpOptionR::ParameterType::parameter_enum: - printf("Type: enum\n"); - printf("Possible values: "); - for(size_t i=0;i enumlist; + std::string desc; + ParameterType type; + QVariant defaultval, minv, maxv; + std::vector enumlist; - qmpOptionR(){} - qmpOptionR( - std::string _desc, - ParameterType _t,QVariant _def=QVariant(), - QVariant _min=QVariant(),QVariant _max=QVariant()): - desc(_desc), - type(_t), - defaultval(_def), - minv(_min), - maxv(_max){} + qmpOptionR() {} + qmpOptionR( + std::string _desc, + ParameterType _t, QVariant _def = QVariant(), + QVariant _min = QVariant(), QVariant _max = QVariant()): + desc(_desc), + type(_t), + defaultval(_def), + minv(_min), + maxv(_max) {} }; class qmpSettingsRO { public: - qmpSettingsRO(); - void registerOptionInt(std::string tab,std::string desc,std::string key,int min,int max,int defaultval); - int getOptionInt(std::string key); - void setOptionInt(std::string key,int val); - void registerOptionUint(std::string tab,std::string desc,std::string key,unsigned min,unsigned max,unsigned defaultval); - unsigned getOptionUint(std::string key); - void setOptionUint(std::string key,unsigned val); - void registerOptionBool(std::string tab,std::string desc,std::string key,bool defaultval); - bool getOptionBool(std::string key); - void setOptionBool(std::string key,bool val); - void registerOptionDouble(std::string tab,std::string desc,std::string key,double min,double max,double defaultval); - double getOptionDouble(std::string key); - void setOptionDouble(std::string key,double val); - void registerOptionString(std::string tab,std::string desc,std::string key,std::string defaultval,bool is_url); - std::string getOptionString(std::string key); - void setOptionString(std::string key,std::string val); - void registerOptionEnumInt(std::string tab,std::string desc,std::string key,std::vector enumlist,int defaultval); - int getOptionEnumInt(std::string key); - std::string getOptionEnumIntOptName(std::string key); - void setOptionEnumInt(std::string key,int val); - void setOptionEnumIntOptName(std::string key,std::string valname); + qmpSettingsRO(); + void registerOptionInt(std::string tab, std::string desc, std::string key, int min, int max, int defaultval); + int getOptionInt(std::string key); + void setOptionInt(std::string key, int val); + void registerOptionUint(std::string tab, std::string desc, std::string key, unsigned min, unsigned max, unsigned defaultval); + unsigned getOptionUint(std::string key); + void setOptionUint(std::string key, unsigned val); + void registerOptionBool(std::string tab, std::string desc, std::string key, bool defaultval); + bool getOptionBool(std::string key); + void setOptionBool(std::string key, bool val); + void registerOptionDouble(std::string tab, std::string desc, std::string key, double min, double max, double defaultval); + double getOptionDouble(std::string key); + void setOptionDouble(std::string key, double val); + void registerOptionString(std::string tab, std::string desc, std::string key, std::string defaultval, bool is_url); + std::string getOptionString(std::string key); + void setOptionString(std::string key, std::string val); + void registerOptionEnumInt(std::string tab, std::string desc, std::string key, std::vector enumlist, int defaultval); + int getOptionEnumInt(std::string key); + std::string getOptionEnumIntOptName(std::string key); + void setOptionEnumInt(std::string key, int val); + void setOptionEnumIntOptName(std::string key, std::string valname); - void load(const char* path); - void setopt(std::string key,std::string val); - void listopt(); + void load(const char *path); + void setopt(std::string key, std::string val); + void listopt(); private: - std::map options; - std::vector optionlist; - QVariantMap settings; + std::map options; + std::vector optionlist; + QVariantMap settings; }; #endif diff --git a/visualization/renderer/qmpvisrendercore.cpp b/visualization/renderer/qmpvisrendercore.cpp index b12ed91..9d58206 100644 --- a/visualization/renderer/qmpvisrendercore.cpp +++ b/visualization/renderer/qmpvisrendercore.cpp @@ -19,262 +19,271 @@ #include #include #include -qmpVisRenderCore *qmpVisRenderCore::inst=nullptr; +qmpVisRenderCore *qmpVisRenderCore::inst = nullptr; -qmpVisRenderCore::qmpVisRenderCore(QCommandLineParser *_clp):QObject(nullptr),clp(_clp) +qmpVisRenderCore::qmpVisRenderCore(QCommandLineParser *_clp): QObject(nullptr), clp(_clp) { - inst=this; - player=new CMidiPlayer(); - api=new qmpPluginAPIStub(this); - msettings=new qmpSettingsRO(); - frameno=0; - msettings->registerOptionEnumInt("MIDI","Text encoding","Midi/TextEncoding",{"Unicode","Big5","Big5-HKSCS","CP949","EUC-JP","EUC-KR","GB18030","KOI8-R","KOI8-U","Macintosh","Shift-JIS"},0); + inst = this; + player = new CMidiPlayer(); + api = new qmpPluginAPIStub(this); + msettings = new qmpSettingsRO(); + frameno = 0; + msettings->registerOptionEnumInt("MIDI", "Text encoding", "Midi/TextEncoding", {"Unicode", "Big5", "Big5-HKSCS", "CP949", "EUC-JP", "EUC-KR", "GB18030", "KOI8-R", "KOI8-U", "Macintosh", "Shift-JIS"}, 0); } bool qmpVisRenderCore::loadVisualizationLibrary() { #ifdef _WIN32 - std::vector libpath={ - QCoreApplication::applicationDirPath().toStdWString()+L"/plugins/libvisualization.dll", - L"libvisualization.dll", - L"../libvisualization.dll"//for debugging only...? - }; + std::vector libpath = + { + QCoreApplication::applicationDirPath().toStdWString() + L"/plugins/libvisualization.dll", + L"libvisualization.dll", + L"../libvisualization.dll"//for debugging only...? + }; #else - std::vector libpath={ - QCoreApplication::applicationDirPath().toStdString()+"/plugins/libvisualization.so", - QT_STRINGIFY(INSTALL_PREFIX)+std::string("/lib/qmidiplayer/libvisualization.so"), - "../libvisualization.so"//for debugging only - }; + std::vector libpath = + { + QCoreApplication::applicationDirPath().toStdString() + "/plugins/libvisualization.so", + QT_STRINGIFY(INSTALL_PREFIX) + std::string("/lib/qmidiplayer/libvisualization.so"), + "../libvisualization.so"//for debugging only + }; #endif - for(auto&l:libpath) - { - mp=dlopen(l.c_str(),RTLD_LAZY); - if(mp)break; - } - if(!mp) - { - fprintf(stderr,"failed to load the visualization module!\n"); - return false; - } - GetInterface_func getintf=reinterpret_cast(dlsym(mp,"qmpPluginGetInterface")); - SwitchMode_func switchmode=reinterpret_cast(dlsym(mp,"switchToRenderMode")); - vf=nullptr; - vp=getintf(api); - switchmode(&qmpVisRenderCore::framefunc,!clp->isSet("show-window")); - vp->init(); - resetcb(nullptr,nullptr); - if(clp->isSet("list-options")) - { - msettings->listopt(); - exit(0); - } - return true; + for (auto &l : libpath) + { + mp = dlopen(l.c_str(), RTLD_LAZY); + if (mp) + break; + } + if (!mp) + { + fprintf(stderr, "failed to load the visualization module!\n"); + return false; + } + GetInterface_func getintf = reinterpret_cast(dlsym(mp, "qmpPluginGetInterface")); + SwitchMode_func switchmode = reinterpret_cast(dlsym(mp, "switchToRenderMode")); + vf = nullptr; + vp = getintf(api); + switchmode(&qmpVisRenderCore::framefunc, !clp->isSet("show-window")); + vp->init(); + resetcb(nullptr, nullptr); + if (clp->isSet("list-options")) + { + msettings->listopt(); + exit(0); + } + return true; } void qmpVisRenderCore::unloadVisualizationLibrary() { - vp->deinit(); - dlclose(mp); + vp->deinit(); + dlclose(mp); } void qmpVisRenderCore::loadSettings() { - if(clp->isSet("config")) - msettings->load(clp->value("config").toStdString().c_str()); - for(auto &o:clp->values("option")) - { - int sp=o.indexOf('='); - if(!~sp) - { - qDebug("invalid option pair: %s",o.toStdString().c_str()); - continue; - } - QString key=o.left(sp); - QString value=o.mid(sp+1); - msettings->setopt(key.toStdString(),value.toStdString()); - } + if (clp->isSet("config")) + msettings->load(clp->value("config").toStdString().c_str()); + for (auto &o : clp->values("option")) + { + int sp = o.indexOf('='); + if (!~sp) + { + qDebug("invalid option pair: %s", o.toStdString().c_str()); + continue; + } + QString key = o.left(sp); + QString value = o.mid(sp + 1); + msettings->setopt(key.toStdString(), value.toStdString()); + } } void qmpVisRenderCore::setMIDIFile(const char *url) { - player->playerLoadFile(url); + player->playerLoadFile(url); } void qmpVisRenderCore::startRender() { - assert(vf); - subst={ - {'w',QString::number(msettings->getOptionInt("Visualization/wwidth"))}, - {'h',QString::number(msettings->getOptionInt("Visualization/wheight"))}, - {'r',QString::number(msettings->getOptionInt("Visualization/tfps"))}, - {'i', - QStringList() - <<"-f"<<"rawvideo" - <<"-pixel_format"<<"rgba" - <<"-video_size"<getOptionInt("Visualization/wwidth")).arg(msettings->getOptionInt("Visualization/wheight")) - <<"-framerate"<getOptionInt("Visualization/tfps")) - <<"-i"<<"pipe:" - }, - {'o',clp->value("output-file")} - }; - if(clp->value("receiver-execution")=="per-frame") - { - subst['o']=clp->value("output-file").replace("%f",QString("%1").arg(frameno,6,10,QChar('0'))); - oneshot=false; - } - else - { - oneshot=true; - if(clp->value("receiver-execution")!="one-shot") - qWarning("Invalid value set for --receiver-execution. Using default value."); - } - rxproc=new QProcess(); - QStringList arguments=process_arguments(clp->value("receiver"),subst); - assert(arguments.length()>0); - rxproc->setProgram(arguments.front()); - arguments.pop_front(); - rxproc->setArguments(arguments); - frameconn=connect(this,&qmpVisRenderCore::frameRendered,this, - [this](void* px,size_t sz,uint32_t c,uint32_t t) - { - if(sz) - { - if(!oneshot) - { - subst['f']=QString("%1").arg(frameno,6,10,QChar('0')); - subst['o']=clp->value("output-file").replace("%f",QString("%1").arg(frameno,6,10,QChar('0'))); - frameno++; - QStringList arguments=process_arguments(clp->value("receiver"),subst); - arguments.pop_front(); - rxproc->setArguments(arguments); - rxproc->start(); - rxproc->waitForStarted(); - } - if(!rxproc->isOpen())return; - rxproc->write(static_cast(px),static_cast(sz)); - while(rxproc->bytesToWrite()>(oneshot?(1<<26):0)) - rxproc->waitForBytesWritten(); - if(!oneshot) - { - rxproc->closeWriteChannel(); - rxproc->waitForFinished(-1); - } - } - fprintf(stderr,"Rendered tick %u of %u, %.2f%% done.\r",c,t,std::min(100.,100.*c/t)); - if(c>t) - { - this->rxproc->closeWriteChannel(); - disconnect(frameconn); - qApp->exit(0); - } - },Qt::ConnectionType::BlockingQueuedConnection); - connect(rxproc,QOverload::of(&QProcess::finished), - [this](int x,QProcess::ExitStatus st){ - qDebug("%s",this->rxproc->readAllStandardError().data()); - if(oneshot) - { - disconnect(frameconn); - if(x||st==QProcess::ExitStatus::CrashExit) - qApp->exit(1); - else - qApp->exit(0); - } - }); - QMetaObject::invokeMethod(this,[this](){ - if(oneshot) - rxproc->start(); - vf->show(); - startcb(nullptr,nullptr); - },Qt::ConnectionType::QueuedConnection); + assert(vf); + subst = + { + {'w', QString::number(msettings->getOptionInt("Visualization/wwidth"))}, + {'h', QString::number(msettings->getOptionInt("Visualization/wheight"))}, + {'r', QString::number(msettings->getOptionInt("Visualization/tfps"))}, + { + 'i', + QStringList() + << "-f" << "rawvideo" + << "-pixel_format" << "rgba" + << "-video_size" << QString("%1x%2").arg(msettings->getOptionInt("Visualization/wwidth")).arg(msettings->getOptionInt("Visualization/wheight")) + << "-framerate" << QString::number(msettings->getOptionInt("Visualization/tfps")) + << "-i" << "pipe:" + }, + {'o', clp->value("output-file")} + }; + if (clp->value("receiver-execution") == "per-frame") + { + subst['o'] = clp->value("output-file").replace("%f", QString("%1").arg(frameno, 6, 10, QChar('0'))); + oneshot = false; + } + else + { + oneshot = true; + if (clp->value("receiver-execution") != "one-shot") + qWarning("Invalid value set for --receiver-execution. Using default value."); + } + rxproc = new QProcess(); + QStringList arguments = process_arguments(clp->value("receiver"), subst); + assert(arguments.length() > 0); + rxproc->setProgram(arguments.front()); + arguments.pop_front(); + rxproc->setArguments(arguments); + frameconn = connect(this, &qmpVisRenderCore::frameRendered, this, + [this](void *px, size_t sz, uint32_t c, uint32_t t) + { + if (sz) + { + if (!oneshot) + { + subst['f'] = QString("%1").arg(frameno, 6, 10, QChar('0')); + subst['o'] = clp->value("output-file").replace("%f", QString("%1").arg(frameno, 6, 10, QChar('0'))); + frameno++; + QStringList arguments = process_arguments(clp->value("receiver"), subst); + arguments.pop_front(); + rxproc->setArguments(arguments); + rxproc->start(); + rxproc->waitForStarted(); + } + if (!rxproc->isOpen()) + return; + rxproc->write(static_cast(px), static_cast(sz)); + while (rxproc->bytesToWrite() > (oneshot ? (1 << 26) : 0)) + rxproc->waitForBytesWritten(); + if (!oneshot) + { + rxproc->closeWriteChannel(); + rxproc->waitForFinished(-1); + } + } + fprintf(stderr, "Rendered tick %u of %u, %.2f%% done.\r", c, t, std::min(100., 100.*c / t)); + if (c > t) + { + this->rxproc->closeWriteChannel(); + disconnect(frameconn); + qApp->exit(0); + } + }, Qt::ConnectionType::BlockingQueuedConnection); + connect(rxproc, QOverload::of(&QProcess::finished), + [this](int x, QProcess::ExitStatus st) + { + qDebug("%s", this->rxproc->readAllStandardError().data()); + if (oneshot) + { + disconnect(frameconn); + if (x || st == QProcess::ExitStatus::CrashExit) + qApp->exit(1); + else + qApp->exit(0); + } + }); + QMetaObject::invokeMethod(this, [this]() + { + if (oneshot) + rxproc->start(); + vf->show(); + startcb(nullptr, nullptr); + }, Qt::ConnectionType::QueuedConnection); } -QStringList qmpVisRenderCore::process_arguments(QString a,QMap subst) +QStringList qmpVisRenderCore::process_arguments(QString a, QMap subst) { - QStringList ret; - QString buf; - bool escaped=false; - bool substi=false; - for(int i=0;iframeRendered(px,sz,curf,totf); + emit inst->frameRendered(px, sz, curf, totf); } diff --git a/visualization/renderer/qmpvisrendercore.hpp b/visualization/renderer/qmpvisrendercore.hpp index 71eeaed..ba978f4 100644 --- a/visualization/renderer/qmpvisrendercore.hpp +++ b/visualization/renderer/qmpvisrendercore.hpp @@ -15,44 +15,47 @@ class QCommandLineParser; class QProcess; -class qmpVisRenderCore:public QObject +class qmpVisRenderCore: public QObject { - Q_OBJECT + Q_OBJECT public: - qmpVisRenderCore(QCommandLineParser *_clp); - bool loadVisualizationLibrary(); - void unloadVisualizationLibrary(); - void loadSettings(); - void setMIDIFile(const char* url); - void startRender(); - - qmpSettingsRO* settings(){return msettings;} + qmpVisRenderCore(QCommandLineParser *_clp); + bool loadVisualizationLibrary(); + void unloadVisualizationLibrary(); + void loadSettings(); + void setMIDIFile(const char *url); + void startRender(); + + qmpSettingsRO *settings() + { + return msettings; + } signals: - void frameRendered(void* px,size_t sz,uint32_t current_tick,uint32_t total_ticks); + void frameRendered(void *px, size_t sz, uint32_t current_tick, uint32_t total_ticks); private: - qmpPluginIntf *vp; - qmpFuncBaseIntf *vf; - callback_t startcb; - callback_t resetcb; - void *mp; - qmpPluginAPIStub *api; - CMidiPlayer *player; - qmpSettingsRO *msettings; - QProcess *rxproc; - QMap subst; - QCommandLineParser *clp; - QStringList process_arguments(QString a, QMap subst); - int frameno; - bool oneshot; - QMetaObject::Connection frameconn; - typedef qmpPluginIntf*(*GetInterface_func)(qmpPluginAPI*); - typedef void(*SwitchMode_func)(void(*frameCallback)(void*,size_t,uint32_t,uint32_t),bool hidewindow); - - friend class qmpPluginAPIStub; - static void framefunc(void* px, size_t sz, uint32_t curf, uint32_t totf); - static qmpVisRenderCore *inst; + qmpPluginIntf *vp; + qmpFuncBaseIntf *vf; + callback_t startcb; + callback_t resetcb; + void *mp; + qmpPluginAPIStub *api; + CMidiPlayer *player; + qmpSettingsRO *msettings; + QProcess *rxproc; + QMap subst; + QCommandLineParser *clp; + QStringList process_arguments(QString a, QMap subst); + int frameno; + bool oneshot; + QMetaObject::Connection frameconn; + typedef qmpPluginIntf *(*GetInterface_func)(qmpPluginAPI *); + typedef void(*SwitchMode_func)(void(*frameCallback)(void *, size_t, uint32_t, uint32_t), bool hidewindow); + + friend class qmpPluginAPIStub; + static void framefunc(void *px, size_t sz, uint32_t curf, uint32_t totf); + static qmpVisRenderCore *inst; }; #endif // QMPVISRENDERCORE_HPP -- cgit v1.2.3