Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to swap assets of any object type #7365

Merged
merged 3 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion newIDE/app/src/AssetStore/AssetStoreSearchFilter.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,16 @@ export class ColorAssetStoreSearchFilter
}

const toAssetStoreType = (type: string) => {
return type === 'Sprite' ? 'sprite' : type;
switch (type) {
case 'Sprite':
return 'sprite';
case 'TiledSpriteObject::TiledSprite':
return 'tiled';
case 'PanelSpriteObject::PanelSprite':
return '9patch';
default:
return type;
}
};

// Thematic tags are noise for asset swapping as changing the theme may be what
Expand Down
28 changes: 23 additions & 5 deletions newIDE/app/src/AssetStore/AssetSwapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,18 @@ type SpriteObjectDataType = {
animations: Array<SpriteAnimationData>,
};

export const canSwapAssetOfObject = (object: gdObject) => {
const type = object.getType();
return type === 'Scene3D::Model3DObject' || type === 'Sprite';
};
const unswappableObjectTypes = [
'BBText::BBText',
'TextObject::Text',
'Lighting::LightObject',
'PrimitiveDrawing::Drawer',
'TileMap::TileMap',
'TileMap::CollisionMask',
'TileMap::SimpleTileMap',
'Video::VideoObject',
];
export const canSwapAssetOfObject = (object: gdObject) =>
!unswappableObjectTypes.includes(object.getType());

const mergeAnimations = function<A: { name: string }>(
project: gdProject,
Expand Down Expand Up @@ -312,7 +320,7 @@ export const swapAsset = (
assetObject: gdObject,
assetShortHeader?: ?AssetShortHeader
) => {
const serializedObject = serializeToJSObject(object);
let serializedObject = serializeToJSObject(object);
const serializedAssetObject = serializeToJSObject(assetObject);

if (object.getType() === 'Sprite') {
Expand All @@ -338,6 +346,7 @@ export const swapAsset = (
scaleX,
scaleY
);
serializedObject.assetStoreId = serializedAssetObject.assetStoreId;
} else if (object.getType() === 'Scene3D::Model3DObject') {
const objectVolume =
serializedObject.content.width *
Expand Down Expand Up @@ -365,6 +374,15 @@ export const swapAsset = (
centerLocation: serializedObject.content.centerLocation,
};
serializedObject.assetStoreId = serializedAssetObject.assetStoreId;
} else {
serializedObject = {
...serializedAssetObject,
name: serializedObject.name,
type: serializedObject.type,
variables: serializedObject.variables,
behaviors: serializedObject.behaviors,
effects: serializedObject.effects,
};
}
unserializeFromJSObject(object, serializedObject, 'unserializeFrom', project);
};
Original file line number Diff line number Diff line change
Expand Up @@ -90,22 +90,22 @@ const sortedContentType: PrivateAssetPackAssetType[] = [
'TileMap::SimpleTileMap',
'ParticleSystem::ParticleEmitter',
'font',
'bitmapFont',
'audio',
'partial',
];

const contentTypeToMessageDescriptor: {
[PrivateAssetPackAssetType]: MessageDescriptor,
} = {
sprite: t`Sprites`,
'9patch': t`Panel sprites`,
tiled: t`Tiled sprites`,
sprite: t`sprites`,
'9patch': t`panel sprites`,
tiled: t`tiled sprites`,
'Scene3D::Model3DObject': t`3D models`,
'TileMap::SimpleTileMap': t`Tilemaps`,
'ParticleSystem::ParticleEmitter': t`Particle emitters`,
font: t`Fonts`,
audio: t`Audios`,
partial: t`Other`,
'TileMap::SimpleTileMap': t`tile maps`,
'ParticleSystem::ParticleEmitter': t`particle emitters`,
font: t`fonts`,
bitmapFont: t`bitmap fonts`,
audio: t`audios`,
};

const styles = {
Expand Down Expand Up @@ -521,6 +521,23 @@ const PrivateAssetPackInformationPage = ({
{ subscription, privateAssetPackListingData, isAlreadyReceived }
);

const smartObjectsCount = React.useMemo(
() => {
if (!assetPack) {
return 0;
}
let smartObjectsCount = 0;
for (const type in assetPack.content) {
const assetCount = assetPack.content[type];
if (!sortedContentType.includes(type)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels a bit light as a check to decide if the object is a smart object. If we add 3D particle emitters or 3D cubes in a pack, it will display them as a smart objects.

Copy link
Collaborator Author

@D8H D8H Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If smart objects mean an object with some logic, it's the case for any object so I think it's not a big deal.
We can add lines for more objects in the future if we think it becomes useful.
I see it as a "others" category but less boring.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it's quite deceptive when users purchase something and they end up with boring objects.

Copy link
Collaborator Author

@D8H D8H Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no easy way to know if an object comes from engine or an event-based extension. And even in this case, the limit is blurry because the 3D particle emitter is from an event-based extension and it may not fit everyone definition of "smart object".
I think when there are new cases, we can add specific lines for them.
The choice of words:

  • "smart object" avoids diminishing the appeal for asset packs with custom objects (which is an actual use-case)
  • "other" avoids the risk of mislabeling new objects (which rarely happens, is only a bug that can be fixed easily)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smart objects is probably fine. If some are becoming super "well known", we'll add specific names for them in the future.

smartObjectsCount += assetCount;
}
}
return smartObjectsCount;
},
[assetPack]
);

return (
<I18n>
{({ i18n }) => (
Expand Down Expand Up @@ -714,6 +731,13 @@ const PrivateAssetPackInformationPage = ({
}
return null;
})}
{smartObjectsCount > 0 ? (
<li>
<Text displayInlineAsSpan noMargin>
<Trans>{smartObjectsCount} smart objects</Trans>
</Text>
</li>
) : null}
</Column>
{bundlesContainingPackTiles &&
bundlesContainingPackTiles.length ? (
Expand Down
4 changes: 2 additions & 2 deletions newIDE/app/src/Utils/GDevelopServices/Asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@ export type PrivateAssetPackAssetType =
| 'sprite'
| '9patch'
| 'tiled'
| 'partial'
| 'Scene3D::Model3DObject'
| 'TileMap::SimpleTileMap'
| 'ParticleSystem::ParticleEmitter';
| 'ParticleSystem::ParticleEmitter'
| string;

export type PrivateAssetPackContent = { [PrivateAssetPackAssetType]: number };

Expand Down