void SoundplaneZoneView::renderZones() { if (!mpModel) return; const ScopedLock lock(*(mpModel->getZoneLock())); const std::vector<ZonePtr>& zoneList = mpModel->getZones(); int viewW = getBackingLayerWidth(); int viewH = getBackingLayerHeight(); int viewScale = getRenderingScale(); // float viewAspect = (float)viewW / (float)viewH; int gridWidth = 30; // Soundplane A TODO get from tracker int gridHeight = 5; int lineWidth = viewW / 200; int thinLineWidth = viewW / 400; // int margin = lineWidth*2; // put origin in lower left. MLGL::orthoView2(viewW, viewH); MLRange xRange(0, gridWidth, 1, viewW); MLRange yRange(0, gridHeight, 1, viewH); Vec4 lineColor; Vec4 darkBlue(0.3f, 0.3f, 0.5f, 1.f); Vec4 gray(0.6f, 0.6f, 0.6f, 1.f); Vec4 lightGray(0.9f, 0.9f, 0.9f, 1.f); Vec4 blue2(0.1f, 0.1f, 0.5f, 1.f); float smallDotSize = xRange(1.f); // float strokeWidth = viewW / 100; std::vector<ZonePtr>::const_iterator it; for(it = zoneList.begin(); it != zoneList.end(); ++it) { const Zone& zone = **it; int t = zone.getType(); MLRect zr = zone.getBounds(); const char * name = zone.getName().c_str(); int offset = zone.getOffset(); // affine transforms TODO for better syntax: MLRect zrd = zr.xform(gridToView); MLRect zoneRectInView(xRange.convert(zr.x()), yRange.convert(zr.y()), xRange.convert(zr.width()), yRange.convert(zr.height())); zoneRectInView.shrink(lineWidth); // color idx = type + port offset. Vec4 zoneStroke(MLGL::getIndicatorColor(t + offset)); Vec4 zoneFill(zoneStroke); zoneFill[3] = 0.1f; Vec4 activeFill(zoneStroke); activeFill[3] = 0.25f; Vec4 dotFill(zoneStroke); dotFill[3] = 0.5f; // draw box common to all kinds of zones glColor4fv(&zoneFill[0]); MLGL::fillRect(zoneRectInView); glColor4fv(&zoneStroke[0]); glLineWidth(lineWidth); MLGL::strokeRect(zoneRectInView, 2.0f*viewScale); glLineWidth(1); // draw name // all these rect calculations read upside-down here because view origin is at bottom MLGL::drawTextAt(zoneRectInView.left() + lineWidth, zoneRectInView.top() + lineWidth, 0.f, 0.1f, viewScale, name); // draw any zone-specific things float x, y; int toggle; switch(t) { case kNoteRow: for(int i = 0; i < kSoundplaneMaxTouches; ++i) { const ZoneTouch& uTouch = zone.getTouch(i); const ZoneTouch& touch = zone.touchToKeyPos(uTouch); if(touch.isActive()) { glColor4fv(&dotFill[0]); float dx = xRange(touch.pos.x()); float dy = yRange(touch.pos.y()); float dz = touch.pos.z(); MLGL::drawDot(Vec2(dx, dy), dz*smallDotSize); } } break; case kControllerX: x = xRange(zone.getXKeyPos()); glColor4fv(&zoneStroke[0]); glLineWidth(thinLineWidth); MLGL::strokeRect(MLRect(x, zoneRectInView.top(), 0., zoneRectInView.height()), viewScale); glColor4fv(&activeFill[0]); MLGL::fillRect(MLRect(zoneRectInView.left(), zoneRectInView.top(), x - zoneRectInView.left(), zoneRectInView.height())); break; case kControllerY: y = yRange(zone.getYKeyPos()); glColor4fv(&zoneStroke[0]); glLineWidth(thinLineWidth); MLGL::strokeRect(MLRect(zoneRectInView.left(), y, zoneRectInView.width(), 0.), viewScale); glColor4fv(&activeFill[0]); MLGL::fillRect(MLRect(zoneRectInView.left(), zoneRectInView.top(), zoneRectInView.width(), y - zoneRectInView.top())); break; case kControllerXY: x = xRange(zone.getXKeyPos()); y = yRange(zone.getYKeyPos()); glColor4fv(&zoneStroke[0]); glLineWidth(thinLineWidth); // cross-hairs centered on dot MLGL::strokeRect(MLRect(x, zoneRectInView.top(), 0., zoneRectInView.height()), viewScale); MLGL::strokeRect(MLRect(zoneRectInView.left(), y, zoneRectInView.width(), 0.), viewScale); glColor4fv(&dotFill[0]); MLGL::drawDot(Vec2(x, y), smallDotSize*0.25f); break; case kControllerZ: y = yRange(zone.mYRange(zone.getValue(0))); // look at z value over y range glColor4fv(&zoneStroke[0]); glLineWidth(thinLineWidth); MLGL::strokeRect(MLRect(zoneRectInView.left(), y, zoneRectInView.width(), 0.), viewScale); glColor4fv(&activeFill[0]); MLGL::fillRect(MLRect(zoneRectInView.left(), zoneRectInView.top(), zoneRectInView.width(), y - zoneRectInView.top())); break; case kToggle: toggle = zone.getToggleValue(); glColor4fv(&zoneStroke[0]); glLineWidth(thinLineWidth); if(toggle) { MLRect toggleFill = zoneRectInView; Vec2 zoneCenter = zoneRectInView.getCenter(); glColor4fv(&activeFill[0]); MLGL::fillRect(zoneRectInView); glColor4fv(&dotFill[0]); MLGL::drawDot(zoneCenter, smallDotSize*0.25f); } break; } } }
void MLPluginProcessor::getStateAsXML (XmlElement& xml) { if( !(mEngine.getCompileStatus() == MLProc::OK)) return; #if DEMO xml.setAttribute ("pluginVersion", JucePlugin_VersionCode); xml.setAttribute ("presetName", String("----")); #else const unsigned numParams = getNumParameters(); // TODO use string properties of model instead of these JUCE strings. // also move to JSON. xml.setAttribute ("pluginVersion", JucePlugin_VersionCode); xml.setAttribute ("presetName", String(getStringProperty("preset").c_str())); xml.setAttribute ("scaleName", String(getStringProperty("key_scale").c_str())); // store parameter values to xml as a bunch of attributes. // not XML best practice in general but takes fewer characters. for(unsigned i=0; i<numParams; ++i) { const String paramName = symbolToXMLAttr(getParameterAlias(i)); const float defaultVal = getParameterDefault(i); const float paramVal = getParameter(i); if (paramVal != defaultVal) { xml.setAttribute(paramName, paramVal); //debug() << "setting XML param " << paramName << " to " << paramVal << "\n"; } } // store patcher info to xml { MLProcList patchers = getPatcherList(); if (!patchers.empty()) { MLProcPatcher& firstPatcher = static_cast<MLProcPatcher&>(**patchers.begin()); const int inputs = firstPatcher.getParam("inputs"); const int outputs = firstPatcher.getParam("outputs"); String outStr; String patcherInput = "patcher_input_"; for(unsigned i=1; i<=inputs; ++i) { bool differentFromDefault = false; outStr = ""; for(unsigned j=1; j<=outputs; ++j) { if (firstPatcher.getConnection(i, j)) { outStr += "1"; differentFromDefault = true; } else { outStr += "0"; } } if(differentFromDefault) { String outNum (i); xml.setAttribute(patcherInput + outNum, outStr); } } } } // store editor state to XML if one exists MLPluginEditor* pEditor = static_cast<MLPluginEditor*>(getActiveEditor()); if(pEditor) { MLRect r = pEditor->getWindowBounds(); xml.setAttribute("editor_x", r.x()); xml.setAttribute("editor_y", r.y()); xml.setAttribute("editor_width", r.getWidth()); xml.setAttribute("editor_height", r.getHeight()); xml.setAttribute("editor_num", getFloatProperty("patch_num")); xml.setAttribute("editor_anim", getFloatProperty("patch_anim")); } // save blob as most recently saved state mpLatestStateLoaded = XmlElementPtr(new XmlElement(xml)); #endif }