Files
GDevelop/Core/GDCore/Project/EventsBasedObject.h
D8H 896f56e850 Allow to switch between variants of custom objects (#7403)
- Variants allows to restyle custom objects
- They can be customized with the graphical editor
- The asset store will progressively use them notably for UI elements (buttons, sliders)
2025-04-24 11:05:00 +02:00

368 lines
9.4 KiB
C++

/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <vector>
#include "GDCore/Project/AbstractEventsBasedEntity.h"
#include "GDCore/Project/EventsBasedObjectVariant.h"
#include "GDCore/Project/EventsBasedObjectVariantsContainer.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/InitialInstancesContainer.h"
#include "GDCore/Project/LayersContainer.h"
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
class Project;
} // namespace gd
namespace gd {
// TODO EBO Add a way to mark some parts of children configuration as readonly.
/**
* \brief Represents an object that is implemented with events.
*
* It's the responsibility of the IDE to run the logic to transform this into a
* real object, by declaring an extension and running code generation.
* See `EventsFunctionsExtensionsLoader`.
*
* \ingroup PlatformDefinition
*/
class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
public:
EventsBasedObject();
virtual ~EventsBasedObject();
/**
* \brief Return a pointer to a new EventsBasedObject constructed from
* this one.
*/
EventsBasedObject* Clone() const { return new EventsBasedObject(*this); };
/**
* \brief Get the default name for created objects.
*/
const gd::String& GetDefaultName() const { return defaultName; };
/**
* \brief Set the default name for created objects.
*/
EventsBasedObject& SetDefaultName(const gd::String& defaultName_) {
defaultName = defaultName_;
return *this;
}
EventsBasedObject& SetDescription(const gd::String& description_) override {
AbstractEventsBasedEntity::SetDescription(description_);
return *this;
}
/**
* \brief Set the internal name of the object.
*/
EventsBasedObject& SetName(const gd::String& name_) {
AbstractEventsBasedEntity::SetName(name_);
return *this;
}
/**
* \brief Set the name of the object, to be displayed in the editor.
*/
EventsBasedObject& SetFullName(const gd::String& fullName_) {
AbstractEventsBasedEntity::SetFullName(fullName_);
return *this;
}
/**
* \brief Set that the object is private - it can't be used outside of its
* extension.
*/
EventsBasedObject& SetPrivate(bool isPrivate) {
AbstractEventsBasedEntity::SetPrivate(isPrivate);
return *this;
}
/**
* \brief Declare a usage of the 3D renderer.
*/
EventsBasedObject& MarkAsRenderedIn3D(bool isRenderedIn3D_) {
isRenderedIn3D = isRenderedIn3D_;
return *this;
}
/**
* \brief Return true if the object uses the 3D renderer.
*/
bool IsRenderedIn3D() const { return isRenderedIn3D; }
/**
* \brief Declare an Animatable capability.
*/
EventsBasedObject& MarkAsAnimatable(bool isAnimatable_) {
isAnimatable = isAnimatable_;
return *this;
}
/**
* \brief Return true if the object needs an Animatable capability.
*/
bool IsAnimatable() const { return isAnimatable; }
/**
* \brief Declare a TextContainer capability.
*/
EventsBasedObject &MarkAsTextContainer(bool isTextContainer_) {
isTextContainer = isTextContainer_;
return *this;
}
/**
* \brief Declare that the parent scale will always be 1 and children will
* adapt there size. This is removing the ScalableCapability.
*/
EventsBasedObject &
MarkAsInnerAreaFollowingParentSize(bool isInnerAreaExpandingWithParent_) {
isInnerAreaFollowingParentSize = isInnerAreaExpandingWithParent_;
return *this;
}
/**
* \brief Return true if objects handle size changes on their own and
* don't have the ScalableCapability.
*
* When the parent dimensions change:
* - if `false`, the object is stretch proportionally while children local
* positions stay the same.
* - if `true`, the children local positions need to be adapted by events
* to follow their parent size.
*/
bool IsInnerAreaFollowingParentSize() const {
return isInnerAreaFollowingParentSize;
}
/**
* \brief Declare that custom object are rendered using their child-objects
* instead of their child-instances.
*/
EventsBasedObject &
MakAsUsingLegacyInstancesRenderer(bool isUsingLegacyInstancesRenderer_) {
isUsingLegacyInstancesRenderer = isUsingLegacyInstancesRenderer_;
return *this;
}
/**
* \brief Return true if custom object are rendered using their child-objects
* instead of their child-instances.
*/
bool IsUsingLegacyInstancesRenderer() const {
return isUsingLegacyInstancesRenderer;
}
/**
* \brief Return true if the object needs a TextContainer capability.
*/
bool IsTextContainer() const { return isTextContainer; }
/**
* \brief Get the default variant of the custom object.
*/
const gd::EventsBasedObjectVariant& GetDefaultVariant() const { return defaultVariant; }
/**
* \brief Get the default variant of the custom object.
*/
gd::EventsBasedObjectVariant& GetDefaultVariant() { return defaultVariant; }
/**
* \brief Get the variants of the custom object.
*/
const gd::EventsBasedObjectVariantsContainer& GetVariants() const { return variants; }
/**
* \brief Get the variants of the custom object.
*/
gd::EventsBasedObjectVariantsContainer& GetVariants() { return variants; }
/** \name Layers
*/
///@{
/**
* \brief Get the layers of the custom object.
*/
const gd::LayersContainer& GetLayers() const { return defaultVariant.GetLayers(); }
/**
* \brief Get the layers of the custom object.
*/
gd::LayersContainer& GetLayers() { return defaultVariant.GetLayers(); }
///@}
/** \name Child objects
*/
///@{
/**
* \brief Get the objects of the custom object.
*/
gd::ObjectsContainer& GetObjects() {
return defaultVariant.GetObjects();
}
/**
* \brief Get the objects of the custom object.
*/
const gd::ObjectsContainer& GetObjects() const {
return defaultVariant.GetObjects();
}
///@}
/** \name Instances
*/
///@{
/**
* \brief Get the instances of the custom object.
*/
gd::InitialInstancesContainer& GetInitialInstances() {
return defaultVariant.GetInitialInstances();
}
/**
* \brief Get the instances of the custom object.
*/
const gd::InitialInstancesContainer& GetInitialInstances() const {
return defaultVariant.GetInitialInstances();
}
/**
* \brief Get the left bound of the custom object.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMinX() const {
return defaultVariant.GetAreaMinX();
}
/**
* \brief Set the left bound of the custom object.
*/
void SetAreaMinX(int areaMinX) {
defaultVariant.SetAreaMinX(areaMinX);
}
/**
* \brief Get the top bound of the custom object.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMinY() const {
return defaultVariant.GetAreaMinY();
}
/**
* \brief Set the top bound of the custom object.
*/
void SetAreaMinY(int areaMinY) {
defaultVariant.SetAreaMinY(areaMinY);
}
/**
* \brief Get the min Z bound of the custom object.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMinZ() const {
return defaultVariant.GetAreaMinZ();
}
/**
* \brief Set the min Z bound of the custom object.
*/
void SetAreaMinZ(int areaMinZ) {
defaultVariant.SetAreaMinZ(areaMinZ);
}
/**
* \brief Get the right bound of the custom object.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMaxX() const {
return defaultVariant.GetAreaMaxX();
}
/**
* \brief Set the right bound of the custom object.
*/
void SetAreaMaxX(int areaMaxX) {
defaultVariant.SetAreaMaxX(areaMaxX);
}
/**
* \brief Get the bottom bound of the custom object.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMaxY() const {
return defaultVariant.GetAreaMaxY();
}
/**
* \brief Set the bottom bound of the custom object.
*/
void SetAreaMaxY(int areaMaxY) {
defaultVariant.SetAreaMaxY(areaMaxY);
}
/**
* \brief Get the max Z bound of the custom object.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMaxZ() const {
return defaultVariant.GetAreaMaxZ();
}
/**
* \brief Set the bottom bound of the custom object.
*/
void SetAreaMaxZ(int areaMaxZ) {
defaultVariant.SetAreaMaxZ(areaMaxZ);
}
///@}
/**
* @brief Serialize the events-based object for an extension in an external file.
* Variants are not serialized.
*/
void SerializeToExternal(SerializerElement& element) const;
void SerializeTo(SerializerElement& element) const override;
void UnserializeFrom(gd::Project& project,
const SerializerElement& element) override;
private:
gd::String defaultName;
bool isRenderedIn3D;
bool isAnimatable;
bool isTextContainer;
bool isInnerAreaFollowingParentSize;
bool isUsingLegacyInstancesRenderer;
gd::EventsBasedObjectVariant defaultVariant;
gd::EventsBasedObjectVariantsContainer variants;
};
} // namespace gd