mirror of
https://github.com/4ian/GDevelop.git
synced 2026-10-12 02:01:17 +00:00
Ensure behaviors are compatible with the object before pasting them (#7343)
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2025 Florian Rival ([email protected]). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ObjectTools.h"
|
||||
|
||||
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
bool ObjectTools::IsBehaviorCompatibleWithObject(
|
||||
const gd::Platform &platform, const gd::String &objectType,
|
||||
const gd::String &behaviorType,
|
||||
std::unordered_set<gd::String> coveredBehaviorType) {
|
||||
bool isBehaviorTypeAlreadyCovered =
|
||||
!coveredBehaviorType.insert(behaviorType).second;
|
||||
if (isBehaviorTypeAlreadyCovered) {
|
||||
return true;
|
||||
}
|
||||
const gd::BehaviorMetadata &behaviorMetadata =
|
||||
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
|
||||
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
// Should not happen because the behavior was added successfully (so its
|
||||
// metadata are valid) - but double check anyway and bail out if the
|
||||
// behavior metadata are invalid.
|
||||
return false;
|
||||
}
|
||||
if (!behaviorMetadata.GetObjectType().empty() &&
|
||||
behaviorMetadata.GetObjectType() != objectType) {
|
||||
return false;
|
||||
}
|
||||
for (const gd::String &requiredBehaviorType :
|
||||
behaviorMetadata.GetRequiredBehaviorTypes()) {
|
||||
const gd::BehaviorMetadata &requiredBehaviorMetadata =
|
||||
gd::MetadataProvider::GetBehaviorMetadata(platform, requiredBehaviorType);
|
||||
if (requiredBehaviorMetadata.IsHidden()) {
|
||||
const gd::ObjectMetadata &objectMetadata =
|
||||
gd::MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||
if (objectMetadata.GetDefaultBehaviors().find(requiredBehaviorType) ==
|
||||
objectMetadata.GetDefaultBehaviors().end()) {
|
||||
// A capability is missing in the object.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!gd::ObjectTools::IsBehaviorCompatibleWithObject(
|
||||
platform, objectType, requiredBehaviorType, coveredBehaviorType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2025 Florian Rival ([email protected]). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/String.h"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace gd {
|
||||
class Platform;
|
||||
class Object;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
class GD_CORE_API ObjectTools {
|
||||
public:
|
||||
static bool IsBehaviorCompatibleWithObject(const gd::Platform &platform,
|
||||
const gd::String &objectType,
|
||||
const gd::String &behaviorType) {
|
||||
std::unordered_set<gd::String> coveredBehaviorType;
|
||||
return IsBehaviorCompatibleWithObject(platform, objectType, behaviorType,
|
||||
coveredBehaviorType);
|
||||
}
|
||||
|
||||
private:
|
||||
static bool IsBehaviorCompatibleWithObject(
|
||||
const gd::Platform &platform, const gd::String &objectType,
|
||||
const gd::String &behaviorType,
|
||||
std::unordered_set<gd::String> coveredBehaviorType);
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
@@ -2786,6 +2786,13 @@ interface WholeProjectRefactorer {
|
||||
[Value] SetString STATIC_FindAllLeaderboardIds([Ref] Project project);
|
||||
};
|
||||
|
||||
interface ObjectTools {
|
||||
boolean STATIC_IsBehaviorCompatibleWithObject(
|
||||
[Const, Ref] Platform platform,
|
||||
[Const] DOMString objectType,
|
||||
[Const] DOMString behaviorType);
|
||||
};
|
||||
|
||||
interface EventsBasedObjectDependencyFinder {
|
||||
boolean STATIC_IsDependentFromEventsBasedObject(
|
||||
[Const, Ref] Project project,
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
#include <GDCore/Project/MeasurementUnitElement.h>
|
||||
#include <GDCore/Project/NamedPropertyDescriptor.h>
|
||||
#include <GDCore/Project/Object.h>
|
||||
#include <GDCore/Project/ObjectTools.h>
|
||||
#include <GDCore/Project/ObjectFolderOrObject.h>
|
||||
#include <GDCore/Project/ObjectConfiguration.h>
|
||||
#include <GDCore/Project/Project.h>
|
||||
@@ -659,6 +660,7 @@ typedef ExtensionAndMetadata<ExpressionMetadata> ExtensionAndExpressionMetadata;
|
||||
#define STATIC_FindInvalidRequiredBehaviorProperties \
|
||||
FindInvalidRequiredBehaviorProperties
|
||||
#define STATIC_GetBehaviorsWithType GetBehaviorsWithType
|
||||
#define STATIC_IsBehaviorCompatibleWithObject IsBehaviorCompatibleWithObject
|
||||
#define STATIC_FixInvalidRequiredBehaviorProperties \
|
||||
FixInvalidRequiredBehaviorProperties
|
||||
#define STATIC_RemoveLayerInScene RemoveLayerInScene
|
||||
|
||||
Vendored
+4
@@ -1985,6 +1985,10 @@ export class WholeProjectRefactorer extends EmscriptenObject {
|
||||
static findAllLeaderboardIds(project: Project): SetString;
|
||||
}
|
||||
|
||||
export class ObjectTools extends EmscriptenObject {
|
||||
static isBehaviorCompatibleWithObject(platform: Platform, objectType: string, behaviorType: string): boolean;
|
||||
}
|
||||
|
||||
export class EventsBasedObjectDependencyFinder extends EmscriptenObject {
|
||||
static isDependentFromEventsBasedObject(project: Project, eventsBasedObject: EventsBasedObject, dependency: EventsBasedObject): boolean;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Automatically generated by GDevelop.js/scripts/generate-types.js
|
||||
declare class gdObjectTools {
|
||||
static isBehaviorCompatibleWithObject(platform: gdPlatform, objectType: string, behaviorType: string): boolean;
|
||||
delete(): void;
|
||||
ptr: number;
|
||||
};
|
||||
@@ -184,6 +184,7 @@ declare class libGDevelop {
|
||||
ResourceExposer: Class<gdResourceExposer>;
|
||||
VariablesChangeset: Class<gdVariablesChangeset>;
|
||||
WholeProjectRefactorer: Class<gdWholeProjectRefactorer>;
|
||||
ObjectTools: Class<gdObjectTools>;
|
||||
EventsBasedObjectDependencyFinder: Class<gdEventsBasedObjectDependencyFinder>;
|
||||
PropertyFunctionGenerator: Class<gdPropertyFunctionGenerator>;
|
||||
UsedExtensionsResult: Class<gdUsedExtensionsResult>;
|
||||
|
||||
@@ -477,6 +477,15 @@ export const useManageObjectBehaviors = ({
|
||||
if (!name || !type || !serializedBehavior) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!gd.ObjectTools.isBehaviorCompatibleWithObject(
|
||||
project.getCurrentPlatform(),
|
||||
object.getType(),
|
||||
type
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const behaviorMetadata = gd.MetadataProvider.getBehaviorMetadata(
|
||||
project.getCurrentPlatform(),
|
||||
|
||||
Reference in New Issue
Block a user