Copy link to clipboard
Copied
Hello everyone,
My objective is to duplicate the existing artboard items and replace an art item with a different one from another .ai file using a C++ plugin. I am able to duplicate the artboard items and also duplicate another art item from a different .ai file, but I am not able to transform the newly duplicated art to the position of the original art.
Below is my code:
ASErr ReplaceFromExternalFile(const ai::FilePath& sourceFilePath, AIArtHandle oldArtHandle)
{
ASErr error = kNoErr;
//Store the current document handle
AIDocumentHandle destDoc;
sAIDocument->GetDocument(&destDoc);
//Open source document containing new logo
AIDocumentHandle sourceDoc;
error = sAIDocumentList->Open(sourceFilePath, kAIUnknownColorModel, kDialogOff, false, &sourceDoc);
if (error || !sourceDoc) return error;
//Get first art in source document
sAIDocumentList->Activate(sourceDoc, false);
//Find the art handle to be used in Destination document
AILayerHandle sourceRoot;
error = sAILayer->GetFirstLayer(&sourceRoot);
if (error || !sourceRoot) return error;
AIArtHandle newLogoArt = nullptr;
error = sAIArt->GetFirstArtOfLayer(sourceRoot, &newLogoArt);
if (error || !newLogoArt) return error;
while (newLogoArt != nullptr)
{
short artType;
error = sAIArt->GetArtType(newLogoArt, &artType);
if (error) return error;
if (artType != kUnknownArt)
{
break; // found usable art
}
error = sAIArt->GetArtSibling(newLogoArt, &newLogoArt);
if (error) return error;
}
if (!newLogoArt)
{
sAIDocumentList->Close(sourceDoc);
return kNotFoundErr;
}
//Acitvate the destination document
error = sAIDocumentList->Activate(destDoc, true);
if (error) return error;
//Get the layer handle and group
AILayerHandle layerDest;
AIArtHandle artDestGroup;
error = sAILayer->GetFirstLayer(&layerDest);
if (error || !layerDest) return error;
sAIArt->GetFirstArtOfLayer(sourceRoot, &artDestGroup);
// Duplicate the art in destination document
AIArtHandle pastedArt = nullptr;
error = sAIArt->DuplicateArt(newLogoArt, kPlaceAboveAll, artDestGroup, &pastedArt);
if (error) return error;
//Transform to the old logo position
AIReal dx = _newArtBoardRect.left;// -newBounds.left * scaleX;
AIReal dy = _newArtBoardRect.top;// -newBounds.bottom * scaleY;
transformArtToNewPosition(pastedArt, dx, dy);
//Added below line to check transform is working or not
AIReal dx = _newArtBoardRect.left;
AIReal dy = _newArtBoardRect.top;
transformArtToNewPosition(oldLogoArtHandle, dx, dy);
//Delete old logo ---
//error = sAIArt->DeleteArt(oldLogoArtHandle);
//if (error) return error;
//Clean up ---
sAIDocumentList->Close(sourceDoc); // close the source logo file
return kNoErr;
}
Also added code for the transformArtToNewPosition and please find below:
ASErr transformArtToNewPosition(AIArtHandle art, AIReal tx, AIReal ty)
{
ASErr result = kNoErr;
AIRealRect artBounds;
AIRealPoint artCenter;
AIRealMatrix artMatrix;
AIReal lineScale;
ai::int32 transformFlags = kTransformObjects | kScaleLines | kTransformChildren;
short artType;
ASErr error = sAIArt->GetArtType(art, &artType);
if (error == kGroupArt)
{
return error;
}
lineScale = (sAIRealMath->AIRealSqrt(1)) * (sAIRealMath->AIRealSqrt(1));
result = sAIArt->GetArtBounds(art, &artBounds);
artCenter.h = artBounds.left + (artBounds.right - artBounds.left) / 2;
artCenter.v = artBounds.bottom + (artBounds.top - artBounds.bottom) / 2;
// move object so that the centerpoint is at the origin
sAIRealMath->AIRealMatrixSetIdentity(&artMatrix);
sAIRealMath->AIRealMatrixSetTranslate(&artMatrix, -artCenter.h, -artCenter.v);
sAIRealMath->AIRealMatrixConcatTranslate(&artMatrix, tx, ty);
sAIRealMath->AIRealMatrixConcatRotate(&artMatrix, 0);
sAIRealMath->AIRealMatrixConcatScale(&artMatrix, 1, 1);
sAIRealMath->AIRealMatrixConcatTranslate(&artMatrix, artCenter.h, artCenter.v);
result = sAITransformArt->TransformArt(art, &artMatrix, lineScale, transformFlags);
return result;
}
With the above transformArtToNewPosition code, I can transform the oldLogoArtHandle, but I cannot change the position of the newly duplicated art. Please check the attached image for the current output of my plugin.
Could anyone shed some light on this or provide any input to help achieve my requirement? Thanks in advance!
The code for duplicating looks fine. As A Patterson says, the API works when used correctly and your code is overly complicated, so chances are there’s a logic bug buried in it. If you’ve still not solved it, I will say this bit of code “smells off” to me:
AIReal dx = _newArtBoardRect.left;// -newBounds.left * scaleX; AIReal dy = _newArtBoardRect.top;// -newBounds.bottom * scaleY; transformArtToNewPosition(pastedArt, dx, dy);
ExtendScript’s high-level API allows you to set an o
...Copy link to clipboard
Copied
1. I don’t understand what the screenshot is showing.
2. Be aware that TransformArt is not recursive. To reposition a collection (group/compound path) of items, you must recursively traverse its contents and call TraverseArt on each of its Art items yourself.
Copy link to clipboard
Copied
Hi hhas01, thank you for the reply.
1. When I run my plugin I am able to duplicate the contents of first artboard and place the Yellow rect in the correct position. I want to replace yellow rect with blue rect. Blue rect is in a different file. As it's showing the screenshot Blue rect was duplicated but not able to transform to Yellow rect position.
2. Yes, I have added TransformGroupItems function to recursively traverse its contents and call TraverseArt. But still not working.
Is my code for duplicating Art from another .ai file correct? Any help? Thanks
Copy link to clipboard
Copied
We also move art between documents and don't have any problems (that I know of!) like this. That said, your matrix code seems overly complicated for a straight translation. Our base class has a function like this:
void Translate(AIArtHandle handle, AIReal x, AIReal y, ETranslateOptions options)
{
AIRealMatrix matrix;
sAIRealMath->AIRealMatrixSetTranslate(&matrix, x, y);
ai::int32 flags = kTransformObjects | kTransformFillGradients | kTransformFillPatterns | kTransformStrokePatterns;
if (options == ETranslateOptions::TranslateChildren) {
flags |= kTransformChildren;
}
auto err = sAITransformArt->TransformArt(handle, &matrix, 1.0, flags);
THROW_EXCEP_IF(err);
}
I don't think that's the source of your problem necessarily, but the very least your transformation could be simplified.
Copy link to clipboard
Copied
Thank you, Patterson, for the simplified version of the Translate function.
Copy link to clipboard
Copied
The code for duplicating looks fine. As A Patterson says, the API works when used correctly and your code is overly complicated, so chances are there’s a logic bug buried in it. If you’ve still not solved it, I will say this bit of code “smells off” to me:
AIReal dx = _newArtBoardRect.left;// -newBounds.left * scaleX; AIReal dy = _newArtBoardRect.top;// -newBounds.bottom * scaleY; transformArtToNewPosition(pastedArt, dx, dy);
ExtendScript’s high-level API allows you to set an object’s absolute position really easily using `object.position = [x,y]`.
Using the low-level C++ API, you must configure an AIMatrix to move (Translate) an Art object relative to its current position. So to center your new Art object over your old Art object:
1. calculate both Art objects’ centerpoints
2. calculate the x and y distances between those two points
3. pass these x and y distance values to the AIRealMatrixSetTranslate() function to populate your AIMatrix
4. pass this matrix and the new Art object to TransformArt(). (Or, if it’s a group or other collection, apply TransformArt recursively to all of its children.)
Me, I might define a convenience function named `ASErr RepositionObjectToCenterOfObject(AIArtHandle newObject, AIArtHandle oldObject)` and fill in its function body from there.
Copy link to clipboard
Copied
Thank you for the reply. I solved the issue, and it's due to the wrong calculation.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now