Sorry, I remembered it slightly wrong. So we have SVG in memory that we convert to an Image when the scale or cursor changes. We use the normal juce::MouseCursor and we use the constructor that takes an image. We get the scale from the associated components x,y coordinates and then get the desktop and its scale from that.
Here is our GUI_Cursors.h file, but you will have to code the
reFX::SVG::loadSVG
function yourself.
In our case, it loads the SVG from the BinaryData into a juce::Drawable.
#pragma once
//-------------------------------------------------------------------------------------------------
class GUI_Cursors
{
public:
GUI_Cursors () = default;
MouseCursor getPencil ( Component& c )
{
return getCursor ( pencil, pencilScale, "cursor-pencil-alt.svg", c, 24, 24 );
}
MouseCursor getPaint ( Component& c )
{
return getCursor ( paint, paintScale, "cursor-brush.svg", c, 24, 24 );
}
MouseCursor getLasso ( Component& c )
{
return getCursor ( lasso, lassoScale, "cursor-select.svg", c, 28, 54 );
}
MouseCursor getEraser ( Component& c )
{
return getCursor ( eraser, eraserScale, "cursor-delete.svg", c, 30, 51, true );
}
MouseCursor getHandRock ( Component& c )
{
return getCursor ( handRock, handRockScale, "cursor-hand-rock.svg", c, 24, 24 );
}
MouseCursor getHandPaper ( Component& c )
{
return getCursor ( handPaper, handPaperScale, "cursor-hand-paper.svg", c, 24, 24 );
}
private:
MouseCursor getCursor ( MouseCursor& mc, float& lastScale, const String& svg, Component& c, const int cx, const int cy, const bool danger = false )
{
auto scale = getScale ( c );
if ( lastScale != scale )
{
lastScale = scale;
mc = cursorFromSvg ( svg, scale, cx, cy, danger );
}
return mc;
}
float getScale ( [[ maybe_unused ]] Component& c )
{
#if JUCE_MAC
return 1.0f;
#else
auto rc = c.localAreaToGlobal ( c.getLocalBounds () );
return float ( Desktop::getInstance ().getDisplays ().findDisplayForRect ( rc ).scale );
#endif
}
MouseCursor cursorFromSvg ( const String& svg, const float scale, const int cx, const int cy, const bool danger )
{
const auto ix = float ( cx ) * scale;
const auto iy = float ( cy ) * scale;
const auto id = int ( std::max ( ix, iy ) );
// Cursor images have to be square (on Windows at least), otherwise they get stretched
Image img ( Image::ARGB, id, id, true );
{
Graphics g ( img );
auto drawable = reFX::SVG::loadSVG ( svg );
#if JUCE_MAC
drawable->replaceColour ( Colour ( 0xffff00ff ), danger ? Colour ( 0xffffaa44 ) : Colours::black );
drawable->replaceColour ( Colour ( 0xff00ff00 ), danger ? Colour ( 0xff443311 ) : Colours::white );
#else
drawable->replaceColour ( Colour ( 0xffff00ff ), danger ? Colour ( 0xffffaa44 ) : Colours::white );
drawable->replaceColour ( Colour ( 0xff00ff00 ), danger ? Colour ( 0xff443311 ) : Colours::black );
#endif
drawable->drawWithin ( g, Rectangle<float> { ix, iy }, 0, 1.0f );
}
const auto inset = int ( 4.0f * scale );
return MouseCursor ( img, inset, inset );
}
MouseCursor pencil;
MouseCursor paint;
MouseCursor lasso;
MouseCursor eraser;
MouseCursor handRock;
MouseCursor handPaper;
float pencilScale = 0.0f;
float paintScale = 0.0f;
float lassoScale = 0.0f;
float eraserScale = 0.0f;
float handRockScale = 0.0f;
float handPaperScale = 0.0f;
};