Copy link to clipboard
Copied
Updated 2-26-21: I need to create custom gradients to apply to path fills, and studied the "SnpGradient.cpp" snippet file to create this test gradient.
The sample code adds the gradient to the Swatches panel, but most of my gradients have no reason to be there, and adding them all would just fill the panel up! If I just apply the color to the pathstyle fill, it doesn't apply the gradient origin or other info and I get this:
That's the gradient annotator all squashed into that {0,0} point! When I read in the pathstyle info back from the path art, I see that the other gradient info is there, but doesn't get applied. The gradient is defined earlier, and here's the code to apply it to the art:
AIColor swatchColor;
swatchColor.kind = kGradient;
swatchColor.c.b.gradient = gradient;
swatchColor.c.b.gradientAngle = 0;
swatchColor.c.b.gradientLength = 100;
swatchColor.c.b.gradientOrigin = {0,50};
swatchColor.c.b.hiliteAngle = 0;
swatchColor.c.b.hiliteLength = 0;
AIPathStyle pathStyle;
result = sAIPathStyle->GetPathStyle(tempart->aiArtHandle(), &pathStyle, nullptr);
AIColor color;
result = sAISwatchList->GetAIColor(swatch, &color);
pathStyle.fill.color = swatchColor;
pathStyle.fillPaint = true;
result = sAIPathStyle->SetPathStyle(tempart->aiArtHandle(), &pathStyle);
AIPathStyle pathStyle2;
result = sAIPathStyle->GetPathStyle(tempart->aiArtHandle(), &pathStyle2, nullptr);
Applying the color to the swatch list, then reading it back allows the art to honor the gradient origin, etc.
result = sAISwatchList->SetAIColor(swatch, &swatchColor);
result = sAIPathStyle->GetPathStyle(tempart->aiArtHandle(), &pathStyle, nullptr);
AIColor color;
result = sAISwatchList->GetAIColor(swatch, &color);
pathStyle.fill.color = color;
Shouldn't one be able to apply the gradient origin, length, and angle without setting a swatch in the swatch list and Swatch panel? Any suggestions would be very much appreciated!
Well, I got it to work!
I didn't use the matrix at all. In order to position the gradient on the path, I had to add the color to the Swatches panel, then retrieve it again before applying it to the art. If I don't want a particular gradient swatch to stay in the panel, I have to manually remove it later.
In the code below, the gradient has already been built, in the variable "gradient." The first line here creates an ellipse-shaped path art object in CORE.
hdi::core::ArtAP tempart = hdi::core::d
...
Copy link to clipboard
Copied
I've discovered that AIArtStylePaintData includes a point member fillRelativeGradientOrigin that should also position the gradient origin. As an anonymous art style with a gradient not in the Swatches panel, these settings, applied with sAIArtStyle->SetArtStyle, seem to do nothing. Surely somebody knows how to do this...
Copy link to clipboard
Copied
Try with AIArtStyleParserSuite::NewPaintFieldFill.
Copy link to clipboard
Copied
Thanks, Milos. I've tried variations of NewPaintFieldFill and GetNthPaintField, but nothing seems to work. The gradient annotator remains collapsed at the {0,0} point. I wish this were documented somewhere other than the cryptic header notes. With so many overlapping structs, I wonder if something gets set up correctly, then canceled out by a function that should apply it. I'll post results if I figure this out.
Copy link to clipboard
Copied
I am pretty sure we managed to do this at one point in our plugin, but I cannot remember how. Did you define gradient steps correctly? Also it is possible to apply transformations for gradient (using AITransformSuite::TransformArt), there is an option to apply transformation matrix only for gradients, you could try and play with that.
Copy link to clipboard
Copied
Well, I got it to work!
I didn't use the matrix at all. In order to position the gradient on the path, I had to add the color to the Swatches panel, then retrieve it again before applying it to the art. If I don't want a particular gradient swatch to stay in the panel, I have to manually remove it later.
In the code below, the gradient has already been built, in the variable "gradient." The first line here creates an ellipse-shaped path art object in CORE.
hdi::core::ArtAP tempart = hdi::core::draw::ellipse(hdi::core::ArtboardPoint(-20,150), 180, 180, true);
// define the swatch color
AISwatchRef swatch;
result = sAISwatchList->SetSwatchName(swatch, ai::UnicodeString("My test swatch"));
AIColor swatchColor;
swatchColor.kind = kGradient;
swatchColor.c.b.gradient = gradient;
swatchColor.c.b.gradientAngle = -90;
swatchColor.c.b.gradientLength = tempart->noStrokeBounds().size.height;
swatchColor.c.b.gradientOrigin = gradientStartPt(tempart->noStrokeBounds().topCenter());
swatchColor.c.b.hiliteAngle = 0;
swatchColor.c.b.hiliteLength = 0;
// add to swatch panel
AISwatchGroupRef swatchGroup;
swatchGroup = sAISwatchGroup->GetSwatchGroupByName(NULL, ai::UnicodeString("My Swatches"));
if (swatchGroup == NULL){
result = sAISwatchGroup->NewSwatchGroup(NULL, kAISGKindGradientsOnly, -1, &swatchGroup);
result = sAISwatchGroup->SetSwatchGroupName(swatchGroup, ai::UnicodeString("My Swatches"));
}
swatch = sAISwatchGroup->GetSwatchByName(swatchGroup, ai::UnicodeString("My test swatch"));
if (swatch == NULL)
swatch = sAISwatchGroup->InsertNthSwatch(swatchGroup, &swatchColor, -1);
// get color from swatch panel
AIColor color;
result = sAISwatchList->GetAIColor(swatch, &color);
// apply color to art
AIPathStyle pathStyle;
pathStyle.fill.color = color;
pathStyle.fillPaint = true;
result = sAIPathStyle->SetPathStyle(tempart->aiArtHandle(), &pathStyle);
// remove the swatch from the panel if it won't be used again
result = sAISwatchGroup->RemoveSwatch(swatchGroup, swatch, false);
The swatches will be placed in my own group, and managed by swatch name.
I want my gradients to run top to bottom, so I set the gradient length to the object height. The gradient origin is essentially the art top-center, flipped vertically. I've included below a small function to convert the CORE artboard point to the adjusted AIRealPoint.
AIRealPoint test::Plugin::gradientStartPt(hdi::core::ArtboardPoint pt){
AIRealPoint p;
p.h = pt.x;
p.v = pt.y * -1;
return p;
}
Now that my test code works, I'll clean it up to check error codes and use variables for the swatch and swatch group names. There's probably a better way to do it, but for now at least, this works!