diff --git a/release-packaging/Classes/FluidPlotter.sc b/release-packaging/Classes/FluidPlotter.sc new file mode 100644 index 0000000..036359d --- /dev/null +++ b/release-packaging/Classes/FluidPlotter.sc @@ -0,0 +1,246 @@ +FluidPlotterPoint { + var id, color, <>size = 1; + + *new { + arg id, x, y, color, size = 1; + ^super.new.init(id,x,y,color,size); + } + + init { + arg id_, x_, y_, color_, size_ = 1; + id = id_; + x = x_; + y = y_; + color = color_ ? Color.black; + size = size_; + } +} + +FluidPlotter : FluidViewer { + var (categoryColors.size-1),{ + "FluidPlotter:setCategories_ FluidPlotter doesn't have that many category colors. You can use the method 'setColor_' to set colors for individual points.".warn + }); + + color = categoryColors[category_int]; + fp_pt.color_(color); + }); + this.refresh; + },{ + "FluidPlotter::setCategories_ FluidPlotter cannot receive setCategories. It has no data. First set a dictionary.".warn; + }); + } + + pointSize_ { + arg identifier, size; + if(dict_internal.at(identifier).notNil,{ + dict_internal.at(identifier).size_(size); + this.refresh; + },{ + "FluidPlotter::pointSize_ identifier not found".warn; + }); + } + + // TODO: addPoint_ that checks if the key already exists and throws an error if it does + addPoint_ { + arg identifier, x, y, color, size = 1; + if(dict_internal.at(identifier).notNil,{ + "FluidPlotter::addPoint_ There already exists a point with identifier %. Point not added. Use setPoint_ to overwrite existing points.".format(identifier).warn; + },{ + this.setPoint_(identifier,x,y,size,color); + }); + } + + setPoint_ { + arg identifier, x, y, color, size = 1; + + dict_internal.put(identifier,FluidPlotterPoint(identifier,x,y,color ? Color.black,size)); + + this.refresh; + } + + pointColor_ { + arg identifier, color; + if(dict_internal.at(identifier).notNil,{ + dict_internal.at(identifier).color_(color); + this.refresh; + },{ + "FluidPlotter::setColor_ identifier not found".warn; + }); + } + + shape_ { + arg sh; + shape = sh; + this.refresh; + } + + background_ { + arg bg; + userView.background_(bg); + } + + refresh { + {userView.refresh}.defer; + } + + pointSizeScale_ { + arg ps; + pointSizeScale = ps; + this.refresh; + } + + dict_ { + arg d; + + if(d.isNil,{^this.dictNotProperlyFormatted}); + if(d.size != 2,{^this.dictNotProperlyFormatted}); + if(d.at("data").isNil,{^this.dictNotProperlyFormatted}); + if(d.at("cols").isNil,{^this.dictNotProperlyFormatted}); + if(d.at("cols") != 2,{^this.dictNotProperlyFormatted}); + + dict = d; + dict_internal = Dictionary.new; + dict.at("data").keysValuesDo({ + arg k, v; + dict_internal.put(k,FluidPlotterPoint(k,v[0],v[1],Color.black,1)); + }); + if(userView.notNil,{ + this.refresh; + }); + } + + xmin_ { + arg val; + xmin = val; + this.refresh; + } + + xmax_ { + arg val; + xmax = val; + this.refresh; + } + + ymin_ { + arg val; + ymin = val; + this.refresh; + } + + ymax_ { + arg val; + ymax = val; + this.refresh; + } + + highlight_ { + arg identifier; + highlightIdentifier = identifier; + this.refresh; + } + + dictNotProperlyFormatted { + "FluidPlotter: The dictionary passed in is not properly formatted.".error; + } + + createPlotWindow { + arg bounds,parent_, mouseMoveAction,dict_; + var xpos, ypos; + var mouseAction = { + arg view, x, y, modifiers, buttonNumber, clickCount; + x = x.linlin(pointSize/2,userView.bounds.width-(pointSize/2),xmin,xmax); + y = y.linlin(pointSize/2,userView.bounds.height-(pointSize/2),ymax,ymin); + mouseMoveAction.(this,x,y,modifiers,buttonNumber, clickCount); + }; + + if(parent_.isNil,{xpos = 0; ypos = 0},{xpos = bounds.left; ypos = bounds.top}); + { + parent = parent_ ? Window("FluidPlotter",bounds); + userView = UserView(parent,Rect(xpos,ypos,bounds.width,bounds.height)); + + userView.drawFunc_({ + if(dict_internal.notNil,{ + dict_internal.keysValuesDo({ + arg key, pt; + var pointSize_, scaledx, scaledy, color; + + /* key.postln; + pt.postln; + pt.x.postln; + pt.y.postln;*/ + + if(key == highlightIdentifier,{ + pointSize_ = pointSize * 2.3 * pt.size + },{ + pointSize_ = pointSize * pt.size + }); + + pointSize_ = pointSize_ * pointSizeScale; + + scaledx = pt.x.linlin(xmin,xmax,0,userView.bounds.width,nil) - (pointSize_/2); + scaledy = pt.y.linlin(ymax,ymin,0,userView.bounds.height,nil) - (pointSize_/2); + + shape.switch( + \square,{Pen.addRect(Rect(scaledx,scaledy,pointSize_,pointSize_))}, + \circle,{Pen.addOval(Rect(scaledx,scaledy,pointSize_,pointSize_))} + ); + + Pen.color_(pt.color); + Pen.draw; + }); + }); + }); + + userView.mouseMoveAction_(mouseAction); + userView.mouseDownAction_(mouseAction); + + this.background_(Color.white); + + if(parent_.isNil,{parent.front;}); + }.defer; + } + + close { + parent.close; + } +}