Пример #1
0
// get smallest rect outlining all elements. For now this is different than getLocalBounds, because
// we might want to allow components to draw into the margin within getLocalBounds. 
//  
MLRect MLPositioner::getLocalOutline()
{
//	MLRect out = mBounds - mTopLeft;
//	out.expand(-mElementsMargin*2);
//	return correctRect(out);

	// TEMP works for horiz only
	return MLRect(getElementBounds(0).getTopLeft(), getElementBounds(mElements - 1).getBottomRight());
}
Пример #2
0
MLAppView* MLPageView::addPage(MLAppView* newPage)
{
	mPages.push_back(newPage);
	addChildComponent(newPage);
	newPage->setBounds(0, 0, getWidth(), getHeight());	

	int pageNum = mWidgets.size();
	addWidgetToView(newPage, MLRect(0, 0, getWidth(), getHeight()), ml::textUtils::addFinalNumber("page", pageNum));	
	return newPage;
}
Пример #3
0
const MLRect MLMultiSlider::getActiveRect() const
{
	int w = getWidth() - kMLShadowThickness*2;
	int h = getHeight() - kMLShadowThickness*2;
	const int dials = getNumSliders();
	w = getSliderWidth() * dials;
	int x = kMLShadowThickness;
	int y = kMLShadowThickness;
	return MLRect(x, y, w, h);
}
Пример #4
0
MLAppView* MLPageView::addPage()
{
	MLAppView* newPage = new MLAppView(mpResponder, mpReporter);
    int pageNum = mPages.size();
    String pageStr = String("page") + String(pageNum);
    newPage->setName(pageStr);
    
    // //debug() << "ADDING page " << pageStr << "\n";
	mPages.push_back(newPage);
	addChildComponent(newPage);
	newPage->setBounds(0, 0, getWidth(), getHeight());	
	addWidgetToView(newPage, MLRect(0, 0, getWidth(), getHeight()), ml::textUtils::addFinalNumber("page", pageNum));
	return newPage;
}
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;
         }
    }
}
Пример #6
0
void MLPluginProcessor::setStateFromXML(const XmlElement& xmlState, bool setViewAttributes)
{
	if (!(xmlState.hasTagName (JucePlugin_Name))) return;
	if (!(mEngine.getCompileStatus() == MLProc::OK)) return; // TODO revisit need to compile first

	// getCallbackLock() is in juce_AudioProcessor
	// process lock is a quick fix.  it is here to prevent doParams() from getting called in 
	// process() methods and thereby setting mParamsChanged to false before the real changes take place.
	// A better alternative would be a lock-free queue of parameter changes.
	const ScopedLock sl (getCallbackLock()); 
		
	// only the differences between default parameters and the program state are saved in a program,
	// so the first step is to set the default parameters.
	setDefaultParameters();
	
	// get program version of saved state
	unsigned blobVersion = xmlState.getIntAttribute ("pluginVersion");
	unsigned pluginVersion = JucePlugin_VersionCode;
	
	if (blobVersion > pluginVersion)
	{
		// TODO show error to user
		MLError() << "MLPluginProcessor::setStateFromXML: saved program version is newer than plugin version!\n";
		return;
	}
    
	// try to load scale if a scale attribute exists
    // TODO auto save all state including this
 	const String scaleDir = xmlState.getStringAttribute ("scaleDir"); // look for old-style dir attribute   
	const String scaleName = xmlState.getStringAttribute ("scaleName");
    String fullName;
    if(scaleName != String::empty)
    {
        fullName = scaleName;
        if(scaleDir != String::empty)
        {
            fullName = scaleDir + String("/") + fullName + ".scl";
        }
    }
    else
    {
        fullName = "12-equal";
    }
    std::string fullScaleName(fullName.toUTF8());
	setProperty("key_scale", fullScaleName);
    bool loaded = false;
    // look for scale under full name with path
    if(fullScaleName != std::string())
    {
        const MLFilePtr f = mScaleFiles->getFileByName(fullScaleName);
        if(f != MLFilePtr())
        {
            loadScale(f->mFile);
            loaded = true;
        }
    }
    if(!loaded)
    {
        loadDefaultScale();
    }
    
	// get preset name saved in blob.  when saving from AU host, name will also be set from RestoreState().
	const String presetName = xmlState.getStringAttribute ("presetName");
	setProperty("preset", std::string(presetName.toUTF8()));
    
	/*
     debug() << "MLPluginProcessor: setStateFromXML: loading program " << presetName << ", version " << std::hex << blobVersion << std::dec << "\n";
     MemoryOutputStream myStream;
     xmlState->writeToStream (myStream, "");
     debug() << myStream.toString();
     */
	
    /*
     setCurrentPresetName(presetName.toUTF8());
     setCurrentPresetDir(presetDir.toUTF8());
     */
    
	// get plugin-specific translation table for updating older versions of data
	std::map<MLSymbol, MLSymbol> translationTable;

	// TODO move this into Aalto! 
	// make translation tables based on program version. 
	//
	if (blobVersion <= 0x00010120)
	{
		// translate seq parameters
		for(unsigned n=0; n<16; ++n)
		{
			std::stringstream pName;
			std::stringstream pName2;
			pName << "seq_value" << n;
			pName2 << "seq_pulse" << n;
			MLSymbol oldSym(pName.str());
			MLSymbol newSym = MLSymbol("seq_value#").withFinalNumber(n);
			MLSymbol oldSym2(pName2.str());
			MLSymbol newSym2 = MLSymbol("seq_pulse#").withFinalNumber(n);
			translationTable[oldSym] = newSym;
			translationTable[oldSym2] = newSym2;	
		}
	}

	if (blobVersion <= 0x00010200)
	{
		MLSymbol oldSym = MLSymbol("seq_value");
		MLSymbol newSym = MLSymbol("seq_value").withFinalNumber(0);
		MLSymbol oldSym2 = MLSymbol("seq_pulse");
		MLSymbol newSym2 = MLSymbol("seq_pulse").withFinalNumber(0);
		translationTable[oldSym] = newSym;
		translationTable[oldSym2] = newSym2;
		
		// translate seq parameters
		for(unsigned n=1; n<16; ++n)
		{
			oldSym = MLSymbol("seq_value#").withFinalNumber(n);
			newSym = MLSymbol("seq_value").withFinalNumber(n);
			oldSym2 = MLSymbol("seq_pulse#").withFinalNumber(n);
			newSym2 = MLSymbol("seq_pulse").withFinalNumber(n);
			translationTable[oldSym] = newSym;
			translationTable[oldSym2] = newSym2;	
		}		
	}
	
	// get params from xml
	const unsigned numAttrs = xmlState.getNumAttributes();
	String patcherInputStr ("patcher_input_");

	for(unsigned i=0; i<numAttrs; ++i)
	{
		// get name / value pair.
		const String& attrName = xmlState.getAttributeName(i);
		const MLParamValue paramVal = xmlState.getDoubleAttribute(attrName);
		
		// if not a patcher input setting,
		if (!attrName.contains(patcherInputStr))
		{					
			// see if we have this named parameter in our engine. 
			MLSymbol paramSym = XMLAttrToSymbol(attrName);
			const int pIdx = getParameterIndex(paramSym);
			
			if (pIdx >= 0)
			{
				// debug() << "setStateFromXML: <" << paramSym << " = " << paramVal << ">\n";
				setPropertyImmediate(paramSym, paramVal);
			}
			else // try finding a match through translation table. 
			{
				//debug() << "Looking for parameter " << paramSym << " in table...\n";
				std::map<MLSymbol, MLSymbol>::iterator it;
				it = translationTable.find(paramSym);
				if (it != translationTable.end())
				{
					const MLSymbol newSym = translationTable[paramSym];
					const int pNewIdx = getParameterIndex(newSym);
					if (pNewIdx >= 0)
					{
						//debug() << "translated parameter to " << newSym << " .\n";
						setPropertyImmediate(newSym, paramVal);
					}
					else
					{
						MLError() << "MLPluginProcessor::setStateFromXML: no such parameter! \n";
					}
				}
				else
				{
					// fail silently on unfound params, because we have deprecated some but they may still 
					// be around in old presets. 
					//debug() << "MLPluginProcessor::setStateFromXML: parameter " << paramSym << " not found!\n";
				}
			}
		}
	}
	
	// get editor state from XML
    if(setViewAttributes)
	{
		int x = xmlState.getIntAttribute("editor_x");
		int y = xmlState.getIntAttribute("editor_y");
		int width = xmlState.getIntAttribute("editor_width");
		int height = xmlState.getIntAttribute("editor_height");
		mEditorRect = MLRect(x, y, width, height);
		mEditorNumbersOn = xmlState.getIntAttribute("editor_num", 1);
		mEditorAnimationsOn = xmlState.getIntAttribute("editor_anim", 1);
	}
}
Пример #7
0
// get local bounds of an element. 
//
MLRect MLPositioner::getElementBounds(int elementIdx)
{
	Vec2 e = getElementPosition(elementIdx);
	
	return correctRect(MLRect(e, e + mElementSize));
}
Пример #8
0
// get local bounds of an element and its margin. 
//
MLRect MLPositioner::getElementBoundsWithMargin(int elementIdx)
{
	Vec2 e = getElementPositionWithMargin(elementIdx);
	
	return correctRect(MLRect(e, e + mElementWithMarginSize));
}