mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
1 Commits
v5.0.0-bet
...
clean/gdcp
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2b60377820 |
@@ -13,6 +13,5 @@
|
||||
-fPIC
|
||||
-I./ExtLibs/SFML/include
|
||||
-I./Core
|
||||
-I./GDCpp/.
|
||||
-I./GDJS/.
|
||||
-F./ExtLibs/SFML/extlibs/libs-osx/Frameworks
|
||||
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1,6 +1,5 @@
|
||||
Core/GDCore/Serialization/rapidjson/rapidjson.h/* linguist-vendored
|
||||
Core/GDCore/TinyXml/* linguist-vendored
|
||||
GDCpp/GDCpp/Runtime/TinyXml/* linguist-vendored
|
||||
Extensions/ParticleSystem/SPARK/* linguist-vendored
|
||||
Extensions/PhysicsBehavior/Box2D/* linguist-vendored
|
||||
Extensions/PhysicsBehavior/box2djs/* linguist-vendored
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,7 +16,6 @@
|
||||
*.bc
|
||||
/Binaries/Output
|
||||
*.autosave
|
||||
!/GDCpp/scripts/bcp.exe
|
||||
!/scripts/libgettextlib-0-17.dll
|
||||
!/scripts/libgettextsrc-0-17.dll
|
||||
!/xgettext.exe
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# Travis CI configuration to build and run all tests
|
||||
# (and typing/formatting) for the Core, newIDE, GDJS (and even GDCpp).
|
||||
# (and typing/formatting) for the Core, newIDE, GDJS.
|
||||
#
|
||||
# This builds GDevelop.js and store it on a S3 so it can be used to run
|
||||
# GDevelop without building it.
|
||||
@@ -62,7 +62,7 @@ before_install:
|
||||
install:
|
||||
#Get the correct version of gcc/g++
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}"; fi
|
||||
#Compile the tests only for GDCore and GDCpp
|
||||
#Compile the tests only for GDCore
|
||||
- mkdir .build-tests
|
||||
- cd .build-tests
|
||||
- cmake -DBUILD_GDJS=FALSE -DBUILD_TESTS=TRUE -DCMAKE_CXX_COMPILER=$(which $CXX) -DCMAKE_C_COMPILER=$(which $CC) ..
|
||||
@@ -89,12 +89,9 @@ install:
|
||||
- cd ../..
|
||||
|
||||
script:
|
||||
# GDCore and GDCpp game engine tests:
|
||||
# GDCore tests:
|
||||
- cd .build-tests
|
||||
- Core/GDCore_tests
|
||||
- GDCpp/GDCpp_tests
|
||||
- Extensions/PathfindingBehavior/PathfindingBehavior_Runtime_tests
|
||||
- Extensions/LinkedObjects/LinkedObjects_Runtime_tests
|
||||
- cd ..
|
||||
# GDevelop.js tests
|
||||
- cd GDevelop.js
|
||||
|
3
.vscode/c_cpp_properties.json
vendored
3
.vscode/c_cpp_properties.json
vendored
@@ -4,7 +4,6 @@
|
||||
"name": "Mac",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
@@ -43,7 +42,6 @@
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
@@ -70,7 +68,6 @@
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
|
@@ -1,3 +1,3 @@
|
||||
This is the directory where native or WebAssembly binaries of the C++ code of GDCore, GDCpp and GDJS are produced.
|
||||
This is the directory where native or WebAssembly binaries of the C++ code of GDCore and GDJS are produced.
|
||||
|
||||
See GDevelop.js README for the instructions to compile after a change in the C++ source code.
|
@@ -92,9 +92,6 @@ ENDIF()
|
||||
IF(BUILD_GDJS)
|
||||
ADD_SUBDIRECTORY(GDJS)
|
||||
ENDIF()
|
||||
IF(BUILD_GDCPP)
|
||||
ADD_SUBDIRECTORY(GDCpp)
|
||||
ENDIF()
|
||||
IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/GDevelop.js/CMakeLists.txt" AND EMSCRIPTEN)
|
||||
ADD_SUBDIRECTORY(GDevelop.js)
|
||||
ENDIF()
|
||||
|
@@ -14,9 +14,8 @@
|
||||
*
|
||||
* \section other Other documentations
|
||||
*
|
||||
* GDevelop is architectured around a `Core` (this library), platforms (`GDJS`, `GDCpp`) and extensions (`Extensions` folder). The editor (`newIDE` folder) is using all of these libraries.
|
||||
* GDevelop is architectured around a `Core` (this library), a game engine (`GDJS`) and extensions (`Extensions` folder). The editor (`newIDE` folder) is using all of these libraries.
|
||||
*
|
||||
* - [Open GDevelop C++ Platform documentation](../GDCpp Documentation/index.html)
|
||||
* - [Open GDevelop JS Platform documentation](../GDJS Documentation/index.html)
|
||||
* - <a href="https://github.com/4ian/GDevelop/blob/master/newIDE/README.md">Getting started with the editor</a>
|
||||
* - <a href="https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md">Getting started with the extensions</a>
|
||||
|
@@ -462,24 +462,21 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
* Other standard parameters type that should be implemented by platforms:
|
||||
* - currentScene: Reference to the current runtime scene.
|
||||
* - objectList : a map containing lists of objects which are specified by the
|
||||
object name in another parameter. (C++: std::map <gd::String,
|
||||
std::vector<RuntimeObject*> *>). Example:
|
||||
object name in another parameter. Example:
|
||||
* \code
|
||||
AddExpression("Count", _("Object count"), _("Count the number of picked
|
||||
objects"), _("Objects"), "res/conditions/nbObjet.png")
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.SetFunctionName("PickedObjectsCount").SetIncludeFile("GDCpp/Extensions/Builtin/ObjectTools.h");
|
||||
.SetFunctionName("getPickedObjectsCount");
|
||||
|
||||
* \endcode
|
||||
* - objectListWithoutPicking : Same as objectList but do not pick object if
|
||||
they are not already picked.
|
||||
* - objectPtr : Return a pointer to object specified by the object name in
|
||||
another parameter ( C++: RuntimeObject* ). Example:
|
||||
* - objectPtr : Return a reference to the object specified by the object name in
|
||||
another parameter. Example:
|
||||
* \code
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectPtr", _("Target object"))
|
||||
//The called function will be called with this signature on the C++ platform:
|
||||
Function(gd::String, RuntimeObject*)
|
||||
* \endcode
|
||||
*/
|
||||
virtual gd::String GenerateParameterCodes(
|
||||
|
@@ -16,7 +16,6 @@
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class EventsList;
|
||||
class MainFrameWrapper;
|
||||
class Project;
|
||||
class Layout;
|
||||
class EventsCodeGenerator;
|
||||
|
@@ -7,7 +7,6 @@
|
||||
#include <SFML/Graphics/Sprite.hpp>
|
||||
#include <iostream>
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
|
||||
#include "GDCore/Project/ImageManager.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -16,11 +15,7 @@ namespace gd {
|
||||
Point Sprite::badPoint("");
|
||||
|
||||
Sprite::Sprite()
|
||||
:
|
||||
#if !defined(EMSCRIPTEN)
|
||||
hasItsOwnImage(false),
|
||||
#endif
|
||||
automaticCollisionMask(true),
|
||||
: automaticCollisionMask(true),
|
||||
origine("origine"),
|
||||
centre("centre"),
|
||||
automaticCentre(true) {
|
||||
@@ -73,36 +68,10 @@ Point& Sprite::GetPoint(const gd::String& name) {
|
||||
|
||||
bool Sprite::SetDefaultCenterPoint(bool enabled) {
|
||||
automaticCentre = enabled;
|
||||
|
||||
#if !defined(EMSCRIPTEN)
|
||||
if (automaticCentre)
|
||||
centre.SetXY(sfmlSprite.getLocalBounds().width / 2,
|
||||
sfmlSprite.getLocalBounds().height / 2);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Polygon2d> Sprite::GetCollisionMask() const {
|
||||
// TODO(perf): Cache to avoid re-creating a mask at every call
|
||||
#if !defined(EMSCRIPTEN)
|
||||
if (automaticCollisionMask) {
|
||||
std::vector<Polygon2d> mask;
|
||||
|
||||
Polygon2d rectangle;
|
||||
rectangle.vertices.push_back(sf::Vector2f(0, 0));
|
||||
rectangle.vertices.push_back(
|
||||
sf::Vector2f(sfmlSprite.getLocalBounds().width, 0));
|
||||
rectangle.vertices.push_back(sf::Vector2f(
|
||||
sfmlSprite.getLocalBounds().width, sfmlSprite.getLocalBounds().height));
|
||||
rectangle.vertices.push_back(
|
||||
sf::Vector2f(0, sfmlSprite.getLocalBounds().height));
|
||||
|
||||
mask.push_back(rectangle);
|
||||
return mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
return customCollisionMask;
|
||||
}
|
||||
|
||||
@@ -111,25 +80,4 @@ void Sprite::SetCustomCollisionMask(
|
||||
customCollisionMask = collisionMask;
|
||||
}
|
||||
|
||||
#if !defined(EMSCRIPTEN)
|
||||
void Sprite::LoadImage(std::shared_ptr<SFMLTextureWrapper> image_) {
|
||||
sfmlImage = image_;
|
||||
sfmlSprite.setTexture(sfmlImage->texture, true);
|
||||
hasItsOwnImage = false;
|
||||
|
||||
if (automaticCentre)
|
||||
centre.SetXY(sfmlSprite.getLocalBounds().width / 2,
|
||||
sfmlSprite.getLocalBounds().height / 2);
|
||||
}
|
||||
|
||||
void Sprite::MakeSpriteOwnsItsImage() {
|
||||
if (!hasItsOwnImage || sfmlImage == std::shared_ptr<SFMLTextureWrapper>()) {
|
||||
sfmlImage = std::make_shared<SFMLTextureWrapper>(
|
||||
sfmlImage->texture); // Copy the texture.
|
||||
sfmlSprite.setTexture(sfmlImage->texture);
|
||||
hasItsOwnImage = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -11,7 +11,6 @@
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
|
||||
#include "GDCore/String.h"
|
||||
class SFMLTextureWrapper;
|
||||
#undef LoadImage // prevent windows.h to be polluting everything
|
||||
|
||||
namespace gd {
|
||||
@@ -19,9 +18,6 @@ namespace gd {
|
||||
/**
|
||||
* \brief Represents a sprite to be displayed on the screen.
|
||||
*
|
||||
* A sprite contains a SFML sprite to be displayed, some points,
|
||||
* and can also have its own texture (rather than a texture from ImageManager).
|
||||
*
|
||||
* \see Direction
|
||||
* \see SpriteObject
|
||||
* \ingroup SpriteObjectExtension
|
||||
@@ -163,53 +159,7 @@ class GD_CORE_API Sprite {
|
||||
*/
|
||||
bool SetDefaultCenterPoint(bool enabled);
|
||||
|
||||
#if !defined(EMSCRIPTEN)
|
||||
/** \name Sprite runtime management
|
||||
* Functions used by the C++ game engine.
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Get the SFML sprite associated with the sprite
|
||||
*/
|
||||
inline const sf::Sprite& GetSFMLSprite() const { return sfmlSprite; }
|
||||
|
||||
/**
|
||||
* \brief Get the SFML sprite associated with the sprite
|
||||
*/
|
||||
inline sf::Sprite& GetSFMLSprite() { return sfmlSprite; }
|
||||
|
||||
/**
|
||||
* \brief Set the SFML texture of the sprite
|
||||
*/
|
||||
void LoadImage(std::shared_ptr<SFMLTextureWrapper> image);
|
||||
|
||||
/**
|
||||
* \brief Get SFML texture used by the sprite
|
||||
*/
|
||||
std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture() { return sfmlImage; };
|
||||
|
||||
/**
|
||||
* \brief Get SFML texture used by the sprite
|
||||
*/
|
||||
const std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture() const {
|
||||
return sfmlImage;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Make the sprite, if it uses a texture from ImageManager,
|
||||
* copy this texture and take ownership of it.
|
||||
*/
|
||||
void MakeSpriteOwnsItsImage();
|
||||
///@}
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if !defined(EMSCRIPTEN)
|
||||
sf::Sprite sfmlSprite; ///< Displayed SFML sprite
|
||||
std::shared_ptr<SFMLTextureWrapper>
|
||||
sfmlImage; ///< Pointer to the image displayed by the sprite.
|
||||
bool hasItsOwnImage; ///< True if sfmlImage is only owned by this Sprite.
|
||||
#endif
|
||||
gd::String image; ///< Name of the image to be loaded in Image Manager.
|
||||
|
||||
bool automaticCollisionMask; ///< True to use the custom collision mask.
|
||||
|
@@ -334,39 +334,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
.UseStandardRelationalOperatorParameters("number")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("CopyImageOnImageOfSprite",
|
||||
_("Copy an image on the current one of an object"),
|
||||
_("Copy an image on the current image of an object.\nNote that "
|
||||
"the source image must be preferably kept loaded in memory."),
|
||||
_("Copy image _PARAM2_ on the current of _PARAM0_ at "
|
||||
"_PARAM3_;_PARAM4_"),
|
||||
_("Effects"),
|
||||
"res/copy24.png",
|
||||
"res/copyicon.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Name of the source image"))
|
||||
.AddParameter("expression", _("X position"))
|
||||
.AddParameter("expression", _("Y position"))
|
||||
.AddParameter(
|
||||
"yesorno",
|
||||
_("Should the copy take in account the source transparency\?"));
|
||||
|
||||
obj.AddAction(
|
||||
"CreateMaskFromColorOnActualImage", // Actual is indeed a mistake :
|
||||
// Current should have been
|
||||
// chosen.
|
||||
_("Make a color of the image of an object transparent"),
|
||||
_("Make a color of the image of an object transparent."),
|
||||
_("Make color _PARAM1_ of the current image of _PARAM0_ transparent"),
|
||||
_("Effects"),
|
||||
"res/actions/opacity24.png",
|
||||
"res/actions/opacity.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("color", _("Color to make transparent"));
|
||||
|
||||
obj.AddAction("ChangeColor",
|
||||
_("Tint color"),
|
||||
_("Change the tint of an object. The default color is white."),
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
|
||||
#include "GDCore/Project/ImageManager.h"
|
||||
#include "GDCore/Project/InitialInstance.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
|
@@ -16,7 +16,6 @@ class Object;
|
||||
class Layout;
|
||||
class Sprite;
|
||||
class Animation;
|
||||
class MainFrameWrapper;
|
||||
class SerializerElement;
|
||||
class PropertyDescriptor;
|
||||
} // namespace gd
|
||||
|
@@ -27,50 +27,6 @@ namespace gd {
|
||||
|
||||
PlatformLoader::PlatformLoader() {}
|
||||
|
||||
void PlatformLoader::LoadAllPlatformsInManager(gd::String dir) {
|
||||
{
|
||||
#if defined(WINDOWS)
|
||||
std::shared_ptr<gd::Platform> platform = LoadPlatformInManager("GDCpp.dll");
|
||||
#elif defined(LINUX)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("libGDCpp.so");
|
||||
#elif defined(MACOS)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("libGDCpp.dylib");
|
||||
#else
|
||||
#warning Add the appropriate filename here for the C++ Platform!
|
||||
std::shared_ptr<gd::Platform> platform;
|
||||
#endif
|
||||
if (platform)
|
||||
gd::ExtensionsLoader::LoadAllExtensions("./CppPlatform/Extensions/",
|
||||
*platform);
|
||||
}
|
||||
|
||||
{
|
||||
#if defined(WINDOWS)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("./JsPlatform/GDJS.dll");
|
||||
#elif defined(LINUX)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("./JsPlatform/libGDJS.so");
|
||||
#elif defined(MACOS)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("./JsPlatform/libGDJS.dylib");
|
||||
#else
|
||||
#warning Add the appropriate filename here for the Js Platform!
|
||||
std::shared_ptr<gd::Platform> platform;
|
||||
#endif
|
||||
if (platform)
|
||||
gd::ExtensionsLoader::LoadAllExtensions("./JsPlatform/Extensions/",
|
||||
*platform);
|
||||
if (platform)
|
||||
gd::ExtensionsLoader::LoadAllExtensions(
|
||||
"./CppPlatform/Extensions/", *platform, true);
|
||||
}
|
||||
|
||||
gd::ExtensionsLoader::ExtensionsLoadingDone("./CppPlatform/Extensions/");
|
||||
}
|
||||
|
||||
std::shared_ptr<gd::Platform> PlatformLoader::LoadPlatformInManager(
|
||||
gd::String fullpath) {
|
||||
std::cout << "Loading platform " << fullpath << "..." << std::endl;
|
||||
|
@@ -30,15 +30,6 @@ passing
|
||||
*/
|
||||
class GD_CORE_API PlatformLoader {
|
||||
public:
|
||||
/**
|
||||
* Load all the platforms available in a directory.
|
||||
*
|
||||
* \param dir The directory where platforms must be searched for.
|
||||
*
|
||||
* \todo For now, only GDCpp.dll and GDJS.dll are loaded.
|
||||
*/
|
||||
static void LoadAllPlatformsInManager(gd::String dir);
|
||||
|
||||
/**
|
||||
* Load a specific platform.
|
||||
*
|
||||
|
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/Project/ImageManager.h"
|
||||
#include <SFML/OpenGL.hpp>
|
||||
#include "GDCore/Project/ResourcesLoader.h"
|
||||
#include "GDCore/Project/ResourcesManager.h"
|
||||
#include "GDCore/Tools/InvalidImage.h"
|
||||
#if !defined(ANDROID) && !defined(MACOS)
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
#undef LoadImage // thx windows.h
|
||||
|
||||
namespace gd {
|
||||
|
||||
ImageManager::ImageManager() : resourcesManager(NULL) {
|
||||
#if !defined(EMSCRIPTEN)
|
||||
badTexture = std::make_shared<SFMLTextureWrapper>();
|
||||
badTexture->texture.loadFromMemory(gd::InvalidImageData,
|
||||
sizeof(gd::InvalidImageData));
|
||||
badTexture->texture.setSmooth(false);
|
||||
badTexture->image = badTexture->texture.copyToImage();
|
||||
#endif
|
||||
}
|
||||
|
||||
std::shared_ptr<SFMLTextureWrapper> ImageManager::GetSFMLTexture(
|
||||
const gd::String& name) const {
|
||||
if (!resourcesManager) {
|
||||
std::cout << "ImageManager has no ResourcesManager associated with.";
|
||||
return badTexture;
|
||||
}
|
||||
|
||||
if (alreadyLoadedImages.find(name) != alreadyLoadedImages.end() &&
|
||||
!alreadyLoadedImages.find(name)->second.expired())
|
||||
return alreadyLoadedImages.find(name)->second.lock();
|
||||
|
||||
std::cout << "ImageManager: Loading " << name << ".";
|
||||
|
||||
// Load only an image when necessary
|
||||
try {
|
||||
ImageResource& image =
|
||||
dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
|
||||
|
||||
auto texture = std::make_shared<SFMLTextureWrapper>();
|
||||
ResourcesLoader::Get()->LoadSFMLImage(image.GetFile(), texture->image);
|
||||
texture->texture.loadFromImage(texture->image);
|
||||
texture->texture.setSmooth(image.smooth);
|
||||
|
||||
alreadyLoadedImages[name] = texture;
|
||||
#if defined(GD_IDE_ONLY)
|
||||
if (preventUnloading)
|
||||
unloadingPreventer.push_back(
|
||||
texture); // If unload prevention is activated, add the image to the
|
||||
// list dedicated to prevent images from being unloaded.
|
||||
#endif
|
||||
|
||||
return texture;
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
std::cout << " Resource not found." << std::endl;
|
||||
|
||||
return badTexture;
|
||||
}
|
||||
|
||||
bool ImageManager::HasLoadedSFMLTexture(const gd::String& name) const {
|
||||
if (alreadyLoadedImages.find(name) != alreadyLoadedImages.end() &&
|
||||
!alreadyLoadedImages.find(name)->second.expired())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImageManager::SetSFMLTextureAsPermanentlyLoaded(
|
||||
const gd::String& name,
|
||||
std::shared_ptr<SFMLTextureWrapper>& texture) const {
|
||||
if (alreadyLoadedImages.find(name) == alreadyLoadedImages.end() ||
|
||||
alreadyLoadedImages.find(name)->second.expired())
|
||||
alreadyLoadedImages[name] = texture;
|
||||
|
||||
if (permanentlyLoadedImages.find(name) == permanentlyLoadedImages.end())
|
||||
permanentlyLoadedImages[name] = texture;
|
||||
}
|
||||
|
||||
void ImageManager::ReloadImage(const gd::String& name) const {
|
||||
if (!resourcesManager) {
|
||||
std::cout << "ImageManager has no ResourcesManager associated with.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify if image is in memory. If not, it will be automatically reloaded
|
||||
// when necessary.
|
||||
if (alreadyLoadedImages.find(name) == alreadyLoadedImages.end() ||
|
||||
alreadyLoadedImages.find(name)->second.expired())
|
||||
return;
|
||||
|
||||
// Image still in memory, get it and update it.
|
||||
std::shared_ptr<SFMLTextureWrapper> oldTexture =
|
||||
alreadyLoadedImages.find(name)->second.lock();
|
||||
|
||||
try {
|
||||
ImageResource& image =
|
||||
dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
|
||||
|
||||
std::cout << "ImageManager: Reload " << name << std::endl;
|
||||
|
||||
ResourcesLoader::Get()->LoadSFMLImage(image.GetFile(), oldTexture->image);
|
||||
oldTexture->texture.loadFromImage(oldTexture->image);
|
||||
oldTexture->texture.setSmooth(image.smooth);
|
||||
|
||||
return;
|
||||
} catch (...) { /*The ressource is not an image*/
|
||||
}
|
||||
|
||||
// Image not present anymore in image list.
|
||||
std::cout << "ImageManager: " << name << " is not available anymore."
|
||||
<< std::endl;
|
||||
*oldTexture = *badTexture;
|
||||
}
|
||||
|
||||
std::shared_ptr<OpenGLTextureWrapper> ImageManager::GetOpenGLTexture(
|
||||
const gd::String& name) const {
|
||||
if (alreadyLoadedOpenGLTextures.find(name) !=
|
||||
alreadyLoadedOpenGLTextures.end() &&
|
||||
!alreadyLoadedOpenGLTextures.find(name)->second.expired())
|
||||
return alreadyLoadedOpenGLTextures.find(name)->second.lock();
|
||||
|
||||
std::cout << "Load OpenGL Texture" << name << std::endl;
|
||||
|
||||
std::shared_ptr<OpenGLTextureWrapper> texture =
|
||||
std::make_shared<OpenGLTextureWrapper>(GetSFMLTexture(name));
|
||||
alreadyLoadedOpenGLTextures[name] = texture;
|
||||
return texture;
|
||||
}
|
||||
|
||||
void ImageManager::LoadPermanentImages() {
|
||||
if (!resourcesManager) {
|
||||
std::cout << "ImageManager has no ResourcesManager associated with.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new list of permanently loaded images but do not delete now the
|
||||
// old list so as not to unload images that could be still present.
|
||||
std::map<gd::String, std::shared_ptr<SFMLTextureWrapper> >
|
||||
newPermanentlyLoadedImages;
|
||||
|
||||
std::vector<gd::String> resources = resourcesManager->GetAllResourceNames();
|
||||
for (std::size_t i = 0; i < resources.size(); i++) {
|
||||
try {
|
||||
ImageResource& image = dynamic_cast<ImageResource&>(
|
||||
resourcesManager->GetResource(resources[i]));
|
||||
|
||||
if (image.alwaysLoaded)
|
||||
newPermanentlyLoadedImages[image.GetName()] =
|
||||
GetSFMLTexture(image.GetName());
|
||||
} catch (...) { /*The resource is not an image, we don't care about it.*/
|
||||
}
|
||||
}
|
||||
|
||||
permanentlyLoadedImages = newPermanentlyLoadedImages;
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void ImageManager::PreventImagesUnloading() {
|
||||
preventUnloading = true;
|
||||
for (auto it = alreadyLoadedImages.begin(); it != alreadyLoadedImages.end();
|
||||
++it) {
|
||||
std::shared_ptr<SFMLTextureWrapper> image = (it->second).lock();
|
||||
if (image != std::shared_ptr<SFMLTextureWrapper>())
|
||||
unloadingPreventer.push_back(image);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageManager::EnableImagesUnloading() {
|
||||
preventUnloading = false;
|
||||
unloadingPreventer
|
||||
.clear(); // Images which are not used anymore will thus be destroyed (As
|
||||
// no shared pointer will be pointing to them).
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace gd
|
||||
|
||||
SFMLTextureWrapper::SFMLTextureWrapper(const sf::Texture& texture_)
|
||||
: texture(texture_), image(texture.copyToImage()) {}
|
||||
|
||||
SFMLTextureWrapper::SFMLTextureWrapper() {}
|
||||
|
||||
SFMLTextureWrapper::~SFMLTextureWrapper() {}
|
||||
|
||||
OpenGLTextureWrapper::OpenGLTextureWrapper(
|
||||
std::shared_ptr<SFMLTextureWrapper> sfmlTexture_) {
|
||||
sfmlTexture = sfmlTexture_;
|
||||
|
||||
#if !defined(ANDROID) // TODO: OpenGL
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sfmlTexture->image.getSize().x,
|
||||
// sfmlTexture->image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
// sfmlTexture->image.getPixelsPtr()); glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(
|
||||
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
#endif
|
||||
}
|
||||
|
||||
OpenGLTextureWrapper::~OpenGLTextureWrapper() {
|
||||
#if !defined(ANDROID) // TODO: OpenGL
|
||||
glDeleteTextures(1, &texture);
|
||||
#endif
|
||||
};
|
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef ImageManager_H
|
||||
#define ImageManager_H
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/OpenGL.hpp>
|
||||
#include <SFML/System.hpp>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class ResourcesManager;
|
||||
}
|
||||
class OpenGLTextureWrapper;
|
||||
class SFMLTextureWrapper;
|
||||
#undef LoadImage // thx windows.h
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Manage images for the IDE as well as at runtime for GD C++ Platform,
|
||||
* providing an easy way to get SFML images or OpenGL textures.
|
||||
*
|
||||
* Image manager is used by objects to obtain their images from the image name.
|
||||
*
|
||||
* Images are loaded dynamically when necessary, and are unloaded if there is no
|
||||
* more shared_ptr pointing on an image.
|
||||
*
|
||||
* You should in particular be interested by gd::ImageManager::GetOpenGLTexture
|
||||
* and gd::ImageManager::GetSFMLTexture.
|
||||
*
|
||||
* \see SFMLTextureWrapper
|
||||
* \see OpenGLTextureWrapper
|
||||
*
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API ImageManager {
|
||||
public:
|
||||
ImageManager();
|
||||
virtual ~ImageManager(){};
|
||||
|
||||
/**
|
||||
* \brief Get a shared pointer to an OpenGL texture. The shared pointer must
|
||||
* be kept alive as long as the texture is used.
|
||||
*/
|
||||
std::shared_ptr<OpenGLTextureWrapper> GetOpenGLTexture(
|
||||
const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Get a shared pointer to a SFML texture. The shared pointer must be
|
||||
* kept alive as long as the texture is used.
|
||||
*
|
||||
* For example, if the texture is used in an object, you should store the
|
||||
* shared pointer in a member to make sure the texture is available as long as
|
||||
* the object is alive.
|
||||
*/
|
||||
std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture(
|
||||
const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Set the gd::ResourcesManager used by the ImageManager.
|
||||
*/
|
||||
void SetResourcesManager(gd::ResourcesManager* resourcesManager_) {
|
||||
resourcesManager = resourcesManager_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Load all images of the project which are flagged as alwaysLoaded.
|
||||
* \see ImageResource
|
||||
*/
|
||||
void LoadPermanentImages();
|
||||
|
||||
/**
|
||||
* \brief Check if a SFML texture with the specified name is available and
|
||||
* loaded in memory. \return true if the texture called \a name if available
|
||||
* and loaded in memory.
|
||||
*/
|
||||
bool HasLoadedSFMLTexture(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Add the SFMLTextureWrapper to loaded images ( so that it can be
|
||||
* accessed thanks to ImageManager::GetSFMLTexture ) with the specified name
|
||||
* and mark it as permanently loaded ( so that is is unloaded only when the
|
||||
* layout is unloaded ).
|
||||
*/
|
||||
void SetSFMLTextureAsPermanentlyLoaded(
|
||||
const gd::String& name,
|
||||
std::shared_ptr<SFMLTextureWrapper>& texture) const;
|
||||
|
||||
/**
|
||||
* \brief Reload a single image from the game resources
|
||||
*/
|
||||
void ReloadImage(const gd::String& name) const;
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief When called, images won't be unloaded from memory until
|
||||
* EnableImagesUnloading is called. Can be used when reloading a layout so as
|
||||
* to prevent images from being unloaded and then immediately reloaded.
|
||||
*/
|
||||
void PreventImagesUnloading();
|
||||
|
||||
/**
|
||||
* \brief Enable again unused images to be unloaded from memory.
|
||||
*/
|
||||
void EnableImagesUnloading();
|
||||
#endif
|
||||
|
||||
private:
|
||||
mutable std::map<gd::String, std::weak_ptr<SFMLTextureWrapper> >
|
||||
alreadyLoadedImages; ///< Reference all images loaded in memory.
|
||||
mutable std::map<gd::String, std::shared_ptr<SFMLTextureWrapper> >
|
||||
permanentlyLoadedImages; ///< Contains (smart) pointers to images which
|
||||
///< should stay loaded even if they are not
|
||||
///< (currently) used.
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
|
||||
/** This list is filled, when PreventImagesUnloading is called, with images
|
||||
* already loaded in memory ( and any image loaded after the call to
|
||||
* PreventImagesUnloading ). It will thus prevent these images from being
|
||||
* unloaded. This list is destroyed when EnableImagesUnloading is called.
|
||||
*
|
||||
* \see PreventImagesUnloading
|
||||
* \see EnableImagesUnloading
|
||||
*/
|
||||
mutable std::vector<std::shared_ptr<SFMLTextureWrapper> > unloadingPreventer;
|
||||
bool preventUnloading; ///< True if no images must be currently unloaded.
|
||||
#endif
|
||||
|
||||
mutable std::map<gd::String, std::weak_ptr<OpenGLTextureWrapper> >
|
||||
alreadyLoadedOpenGLTextures; ///< Reference all OpenGL textures loaded in
|
||||
///< memory.
|
||||
|
||||
mutable std::shared_ptr<SFMLTextureWrapper> badTexture;
|
||||
mutable std::shared_ptr<OpenGLTextureWrapper> badOpenGLTexture;
|
||||
|
||||
gd::ResourcesManager* resourcesManager;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
/**
|
||||
* \brief Class wrapping an SFML texture.
|
||||
*
|
||||
* \see gd::ImageManager
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API SFMLTextureWrapper {
|
||||
public:
|
||||
SFMLTextureWrapper(const sf::Texture& texture);
|
||||
SFMLTextureWrapper();
|
||||
~SFMLTextureWrapper();
|
||||
|
||||
sf::Texture texture;
|
||||
sf::Image image; ///< Associated sfml image, used for pixel perfect collision
|
||||
///< for example. If you update the image, call
|
||||
///< LoadFromImage on texture to update it also.
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class wrapping an OpenGL texture.
|
||||
*
|
||||
* \see gd::ImageManager
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API OpenGLTextureWrapper {
|
||||
public:
|
||||
OpenGLTextureWrapper(std::shared_ptr<SFMLTextureWrapper> sfmlTexture_);
|
||||
OpenGLTextureWrapper() : texture(0){};
|
||||
~OpenGLTextureWrapper();
|
||||
inline GLuint GetOpenGLTexture() const { return texture; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<SFMLTextureWrapper> sfmlTexture;
|
||||
GLuint texture;
|
||||
};
|
||||
|
||||
#endif // ImageManager_H
|
@@ -26,7 +26,6 @@
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/Project/ExternalLayout.h"
|
||||
#include "GDCore/Project/ImageManager.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectGroupsContainer.h"
|
||||
@@ -67,23 +66,16 @@ Project::Project()
|
||||
adaptGameResolutionAtRuntime(true),
|
||||
sizeOnStartupMode("adaptWidth"),
|
||||
projectUuid(""),
|
||||
useDeprecatedZeroAsDefaultZOrder(false),
|
||||
imageManager(std::make_shared<ImageManager>())
|
||||
useDeprecatedZeroAsDefaultZOrder(false)
|
||||
#if defined(GD_IDE_ONLY)
|
||||
,
|
||||
useExternalSourceFiles(false),
|
||||
currentPlatform(NULL),
|
||||
gdMajorVersion(gd::VersionWrapper::Major()),
|
||||
gdMinorVersion(gd::VersionWrapper::Minor()),
|
||||
gdBuildVersion(gd::VersionWrapper::Build()),
|
||||
dirty(false)
|
||||
gdBuildVersion(gd::VersionWrapper::Build())
|
||||
#endif
|
||||
{
|
||||
imageManager->SetResourcesManager(&resourcesManager);
|
||||
|
||||
#if !defined(GD_IDE_ONLY)
|
||||
platforms.push_back(&CppPlatform::Get());
|
||||
#endif
|
||||
}
|
||||
|
||||
Project::~Project() {}
|
||||
@@ -823,10 +815,6 @@ void Project::SerializeTo(SerializerElement& element) const {
|
||||
for (std::size_t i = 0; i < externalSourceFiles.size(); ++i)
|
||||
externalSourceFiles[i]->SerializeTo(
|
||||
externalSourceFilesElement.AddChild("sourceFile"));
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
dirty = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Project::ValidateName(const gd::String& name) {
|
||||
@@ -969,9 +957,7 @@ void Project::Init(const gd::Project& game) {
|
||||
platforms = game.platforms;
|
||||
|
||||
resourcesManager = game.resourcesManager;
|
||||
imageManager = std::make_shared<ImageManager>(*game.imageManager);
|
||||
imageManager->SetResourcesManager(&resourcesManager);
|
||||
|
||||
|
||||
initialObjects = gd::Clone(game.initialObjects);
|
||||
|
||||
scenes = gd::Clone(game.scenes);
|
||||
@@ -993,7 +979,6 @@ void Project::Init(const gd::Project& game) {
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
projectFile = game.GetProjectFile();
|
||||
imagesChanged = game.imagesChanged;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -28,7 +28,6 @@ class Object;
|
||||
class VariablesContainer;
|
||||
class ArbitraryResourceWorker;
|
||||
class SourceFile;
|
||||
class ImageManager;
|
||||
class Behavior;
|
||||
class BehaviorsSharedData;
|
||||
class BaseEvent;
|
||||
@@ -498,19 +497,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Return true if the project is marked as being modified (The IDE or
|
||||
* application using the project should ask to save the project if the project
|
||||
* is closed).
|
||||
*/
|
||||
bool IsDirty() { return dirty; }
|
||||
|
||||
/**
|
||||
* \brief Mark the project as being modified (The IDE or application
|
||||
* using the project should ask to save the project if the project is closed).
|
||||
*/
|
||||
void SetDirty(bool enable = true) { dirty = enable; }
|
||||
|
||||
/**
|
||||
* Get the major version of GDevelop used to save the project.
|
||||
*/
|
||||
@@ -792,28 +778,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
*/
|
||||
ResourcesManager& GetResourcesManager() { return resourcesManager; }
|
||||
|
||||
/**
|
||||
* \brief Provide access to the ImageManager allowing to load SFML or OpenGL
|
||||
* textures for the IDE ( or at runtime for the GD C++ Platform ).
|
||||
*/
|
||||
const std::shared_ptr<gd::ImageManager>& GetImageManager() const {
|
||||
return imageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Provide access to the ImageManager allowing to load SFML or OpenGL
|
||||
* textures for the IDE ( or at runtime for the GD C++ Platform ).
|
||||
*/
|
||||
std::shared_ptr<gd::ImageManager>& GetImageManager() { return imageManager; }
|
||||
|
||||
/**
|
||||
* \brief Provide access to the ImageManager allowing to load SFML or OpenGL
|
||||
* textures for the IDE ( or at runtime for the GD C++ Platform ).
|
||||
*/
|
||||
void SetImageManager(std::shared_ptr<gd::ImageManager> imageManager_) {
|
||||
imageManager = imageManager_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Called ( e.g. during compilation ) so as to inventory internal
|
||||
* resources, sometimes update their filename or any other work or resources.
|
||||
@@ -910,12 +874,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
#endif
|
||||
///@}
|
||||
|
||||
// TODO: Put this in private part
|
||||
#if defined(GD_IDE_ONLY)
|
||||
std::vector<gd::String> imagesChanged; ///< Images that have been changed and
|
||||
///< which have to be reloaded
|
||||
#endif
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize from another game. Used by copy-ctor and assign-op.
|
||||
@@ -954,9 +912,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
#endif
|
||||
gd::ResourcesManager
|
||||
resourcesManager; ///< Contains all resources used by the project
|
||||
std::shared_ptr<gd::ImageManager>
|
||||
imageManager; ///< Image manager is accessed thanks to a (smart) ptr as
|
||||
///< it can be shared with GD C++ Platform projects.
|
||||
std::vector<gd::Platform*>
|
||||
platforms; ///< Pointers to the platforms this project supports.
|
||||
gd::String firstLayout;
|
||||
@@ -987,7 +942,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
///< time the project was saved.
|
||||
mutable unsigned int gdBuildVersion; ///< The GD build version used the last
|
||||
///< time the project was saved.
|
||||
mutable bool dirty; ///< True to flag the project as being modified.
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@@ -1,108 +0,0 @@
|
||||
#include "GDCore/Project/ResourcesLoader.h"
|
||||
#include <SFML/Audio.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/FileStream.h"
|
||||
#undef LoadImage // Undef a macro from windows.h
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
ResourcesLoader *ResourcesLoader::_singleton = NULL;
|
||||
|
||||
void ResourcesLoader::LoadSFMLImage(const gd::String &filename,
|
||||
sf::Image &image) {
|
||||
gd::SFMLFileStream stream;
|
||||
if (!stream.open(filename) || !image.loadFromStream(stream))
|
||||
cout << "Failed to load a SFML image: " << filename << endl;
|
||||
}
|
||||
|
||||
sf::Texture ResourcesLoader::LoadSFMLTexture(const gd::String &filename) {
|
||||
sf::Texture texture;
|
||||
LoadSFMLTexture(filename, texture);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void ResourcesLoader::LoadSFMLTexture(const gd::String &filename,
|
||||
sf::Texture &texture) {
|
||||
gd::SFMLFileStream stream;
|
||||
if (!stream.open(filename) || !texture.loadFromStream(stream))
|
||||
cout << "Failed to load a SFML texture: " << filename << endl;
|
||||
}
|
||||
|
||||
std::pair<sf::Font *, StreamHolder *> ResourcesLoader::LoadFont(
|
||||
const gd::String &filename) {
|
||||
sf::Font *font = new sf::Font();
|
||||
StreamHolder *streamHolder = new StreamHolder();
|
||||
|
||||
if (!streamHolder->stream.open(filename) ||
|
||||
!font->loadFromStream(streamHolder->stream)) {
|
||||
cout << "Failed to load a font from a file: " << filename << endl;
|
||||
delete font;
|
||||
delete streamHolder;
|
||||
return std::make_pair((sf::Font *)nullptr, (StreamHolder *)nullptr);
|
||||
}
|
||||
|
||||
return std::make_pair(font, streamHolder);
|
||||
}
|
||||
|
||||
sf::SoundBuffer ResourcesLoader::LoadSoundBuffer(const gd::String &filename) {
|
||||
sf::SoundBuffer sbuffer;
|
||||
gd::SFMLFileStream stream;
|
||||
if (!stream.open(filename) || !sbuffer.loadFromStream(stream))
|
||||
cout << "Failed to load a sound buffer: " << filename << endl;
|
||||
|
||||
return sbuffer;
|
||||
}
|
||||
|
||||
gd::String ResourcesLoader::LoadPlainText(const gd::String &filename) {
|
||||
gd::String text;
|
||||
gd::FileStream file(filename, ios::in);
|
||||
|
||||
if (!file.fail()) {
|
||||
std::string ligne;
|
||||
while (getline(file, ligne)) text += gd::String::FromUTF8(ligne) + "\n";
|
||||
|
||||
file.close();
|
||||
} else
|
||||
cout << "Failed to read a file: " << filename << endl;
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a binary text file
|
||||
*/
|
||||
char *ResourcesLoader::LoadBinaryFile(const gd::String &filename) {
|
||||
gd::FileStream file(filename, ios::in | ios::binary | ios::ate);
|
||||
if (file.is_open()) {
|
||||
iostream::pos_type size = file.tellg();
|
||||
char *memblock = new char[size];
|
||||
file.seekg(0, ios::beg);
|
||||
file.read(memblock, size);
|
||||
file.close();
|
||||
|
||||
return memblock;
|
||||
}
|
||||
|
||||
cout << "Binary file " << filename << " can't be loaded into memory " << endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long int ResourcesLoader::GetBinaryFileSize(const gd::String &filename) {
|
||||
gd::FileStream file(filename, ios::in | ios::binary | ios::ate);
|
||||
if (file.is_open()) {
|
||||
return file.tellg();
|
||||
}
|
||||
|
||||
std::cout << "Binary file " << filename << " cannot be read. " << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef RESSOURCESLOADER_H
|
||||
#define RESSOURCESLOADER_H
|
||||
#include <SFML/Audio.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/FileStream.h"
|
||||
#undef LoadImage // Undef macro from windows.h
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief A class holding a buffer and/or a file stream (useful for SFML classes
|
||||
* that needs their buffer/stream continuously opened)
|
||||
*/
|
||||
struct StreamHolder {
|
||||
StreamHolder() : buffer(nullptr), stream() {}
|
||||
~StreamHolder() {
|
||||
if (buffer) delete buffer;
|
||||
}
|
||||
|
||||
char *buffer;
|
||||
gd::SFMLFileStream stream;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class used by games to load resources from files: this is purely an
|
||||
* abstraction to most SFML loadFrom* functions.
|
||||
*
|
||||
* This class is replaced in GDCpp by an equivalent that can load also from
|
||||
* memory.
|
||||
*
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API ResourcesLoader {
|
||||
public:
|
||||
void LoadSFMLImage(const gd::String &filename, sf::Image &image);
|
||||
|
||||
/**
|
||||
* Load a SFML texture.
|
||||
*/
|
||||
sf::Texture LoadSFMLTexture(const gd::String &filename);
|
||||
void LoadSFMLTexture(const gd::String &filename, sf::Texture &texture);
|
||||
|
||||
/**
|
||||
* Load a SFML Font.
|
||||
* \warning The function calling LoadFont is the owner of the returned font
|
||||
* and buffer (if any): Don't forget to delete them after use.
|
||||
*
|
||||
* \return A pair containing the loaded font, or NULL if loading failed, and
|
||||
* the buffer that need to be kept alive while the font is used (can be NULL
|
||||
* if the font was loaded from a file).
|
||||
*/
|
||||
std::pair<sf::Font *, StreamHolder *> LoadFont(const gd::String &filename);
|
||||
|
||||
/**
|
||||
* Load a SFML Sound Buffer
|
||||
*/
|
||||
sf::SoundBuffer LoadSoundBuffer(const gd::String &filename);
|
||||
|
||||
/**
|
||||
* Load a plain text file
|
||||
*/
|
||||
gd::String LoadPlainText(const gd::String &filename);
|
||||
|
||||
/**
|
||||
* Get a buffer for file.
|
||||
* Be careful, the buffer will be invalided by any subsequent call to
|
||||
* Load[Something]. Make a copy of the buffer if you want it to stay alive
|
||||
* longer.
|
||||
*/
|
||||
char *LoadBinaryFile(const gd::String &filename);
|
||||
|
||||
/**
|
||||
* Get the size of a file
|
||||
*/
|
||||
long int GetBinaryFileSize(const gd::String &filename);
|
||||
|
||||
static ResourcesLoader *Get() {
|
||||
if (NULL == _singleton) {
|
||||
_singleton = new ResourcesLoader;
|
||||
}
|
||||
|
||||
return (static_cast<ResourcesLoader *>(_singleton));
|
||||
}
|
||||
|
||||
static void DestroySingleton() {
|
||||
if (NULL != _singleton) {
|
||||
delete _singleton;
|
||||
_singleton = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ResourcesLoader(){};
|
||||
virtual ~ResourcesLoader(){};
|
||||
|
||||
static ResourcesLoader *_singleton;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // RESSOURCESLOADER_H
|
@@ -9,12 +9,11 @@
|
||||
/** @file
|
||||
* Provide a way to mark strings to be translated.
|
||||
*
|
||||
* Strings to be translated in GDevelop Core codebase (and GDCpp),
|
||||
* Strings to be translated in GDevelop Core codebase
|
||||
* are marked with the underscore macro, for example: _("Hello World").
|
||||
*
|
||||
* The macro is then defined to be using the translation function
|
||||
* of the underlying platform (Emscripten for GDevelop 5,
|
||||
* no translation for GDCpp Runtime).
|
||||
* of the underlying platform (Emscripten for GDevelop 5).
|
||||
*/
|
||||
|
||||
#if defined(EMSCRIPTEN)
|
||||
@@ -33,7 +32,7 @@ gd::String GetTranslation(const char* str);
|
||||
#define _(s) gd::GetTranslation(u8##s)
|
||||
|
||||
#else
|
||||
// When compiling without Emscripten (typically for GDC++ Runtime),
|
||||
// When compiling without Emscripten,
|
||||
// just return an untranslated gd::String.
|
||||
|
||||
// Create a new macro to return UTF8 gd::String from a translation
|
||||
|
@@ -35,13 +35,6 @@ gd::String VersionWrapper::Year() {
|
||||
gd::String VersionWrapper::Status() {
|
||||
return Revision() == 0 ? "Release" : "Dev";
|
||||
}
|
||||
bool VersionWrapper::CompiledForEdittime() {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool VersionWrapper::IsOlder(int major,
|
||||
int minor,
|
||||
|
@@ -48,11 +48,6 @@ class GD_CORE_API VersionWrapper {
|
||||
*/
|
||||
static gd::String Status();
|
||||
|
||||
/**
|
||||
* \brief Return true if GDCpp is compiled with edittime support.
|
||||
*/
|
||||
static bool CompiledForEdittime();
|
||||
|
||||
/**
|
||||
* \brief Get Year of the release
|
||||
*/
|
||||
|
@@ -1,13 +1,12 @@
|
||||
# GDevelop Architecture Overview
|
||||
|
||||
GDevelop is architectured around a `Core` library, platforms (`GDJS`, `GDCpp`) and extensions (`Extensions` folder). The editor (`newIDE` folder) is using all of these libraries. This is a recap table of the main folders:
|
||||
GDevelop is architectured around a `Core` library, the game engine (`GDJS`) and extensions (`Extensions` folder). The editor (`newIDE` folder) is using all of these libraries. This is a recap table of the main folders:
|
||||
|
||||
| Directory | ℹ️ Description |
|
||||
| ------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `Core` | GDevelop core library, containing common tools to implement the IDE and work with GDevelop games. |
|
||||
| `GDCpp` | The C++ game engine, used to build native games (_not used in GDevelop 5_). |
|
||||
| `GDJS` | The game engine, written in TypeScript, using PixiJS (WebGL), powering all GDevelop games. |
|
||||
| `GDevelop.js` | Bindings of `Core`/`GDCpp`/`GDJS` and `Extensions` to JavaScript (with WebAssembly), used by the IDE. |
|
||||
| `GDevelop.js` | Bindings of `Core`, `GDJS` and `Extensions` to JavaScript (with WebAssembly), used by the IDE. |
|
||||
| `newIDE` | The game editor, written in JavaScript with React, Electron and PixiJS. |
|
||||
| `Extensions` | Extensions for the game engine, providing objects, behaviors, events and new features. |
|
||||
|
||||
@@ -17,11 +16,11 @@ The rest of this page is an introduction to the main concepts of GDevelop archit
|
||||
|
||||
**IDE** stands for "Integrated Development Environment". A synonym for it is also simply "editor". In GDevelop, the software itself, that is used to create games and running as an app or a web-app, is called the "GDevelop Editor" or the "GDevelop IDE"
|
||||
|
||||
> The term "IDE" is also used in some folders. When you browse `Core`, `GDCpp` or `GDJS` subfolders, some folders are called `IDE`. They contain classes and tools that are **only useful for the editor** (they are not per se mandatory to describe the structure of a game).
|
||||
> The term "IDE" is also used in some folders. When you browse `Core` or `GDJS` subfolders, some folders are called `IDE`. They contain classes and tools that are **only useful for the editor** (they are not per se mandatory to describe the structure of a game).
|
||||
|
||||
**Runtime** is a word used to describe classes, tools and source files being used during a game. This could also be called "in-game" or a "game engine".
|
||||
|
||||
> When you browse `GDCpp` or `GDJS` subfolders, you can find folders called `Runtime`. They contain the **game engine** of GDevelop.
|
||||
> When you browse `GDJS` subfolder, you can find a folder called `Runtime`. It's the **game engine** of GDevelop.
|
||||
|
||||
Extensions do have the same distinction between the "**IDE**" part and the "**Runtime**" part. For example, most extensions have:
|
||||
|
||||
@@ -79,7 +78,7 @@ You're welcome to do so! Please get in touch :)
|
||||
The idea of the GDevelop editor and game engine is to have a lean game engine, supporting almost nothing. Then, one can add "mods", "plugins", "modules" for GDevelop. We chose to call them "**Extensions**" in GDevelop.
|
||||
|
||||
- `GDevelop/Core/GDCore/Extensions` is the **declaration** of default (we say "builtin") extensions, that are available for any game and are "mandatory". They are called Extensions but they could be named "Extensions that will always be in your game". In programming languages, this is called a "[Standard Library](https://en.wikipedia.org/wiki/Standard_library)" (but don't get too distracted by this naming).
|
||||
- `GDevelop/GDJS/GDJS/Extensions/` and `GDevelop/GDCpp/GDCpp/Extensions/` are reusing these **declarations** and **adding** their own declarations. Mainly, they are setting the name of the functions to be called (either in TypeScript or in C++) for each action, condition or expression.
|
||||
- `GDevelop/GDJS/GDJS/Extensions/` is reusing these **declarations** and **adding** their own declarations. Mainly, they are setting the name of the functions to be called (either in TypeScript or in C++) for each action, condition or expression.
|
||||
- `GDevelop/Extensions/` is the folder for the "mods"/"plugins" for GDevelop - the ones that are not mandatory. They are not part of GDCore - they work on their own.
|
||||
|
||||
> In theory, all extensions could be moved to `GDevelop/Extensions/`. In practice, it's more pragmatic to have a set of "built-in" extensions with basic features.
|
||||
|
@@ -6,8 +6,8 @@ This project is released under the MIT License.
|
||||
#ifndef ANCHORBEHAVIOR_H
|
||||
#define ANCHORBEHAVIOR_H
|
||||
#include <vector>
|
||||
#include "GDCpp/Runtime/Project/Behavior.h"
|
||||
#include "GDCpp/Runtime/Project/Object.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
class Project;
|
||||
@@ -16,7 +16,7 @@ class Project;
|
||||
/**
|
||||
* \brief Allow to anchor objects to the window's bounds.
|
||||
*/
|
||||
class GD_EXTENSION_API AnchorBehavior : public Behavior {
|
||||
class GD_EXTENSION_API AnchorBehavior : public gd::Behavior {
|
||||
public:
|
||||
enum HorizontalAnchor {
|
||||
ANCHOR_HORIZONTAL_NONE = 0,
|
||||
|
@@ -1,212 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - Anchor Behavior Extension
|
||||
Copyright (c) 2016 Victor Levasseur (victorlevasseur52@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "AnchorRuntimeBehavior.h"
|
||||
#include <SFML/Window.hpp>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCpp/Extensions/Builtin/MathematicalTools.h"
|
||||
#include "GDCpp/Runtime/CommonTools.h"
|
||||
#include "GDCpp/Runtime/Project/Layout.h"
|
||||
#include "GDCpp/Runtime/RuntimeGame.h"
|
||||
#include "GDCpp/Runtime/RuntimeObject.h"
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include <map>
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#endif
|
||||
|
||||
AnchorRuntimeBehavior::AnchorRuntimeBehavior(
|
||||
const gd::SerializerElement& behaviorContent)
|
||||
: RuntimeBehavior(behaviorContent),
|
||||
m_relativeToOriginalWindowSize(true),
|
||||
m_leftEdgeAnchor(ANCHOR_HORIZONTAL_NONE),
|
||||
m_rightEdgeAnchor(ANCHOR_HORIZONTAL_NONE),
|
||||
m_topEdgeAnchor(ANCHOR_VERTICAL_NONE),
|
||||
m_bottomEdgeAnchor(ANCHOR_VERTICAL_NONE),
|
||||
m_invalidDistances(true),
|
||||
m_leftEdgeDistance(0.f),
|
||||
m_rightEdgeDistance(0.f),
|
||||
m_topEdgeDistance(0.f),
|
||||
m_bottomEdgeDistance(0.f) {
|
||||
m_relativeToOriginalWindowSize =
|
||||
behaviorContent.GetBoolAttribute("relativeToOriginalWindowSize");
|
||||
m_leftEdgeAnchor = static_cast<HorizontalAnchor>(
|
||||
behaviorContent.GetIntAttribute("leftEdgeAnchor"));
|
||||
m_rightEdgeAnchor = static_cast<HorizontalAnchor>(
|
||||
behaviorContent.GetIntAttribute("rightEdgeAnchor"));
|
||||
m_topEdgeAnchor = static_cast<VerticalAnchor>(
|
||||
behaviorContent.GetIntAttribute("topEdgeAnchor"));
|
||||
m_bottomEdgeAnchor = static_cast<VerticalAnchor>(
|
||||
behaviorContent.GetIntAttribute("bottomEdgeAnchor"));
|
||||
}
|
||||
|
||||
void AnchorRuntimeBehavior::OnActivate() { m_invalidDistances = true; }
|
||||
|
||||
namespace {
|
||||
sf::Vector2f mapFloatPixelToCoords(const sf::Vector2f& point,
|
||||
const sf::RenderTarget& target,
|
||||
const sf::View& view) {
|
||||
// First, convert from viewport coordinates to homogeneous coordinates
|
||||
sf::Vector2f normalized;
|
||||
sf::IntRect viewport = target.getViewport(view);
|
||||
normalized.x = -1.f + 2.f * (point.x - static_cast<float>(viewport.left)) /
|
||||
static_cast<float>(viewport.width);
|
||||
normalized.y = 1.f - 2.f * (point.y - static_cast<float>(viewport.top)) /
|
||||
static_cast<float>(viewport.height);
|
||||
|
||||
// Then transform by the inverse of the view matrix
|
||||
return view.getInverseTransform().transformPoint(normalized);
|
||||
}
|
||||
|
||||
sf::Vector2f mapCoordsToFloatPixel(const sf::Vector2f& point,
|
||||
const sf::RenderTarget& target,
|
||||
const sf::View& view) {
|
||||
// Note: almost the same as RenderTarget::mapCoordsToPixel except that the
|
||||
// result is sf::Vector2f
|
||||
|
||||
// First, transform the point by the view matrix
|
||||
sf::Vector2f normalized = view.getTransform().transformPoint(point);
|
||||
|
||||
// Then convert to viewport coordinates
|
||||
sf::Vector2f pixel;
|
||||
sf::IntRect viewport = target.getViewport(view);
|
||||
pixel.x = (normalized.x + 1.f) / 2.f * static_cast<float>(viewport.width) +
|
||||
static_cast<float>(viewport.left);
|
||||
pixel.y = (-normalized.y + 1.f) / 2.f * static_cast<float>(viewport.height) +
|
||||
static_cast<float>(viewport.top);
|
||||
|
||||
return pixel;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void AnchorRuntimeBehavior::DoStepPreEvents(RuntimeScene& scene) {}
|
||||
|
||||
void AnchorRuntimeBehavior::DoStepPostEvents(RuntimeScene& scene) {
|
||||
const RuntimeLayer& layer = scene.GetRuntimeLayer(object->GetLayer());
|
||||
const RuntimeCamera& firstCamera = layer.GetCamera(0);
|
||||
|
||||
if (m_invalidDistances) {
|
||||
sf::Vector2u windowSize =
|
||||
m_relativeToOriginalWindowSize
|
||||
? sf::Vector2u(scene.game->getWindowOriginalWidth(),
|
||||
scene.game->getWindowOriginalHeight())
|
||||
: scene.renderWindow->getSize();
|
||||
|
||||
// Calculate the distances from the window's bounds.
|
||||
sf::Vector2f topLeftPixel = mapCoordsToFloatPixel(
|
||||
sf::Vector2f(object->GetDrawableX(), object->GetDrawableY()),
|
||||
*(scene.renderWindow),
|
||||
firstCamera.GetSFMLView());
|
||||
|
||||
sf::Vector2f bottomRightPixel = mapCoordsToFloatPixel(
|
||||
sf::Vector2f(object->GetDrawableX() + object->GetWidth(),
|
||||
object->GetDrawableY() + object->GetHeight()),
|
||||
*(scene.renderWindow),
|
||||
firstCamera.GetSFMLView());
|
||||
|
||||
// Left edge
|
||||
if (m_leftEdgeAnchor == ANCHOR_HORIZONTAL_WINDOW_LEFT)
|
||||
m_leftEdgeDistance = topLeftPixel.x;
|
||||
else if (m_leftEdgeAnchor == ANCHOR_HORIZONTAL_WINDOW_RIGHT)
|
||||
m_leftEdgeDistance = static_cast<float>(windowSize.x) - topLeftPixel.x;
|
||||
else if (m_leftEdgeAnchor == ANCHOR_HORIZONTAL_PROPORTIONAL)
|
||||
m_leftEdgeDistance = topLeftPixel.x / windowSize.x;
|
||||
|
||||
// Right edge
|
||||
if (m_rightEdgeAnchor == ANCHOR_HORIZONTAL_WINDOW_LEFT)
|
||||
m_rightEdgeDistance = bottomRightPixel.x;
|
||||
else if (m_rightEdgeAnchor == ANCHOR_HORIZONTAL_WINDOW_RIGHT)
|
||||
m_rightEdgeDistance =
|
||||
static_cast<float>(windowSize.x) - bottomRightPixel.x;
|
||||
else if (m_rightEdgeAnchor == ANCHOR_HORIZONTAL_PROPORTIONAL)
|
||||
m_rightEdgeDistance = bottomRightPixel.x / windowSize.x;
|
||||
|
||||
// Top edge
|
||||
if (m_topEdgeAnchor == ANCHOR_VERTICAL_WINDOW_TOP)
|
||||
m_topEdgeDistance = topLeftPixel.y;
|
||||
else if (m_topEdgeAnchor == ANCHOR_VERTICAL_WINDOW_BOTTOM)
|
||||
m_topEdgeDistance = static_cast<float>(windowSize.y) - topLeftPixel.y;
|
||||
else if (m_topEdgeAnchor == ANCHOR_VERTICAL_PROPORTIONAL)
|
||||
m_topEdgeDistance = topLeftPixel.y / static_cast<float>(windowSize.y);
|
||||
|
||||
// Bottom edge
|
||||
if (m_bottomEdgeAnchor == ANCHOR_VERTICAL_WINDOW_TOP)
|
||||
m_bottomEdgeDistance = bottomRightPixel.y;
|
||||
else if (m_bottomEdgeAnchor == ANCHOR_VERTICAL_WINDOW_BOTTOM)
|
||||
m_bottomEdgeDistance =
|
||||
static_cast<float>(windowSize.y) - bottomRightPixel.y;
|
||||
else if (m_bottomEdgeAnchor == ANCHOR_VERTICAL_PROPORTIONAL)
|
||||
m_bottomEdgeDistance =
|
||||
bottomRightPixel.y / static_cast<float>(windowSize.y);
|
||||
|
||||
m_invalidDistances = false;
|
||||
} else {
|
||||
sf::Vector2u windowSize = scene.renderWindow->getSize();
|
||||
|
||||
// Move and resize the object if needed
|
||||
sf::Vector2f topLeftPixel;
|
||||
sf::Vector2f bottomRightPixel;
|
||||
|
||||
// Left edge
|
||||
if (m_leftEdgeAnchor == ANCHOR_HORIZONTAL_WINDOW_LEFT)
|
||||
topLeftPixel.x = m_leftEdgeDistance;
|
||||
else if (m_leftEdgeAnchor == ANCHOR_HORIZONTAL_WINDOW_RIGHT)
|
||||
topLeftPixel.x = static_cast<float>(windowSize.x) - m_leftEdgeDistance;
|
||||
else if (m_leftEdgeAnchor == ANCHOR_HORIZONTAL_PROPORTIONAL)
|
||||
topLeftPixel.x = m_leftEdgeDistance * static_cast<float>(windowSize.x);
|
||||
|
||||
// Top edge
|
||||
if (m_topEdgeAnchor == ANCHOR_VERTICAL_WINDOW_TOP)
|
||||
topLeftPixel.y = m_topEdgeDistance;
|
||||
else if (m_topEdgeAnchor == ANCHOR_VERTICAL_WINDOW_BOTTOM)
|
||||
topLeftPixel.y = static_cast<float>(windowSize.y) - m_topEdgeDistance;
|
||||
else if (m_topEdgeAnchor == ANCHOR_VERTICAL_PROPORTIONAL)
|
||||
topLeftPixel.y = m_topEdgeDistance * static_cast<float>(windowSize.y);
|
||||
|
||||
// Right edge
|
||||
if (m_rightEdgeAnchor == ANCHOR_HORIZONTAL_WINDOW_LEFT)
|
||||
bottomRightPixel.x = m_rightEdgeDistance;
|
||||
else if (m_rightEdgeAnchor == ANCHOR_HORIZONTAL_WINDOW_RIGHT)
|
||||
bottomRightPixel.x =
|
||||
static_cast<float>(windowSize.x) - m_rightEdgeDistance;
|
||||
else if (m_rightEdgeAnchor == ANCHOR_HORIZONTAL_PROPORTIONAL)
|
||||
bottomRightPixel.x =
|
||||
m_rightEdgeDistance * static_cast<float>(windowSize.x);
|
||||
|
||||
// Bottom edge
|
||||
if (m_bottomEdgeAnchor == ANCHOR_VERTICAL_WINDOW_TOP)
|
||||
bottomRightPixel.y = m_bottomEdgeDistance;
|
||||
else if (m_bottomEdgeAnchor == ANCHOR_VERTICAL_WINDOW_BOTTOM)
|
||||
bottomRightPixel.y =
|
||||
static_cast<float>(windowSize.y) - m_bottomEdgeDistance;
|
||||
else if (m_bottomEdgeAnchor == ANCHOR_VERTICAL_PROPORTIONAL)
|
||||
bottomRightPixel.y =
|
||||
m_bottomEdgeDistance * static_cast<float>(windowSize.y);
|
||||
|
||||
sf::Vector2f topLeftCoord = mapFloatPixelToCoords(
|
||||
topLeftPixel, (*scene.renderWindow), firstCamera.GetSFMLView());
|
||||
sf::Vector2f bottomRightCoord = mapFloatPixelToCoords(
|
||||
bottomRightPixel, (*scene.renderWindow), firstCamera.GetSFMLView());
|
||||
|
||||
// Move and resize the object according to the anchors
|
||||
if (m_rightEdgeAnchor != ANCHOR_HORIZONTAL_NONE)
|
||||
object->SetWidth(bottomRightCoord.x - topLeftCoord.x);
|
||||
if (m_bottomEdgeAnchor != ANCHOR_VERTICAL_NONE)
|
||||
object->SetHeight(bottomRightCoord.y - topLeftCoord.y);
|
||||
if (m_leftEdgeAnchor != ANCHOR_HORIZONTAL_NONE)
|
||||
object->SetX(topLeftCoord.x + object->GetX() - object->GetDrawableX());
|
||||
if (m_topEdgeAnchor != ANCHOR_VERTICAL_NONE)
|
||||
object->SetY(topLeftCoord.y + object->GetY() - object->GetDrawableY());
|
||||
}
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
GDevelop - Anchor Behavior Extension
|
||||
Copyright (c) 2016 Victor Levasseur (victorlevasseur52@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef ANCHORRuntimeBEHAVIOR_H
|
||||
#define ANCHORRuntimeBEHAVIOR_H
|
||||
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
#include <SFML/Graphics/View.hpp>
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
#include <vector>
|
||||
#include "GDCpp/Runtime/RuntimeBehavior.h"
|
||||
#include "GDCpp/Runtime/Project/Object.h"
|
||||
namespace gd {
|
||||
class Layout;
|
||||
}
|
||||
class RuntimeScene;
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
class RuntimeScenePlatformData;
|
||||
|
||||
/**
|
||||
* \brief Allow to anchor objects to the window's bounds.
|
||||
*/
|
||||
class GD_EXTENSION_API AnchorRuntimeBehavior : public RuntimeBehavior {
|
||||
public:
|
||||
enum HorizontalAnchor {
|
||||
ANCHOR_HORIZONTAL_NONE = 0,
|
||||
ANCHOR_HORIZONTAL_WINDOW_LEFT = 1,
|
||||
ANCHOR_HORIZONTAL_WINDOW_RIGHT = 2,
|
||||
ANCHOR_HORIZONTAL_PROPORTIONAL = 3
|
||||
};
|
||||
|
||||
enum VerticalAnchor {
|
||||
ANCHOR_VERTICAL_NONE = 0,
|
||||
ANCHOR_VERTICAL_WINDOW_TOP = 1,
|
||||
ANCHOR_VERTICAL_WINDOW_BOTTOM = 2,
|
||||
ANCHOR_VERTICAL_PROPORTIONAL = 3
|
||||
};
|
||||
|
||||
AnchorRuntimeBehavior(const gd::SerializerElement& behaviorContent);
|
||||
virtual ~AnchorRuntimeBehavior(){};
|
||||
virtual AnchorRuntimeBehavior* Clone() const override { return new AnchorRuntimeBehavior(*this); }
|
||||
|
||||
virtual void OnActivate() override;
|
||||
|
||||
private:
|
||||
virtual void DoStepPreEvents(RuntimeScene& scene) override;
|
||||
virtual void DoStepPostEvents(RuntimeScene& scene) override;
|
||||
|
||||
bool m_relativeToOriginalWindowSize; ///< True if the original size of the
|
||||
///< game window must be used.
|
||||
HorizontalAnchor m_leftEdgeAnchor;
|
||||
HorizontalAnchor m_rightEdgeAnchor;
|
||||
VerticalAnchor m_topEdgeAnchor;
|
||||
VerticalAnchor m_bottomEdgeAnchor;
|
||||
|
||||
bool m_invalidDistances;
|
||||
// Distances (in window's units) from the XXX edge of the object to side of
|
||||
// the window the edge is anchored on. Note: If the edge anchor is set to
|
||||
// PROPORTIONAL, then it contains the ratio of the distance to the window
|
||||
// size.
|
||||
float m_leftEdgeDistance;
|
||||
float m_rightEdgeDistance;
|
||||
float m_topEdgeDistance;
|
||||
float m_bottomEdgeDistance;
|
||||
};
|
||||
|
||||
#endif // ANCHORRuntimeBEHAVIOR_H
|
@@ -13,14 +13,8 @@ gd_add_extension_definitions(AnchorBehavior)
|
||||
include_directories(.)
|
||||
file(GLOB source_files *.cpp *.h)
|
||||
gd_add_clang_utils(AnchorBehavior "${source_files}")
|
||||
|
||||
gd_add_extension_target(AnchorBehavior "${source_files}")
|
||||
gdcpp_add_runtime_extension_target(AnchorBehavior_Runtime "${source_files}")
|
||||
|
||||
#Linker files for the IDE extension
|
||||
###
|
||||
gd_extension_link_libraries(AnchorBehavior)
|
||||
|
||||
#Linker files for the GD C++ Runtime extension
|
||||
###
|
||||
gdcpp_runtime_extension_link_libraries(AnchorBehavior_Runtime)
|
||||
|
@@ -6,9 +6,9 @@ This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "AnchorBehavior.h"
|
||||
#include "AnchorRuntimeBehavior.h"
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "GDCpp/Runtime/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
void DeclareAnchorBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
extension
|
||||
@@ -30,38 +30,3 @@ void DeclareAnchorBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
std::make_shared<AnchorBehavior>(),
|
||||
std::make_shared<gd::BehaviorsSharedData>());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief This class declares information about the extension.
|
||||
*/
|
||||
class AnchorBehaviorCppExtension : public ExtensionBase {
|
||||
public:
|
||||
/**
|
||||
* Constructor of an extension declares everything the extension contains:
|
||||
* objects, actions, conditions and expressions.
|
||||
*/
|
||||
AnchorBehaviorCppExtension() {
|
||||
DeclareAnchorBehaviorExtension(*this);
|
||||
AddRuntimeBehavior<AnchorRuntimeBehavior>(
|
||||
GetBehaviorMetadata("AnchorBehavior::AnchorBehavior"),
|
||||
"AnchorRuntimeBehavior");
|
||||
GetBehaviorMetadata("AnchorBehavior::AnchorBehavior")
|
||||
.SetIncludeFile("AnchorBehavior/AnchorRuntimeBehavior.h");
|
||||
|
||||
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
|
||||
};
|
||||
};
|
||||
|
||||
#if defined(ANDROID)
|
||||
extern "C" ExtensionBase* CreateGDCppAnchorBehaviorExtension() {
|
||||
return new AnchorBehaviorCppExtension;
|
||||
}
|
||||
#elif !defined(EMSCRIPTEN)
|
||||
/**
|
||||
* Used by GDevelop to create the extension class
|
||||
* -- Do not need to be modified. --
|
||||
*/
|
||||
extern "C" ExtensionBase* GD_EXTENSION_API CreateGDExtension() {
|
||||
return new AnchorBehaviorCppExtension;
|
||||
}
|
||||
#endif
|
||||
|
@@ -6,7 +6,6 @@
|
||||
macro(gd_add_extension_includes)
|
||||
include_directories(${sfml_include_dir})
|
||||
include_directories(${GDCORE_include_dir})
|
||||
include_directories(${GDCpp_include_dir})
|
||||
endmacro()
|
||||
|
||||
#Add common defines for a target that will be a GD extension
|
||||
@@ -76,69 +75,13 @@ function(gd_add_extension_target target_name source_files)
|
||||
ENDIF()
|
||||
endfunction()
|
||||
|
||||
#Add a GDC++ runtime extension target, that will produce the final library file for runtime.
|
||||
function(gdcpp_add_runtime_extension_target gdcpp_runtime_target_name source_files)
|
||||
IF(NOT gdcpp_runtime_target_name MATCHES "_Runtime$")
|
||||
MESSAGE(ERROR "You called gdcpp_add_runtime_extension_target with a target name not finishing with '_Runtime'")
|
||||
ENDIF()
|
||||
string(REGEX REPLACE "_Runtime" "" target_name ${gdcpp_runtime_target_name})
|
||||
|
||||
IF(NOT EMSCRIPTEN) #Also add a GDC++ extension target
|
||||
add_library(${gdcpp_runtime_target_name} SHARED ${source_files})
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES COMPILE_DEFINITIONS "${${gdcpp_runtime_target_name}_extra_definitions}")
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}/CppPlatform/Extensions/Runtime")
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}/CppPlatform/Extensions/Runtime")
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}/CppPlatform/Extensions/Runtime")
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES RUNTIME_OUTPUT_NAME "${target_name}")
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES LIBRARY_OUTPUT_NAME "${target_name}")
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES ARCHIVE_OUTPUT_NAME "${target_name}")
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES PREFIX "")
|
||||
IF(WIN32) #GD extensions have special suffix in their filenames.
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES SUFFIX ".xgdw")
|
||||
ELSE()
|
||||
set_target_properties(${gdcpp_runtime_target_name} PROPERTIES SUFFIX ".xgd")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
endfunction()
|
||||
|
||||
#Link default libraries with a target that is a GD extension
|
||||
function(gd_extension_link_libraries target_name)
|
||||
IF(EMSCRIPTEN)
|
||||
#Nothing.
|
||||
ELSE()
|
||||
target_link_libraries(${target_name} GDCore)
|
||||
target_link_libraries(${target_name} GDCpp)
|
||||
target_link_libraries(${target_name} ${sfml_LIBRARIES})
|
||||
ENDIF()
|
||||
endfunction()
|
||||
|
||||
#Link default libraries with a target that is a GDC++ Runtime extension
|
||||
function(gdcpp_runtime_extension_link_libraries target_name)
|
||||
IF(EMSCRIPTEN)
|
||||
#Nothing.
|
||||
ELSE()
|
||||
target_link_libraries(${target_name} GDCpp_Runtime)
|
||||
target_link_libraries(${target_name} ${sfml_LIBRARIES})
|
||||
IF(WIN32)
|
||||
target_link_libraries(${target_name} ws2_32 user32 opengl32 glu32)
|
||||
ENDIF(WIN32)
|
||||
ENDIF()
|
||||
endfunction()
|
||||
|
||||
|
||||
#Create a target for a test executable of a GDC++ Runtime extension
|
||||
function(gdcpp_add_tests_extension_target gdcpp_tests_target_name test_source_files)
|
||||
IF(NOT gdcpp_tests_target_name MATCHES "_tests$")
|
||||
MESSAGE(ERROR "You called gdcpp_add_tests_extension_target with a target name not finishing with '_tests'")
|
||||
ENDIF()
|
||||
string(REGEX REPLACE "_tests" "" target_name ${gdcpp_tests_target_name})
|
||||
|
||||
if(BUILD_TESTS)
|
||||
add_executable(${gdcpp_tests_target_name} ${test_source_files})
|
||||
target_link_libraries(${gdcpp_tests_target_name} GDCpp_Runtime)
|
||||
target_link_libraries(${gdcpp_tests_target_name} ${target_name})
|
||||
target_link_libraries(${gdcpp_tests_target_name} ${sfml_LIBRARIES})
|
||||
|
||||
set_target_properties(${gdcpp_tests_target_name} PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE) #Allow finding dependencies directly from build path on Mac OS X.
|
||||
endif()
|
||||
endfunction()
|
||||
|
@@ -13,14 +13,8 @@ gd_add_extension_definitions(DestroyOutsideBehavior)
|
||||
include_directories(.)
|
||||
file(GLOB source_files *.cpp *.h)
|
||||
gd_add_clang_utils(DestroyOutsideBehavior "${source_files}")
|
||||
|
||||
gd_add_extension_target(DestroyOutsideBehavior "${source_files}")
|
||||
gdcpp_add_runtime_extension_target(DestroyOutsideBehavior_Runtime "${source_files}")
|
||||
|
||||
#Linker files for the IDE extension
|
||||
###
|
||||
gd_extension_link_libraries(DestroyOutsideBehavior GDCore)
|
||||
|
||||
#Linker files for the GD C++ Runtime extension
|
||||
###
|
||||
gdcpp_runtime_extension_link_libraries(DestroyOutsideBehavior_Runtime)
|
||||
|
@@ -1,55 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - DestroyOutside Behavior Extension
|
||||
Copyright (c) 2014-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "DestroyOutsideRuntimeBehavior.h"
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include "GDCpp/Runtime/CommonTools.h"
|
||||
#include "GDCpp/Runtime/Project/Layout.h"
|
||||
#include "GDCpp/Runtime/RuntimeLayer.h"
|
||||
#include "GDCpp/Runtime/RuntimeObject.h"
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
|
||||
|
||||
DestroyOutsideRuntimeBehavior::DestroyOutsideRuntimeBehavior(
|
||||
const gd::SerializerElement& behaviorContent)
|
||||
: RuntimeBehavior(behaviorContent), extraBorder(0) {
|
||||
extraBorder = behaviorContent.GetDoubleAttribute("extraBorder", 0);
|
||||
}
|
||||
|
||||
void DestroyOutsideRuntimeBehavior::DoStepPostEvents(RuntimeScene& scene) {
|
||||
bool erase = true;
|
||||
const RuntimeLayer& theLayer = scene.GetRuntimeLayer(object->GetLayer());
|
||||
float objCenterX = object->GetDrawableX() + object->GetCenterX();
|
||||
float objCenterY = object->GetDrawableY() + object->GetCenterY();
|
||||
for (std::size_t cameraIndex = 0; cameraIndex < theLayer.GetCameraCount();
|
||||
++cameraIndex) {
|
||||
const RuntimeCamera& theCamera = theLayer.GetCamera(cameraIndex);
|
||||
|
||||
float boundingCircleRadius =
|
||||
sqrt(object->GetWidth() * object->GetWidth() +
|
||||
object->GetHeight() * object->GetHeight()) /
|
||||
2.0;
|
||||
if (objCenterX + boundingCircleRadius + extraBorder <
|
||||
theCamera.GetViewCenter().x - theCamera.GetWidth() / 2.0 ||
|
||||
objCenterX - boundingCircleRadius - extraBorder >
|
||||
theCamera.GetViewCenter().x + theCamera.GetWidth() / 2.0 ||
|
||||
objCenterY + boundingCircleRadius + extraBorder <
|
||||
theCamera.GetViewCenter().y - theCamera.GetHeight() / 2.0 ||
|
||||
objCenterY - boundingCircleRadius - extraBorder >
|
||||
theCamera.GetViewCenter().y + theCamera.GetHeight() / 2.0) {
|
||||
// Ok we are outside the camera area.
|
||||
} else {
|
||||
// The object can be viewed by the camera.
|
||||
erase = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (erase) object->DeleteFromScene(scene);
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - DestroyOutside Behavior Extension
|
||||
Copyright (c) 2013-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef DESTROYOUTSIDERUNTIMEBEHAVIOR_H
|
||||
#define DESTROYOUTSIDERUNTIMEBEHAVIOR_H
|
||||
#include <map>
|
||||
#include "GDCpp/Runtime/Project/Object.h"
|
||||
#include "GDCpp/Runtime/RuntimeBehavior.h"
|
||||
class RuntimeScene;
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Behavior that allows objects to be dragged with the mouse
|
||||
*/
|
||||
class GD_EXTENSION_API DestroyOutsideRuntimeBehavior : public RuntimeBehavior {
|
||||
public:
|
||||
DestroyOutsideRuntimeBehavior(const gd::SerializerElement& behaviorContent);
|
||||
virtual ~DestroyOutsideRuntimeBehavior(){};
|
||||
virtual DestroyOutsideRuntimeBehavior* Clone() const {
|
||||
return new DestroyOutsideRuntimeBehavior(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the value of the extra border.
|
||||
*/
|
||||
bool GetExtraBorder() const { return extraBorder; };
|
||||
|
||||
/**
|
||||
* \brief Set the value of the extra border, i.e the supplementary margin that
|
||||
* the object must cross before being deleted.
|
||||
*/
|
||||
void SetExtraBorder(float extraBorder_) { extraBorder = extraBorder_; };
|
||||
|
||||
private:
|
||||
virtual void DoStepPostEvents(RuntimeScene& scene);
|
||||
|
||||
float extraBorder; ///< The supplementary margin outside the screen that the
|
||||
///< object must cross before being deleted.
|
||||
};
|
||||
|
||||
#endif // DESTROYOUTSIDERUNTIMEBEHAVIOR_H
|
@@ -6,8 +6,9 @@ This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "DestroyOutsideBehavior.h"
|
||||
#include "DestroyOutsideRuntimeBehavior.h"
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
extension
|
||||
@@ -66,39 +67,3 @@ void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
.SetIncludeFile("DestroyOutsideBehavior/DestroyOutsideRuntimeBehavior.h");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief This class declares information about the extension.
|
||||
*/
|
||||
class DestroyOutsideBehaviorCppExtension : public ExtensionBase {
|
||||
public:
|
||||
/**
|
||||
* Constructor of an extension declares everything the extension contains:
|
||||
* objects, actions, conditions and expressions.
|
||||
*/
|
||||
DestroyOutsideBehaviorCppExtension() {
|
||||
DeclareDestroyOutsideBehaviorExtension(*this);
|
||||
AddRuntimeBehavior<DestroyOutsideRuntimeBehavior>(
|
||||
GetBehaviorMetadata("DestroyOutsideBehavior::DestroyOutside"),
|
||||
"DestroyOutsideRuntimeBehavior");
|
||||
GetBehaviorMetadata("DestroyOutsideBehavior::DestroyOutside")
|
||||
.SetIncludeFile(
|
||||
"DestroyOutsideBehavior/DestroyOutsideRuntimeBehavior.h");
|
||||
|
||||
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
|
||||
};
|
||||
};
|
||||
|
||||
#if defined(ANDROID)
|
||||
extern "C" ExtensionBase* CreateGDCppDestroyOutsideBehaviorExtension() {
|
||||
return new DestroyOutsideBehaviorCppExtension;
|
||||
}
|
||||
#elif !defined(EMSCRIPTEN)
|
||||
/**
|
||||
* Used by GDevelop to create the extension class
|
||||
* -- Do not need to be modified. --
|
||||
*/
|
||||
extern "C" ExtensionBase* GD_EXTENSION_API CreateGDExtension() {
|
||||
return new DestroyOutsideBehaviorCppExtension;
|
||||
}
|
||||
#endif
|
||||
|
@@ -13,14 +13,8 @@ gd_add_extension_definitions(DraggableBehavior)
|
||||
include_directories(.)
|
||||
file(GLOB source_files *.cpp *.h)
|
||||
gd_add_clang_utils(DraggableBehavior "${source_files}")
|
||||
|
||||
gd_add_extension_target(DraggableBehavior "${source_files}")
|
||||
gdcpp_add_runtime_extension_target(DraggableBehavior_Runtime "${source_files}")
|
||||
|
||||
#Linker files for the IDE extension
|
||||
###
|
||||
gd_extension_link_libraries(DraggableBehavior)
|
||||
|
||||
#Linker files for the GD C++ Runtime extension
|
||||
###
|
||||
gdcpp_runtime_extension_link_libraries(DraggableBehavior_Runtime)
|
||||
|
@@ -6,6 +6,6 @@ This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "DraggableBehavior.h"
|
||||
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
DraggableBehavior::DraggableBehavior() {}
|
||||
|
@@ -9,8 +9,8 @@ This project is released under the MIT License.
|
||||
#define DRAGGABLEBEHAVIOR_H
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
#include <map>
|
||||
#include "GDCpp/Runtime/Project/Behavior.h"
|
||||
#include "GDCpp/Runtime/Project/Object.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
class RuntimeScene;
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
@@ -20,7 +20,7 @@ class Layout;
|
||||
/**
|
||||
* \brief Behavior that allows objects to be dragged with the mouse
|
||||
*/
|
||||
class GD_EXTENSION_API DraggableBehavior : public Behavior {
|
||||
class GD_EXTENSION_API DraggableBehavior : public gd::Behavior {
|
||||
public:
|
||||
DraggableBehavior();
|
||||
virtual ~DraggableBehavior(){};
|
||||
|
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - Draggable Behavior Extension
|
||||
Copyright (c) 2014-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "DraggableRuntimeBehavior.h"
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include "GDCpp/Runtime/CommonTools.h"
|
||||
#include "GDCpp/Runtime/Project/Layout.h"
|
||||
#include "GDCpp/Runtime/RuntimeLayer.h"
|
||||
#include "GDCpp/Runtime/RuntimeObject.h"
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
|
||||
|
||||
bool DraggableRuntimeBehavior::somethingDragged = false;
|
||||
bool DraggableRuntimeBehavior::leftPressedLastFrame = false;
|
||||
|
||||
DraggableRuntimeBehavior::DraggableRuntimeBehavior(
|
||||
const gd::SerializerElement& behaviorContent)
|
||||
: RuntimeBehavior(behaviorContent), dragged(false) {}
|
||||
|
||||
void DraggableRuntimeBehavior::DoStepPreEvents(RuntimeScene& scene) {
|
||||
// Begin drag ?
|
||||
if (!dragged && scene.GetInputManager().IsMouseButtonPressed("Left") &&
|
||||
!leftPressedLastFrame && !somethingDragged) {
|
||||
RuntimeLayer& theLayer = scene.GetRuntimeLayer(object->GetLayer());
|
||||
for (std::size_t cameraIndex = 0; cameraIndex < theLayer.GetCameraCount();
|
||||
++cameraIndex) {
|
||||
sf::Vector2f mousePos = scene.renderWindow->mapPixelToCoords(
|
||||
scene.GetInputManager().GetMousePosition(),
|
||||
theLayer.GetCamera(cameraIndex).GetSFMLView());
|
||||
|
||||
if (object->GetDrawableX() <= mousePos.x &&
|
||||
object->GetDrawableX() + object->GetWidth() >= mousePos.x &&
|
||||
object->GetDrawableY() <= mousePos.y &&
|
||||
object->GetDrawableY() + object->GetHeight() >= mousePos.y) {
|
||||
dragged = true;
|
||||
somethingDragged = true;
|
||||
xOffset = mousePos.x - object->GetX();
|
||||
yOffset = mousePos.y - object->GetY();
|
||||
dragCameraIndex = cameraIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// End dragging ?
|
||||
else if (!scene.GetInputManager().IsMouseButtonPressed("Left")) {
|
||||
dragged = false;
|
||||
somethingDragged = false;
|
||||
}
|
||||
|
||||
// Being dragging ?
|
||||
if (dragged) {
|
||||
RuntimeLayer& theLayer = scene.GetRuntimeLayer(object->GetLayer());
|
||||
sf::Vector2f mousePos = scene.renderWindow->mapPixelToCoords(
|
||||
scene.GetInputManager().GetMousePosition(),
|
||||
theLayer.GetCamera(dragCameraIndex).GetSFMLView());
|
||||
|
||||
object->SetX(mousePos.x - xOffset);
|
||||
object->SetY(mousePos.y - yOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void DraggableRuntimeBehavior::DoStepPostEvents(RuntimeScene& scene) {
|
||||
leftPressedLastFrame = scene.GetInputManager().IsMouseButtonPressed("Left");
|
||||
}
|
||||
|
||||
void DraggableRuntimeBehavior::OnDeActivate() {
|
||||
if (dragged) somethingDragged = false;
|
||||
dragged = false;
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - Draggable Behavior Extension
|
||||
Copyright (c) 2013-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef DRAGGABLERUNTIMEBEHAVIOR_H
|
||||
#define DRAGGABLERUNTIMEBEHAVIOR_H
|
||||
#include "GDCpp/Runtime/Project/Object.h"
|
||||
#include "GDCpp/Runtime/RuntimeBehavior.h"
|
||||
class RuntimeScene;
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Behavior that allows objects to be dragged with the mouse
|
||||
*/
|
||||
class GD_EXTENSION_API DraggableRuntimeBehavior : public RuntimeBehavior {
|
||||
public:
|
||||
DraggableRuntimeBehavior(const gd::SerializerElement& behaviorContent);
|
||||
virtual ~DraggableRuntimeBehavior(){};
|
||||
virtual DraggableRuntimeBehavior* Clone() const {
|
||||
return new DraggableRuntimeBehavior(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the object is being dragged.
|
||||
*/
|
||||
bool IsDragged() const { return dragged; };
|
||||
|
||||
virtual void OnDeActivate();
|
||||
|
||||
private:
|
||||
virtual void DoStepPreEvents(RuntimeScene& scene);
|
||||
virtual void DoStepPostEvents(RuntimeScene& scene);
|
||||
|
||||
float xOffset;
|
||||
float yOffset;
|
||||
std::size_t dragCameraIndex; ///< The camera being used to move the object. (
|
||||
///< The layer is the object's layer ).
|
||||
bool dragged; ///< True if the object is being dragged.
|
||||
static bool somethingDragged; ///< Used to avoid start dragging an object
|
||||
///< while another is being dragged.
|
||||
static bool
|
||||
leftPressedLastFrame; ///< Used to only start dragging when clicking.
|
||||
};
|
||||
|
||||
#endif // DRAGGABLERUNTIMEBEHAVIOR_H
|
@@ -6,8 +6,9 @@ This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "DraggableBehavior.h"
|
||||
#include "DraggableRuntimeBehavior.h"
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
void DeclareDraggableBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
extension
|
||||
@@ -46,33 +47,3 @@ void DeclareDraggableBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
.SetFunctionName("IsDragged");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief This class declares information about the extension.
|
||||
*/
|
||||
class Extension : public ExtensionBase {
|
||||
public:
|
||||
/**
|
||||
* Constructor of an extension declares everything the extension contains:
|
||||
* objects, actions, conditions and expressions.
|
||||
*/
|
||||
Extension() {
|
||||
DeclareDraggableBehaviorExtension(*this);
|
||||
AddRuntimeBehavior<DraggableRuntimeBehavior>(
|
||||
GetBehaviorMetadata("DraggableBehavior::Draggable"),
|
||||
"DraggableRuntimeBehavior");
|
||||
GetBehaviorMetadata("DraggableBehavior::Draggable")
|
||||
.SetIncludeFile("DraggableBehavior/DraggableRuntimeBehavior.h");
|
||||
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
|
||||
};
|
||||
};
|
||||
|
||||
#if !defined(EMSCRIPTEN)
|
||||
/**
|
||||
* Used by GDevelop to create the extension class
|
||||
* -- Do not need to be modified. --
|
||||
*/
|
||||
extern "C" ExtensionBase* GD_EXTENSION_API CreateGDExtension() {
|
||||
return new Extension;
|
||||
}
|
||||
#endif
|
||||
|
@@ -15,18 +15,7 @@ file(GLOB source_files *.cpp *.h)
|
||||
gd_add_clang_utils(Inventory "${source_files}")
|
||||
|
||||
gd_add_extension_target(Inventory "${source_files}")
|
||||
gdcpp_add_runtime_extension_target(Inventory_Runtime "${source_files}")
|
||||
|
||||
#Linker files for the IDE extension
|
||||
###
|
||||
gd_extension_link_libraries(Inventory)
|
||||
|
||||
|
||||
#Linker files for the GD C++ Runtime extension
|
||||
###
|
||||
gdcpp_runtime_extension_link_libraries(Inventory_Runtime)
|
||||
|
||||
#Tests for the GD C++ Runtime extension
|
||||
###
|
||||
file(GLOB_RECURSE test_source_files tests/*)
|
||||
gdcpp_add_tests_extension_target(Inventory_Runtime_tests "${test_source_files}")
|
||||
|
@@ -5,8 +5,8 @@ Copyright (c) 2008-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "InventoryTools.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -212,38 +212,3 @@ void DeclareInventoryExtension(gd::PlatformExtension& extension) {
|
||||
.SetIncludeFile("Inventory/InventoryTools.h");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief This class declares information about the extension.
|
||||
*/
|
||||
class InventoryCppExtension : public ExtensionBase {
|
||||
public:
|
||||
/**
|
||||
* Constructor of an extension declares everything the extension contains:
|
||||
* objects, actions, conditions and expressions.
|
||||
*/
|
||||
InventoryCppExtension() {
|
||||
DeclareInventoryExtension(*this);
|
||||
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
|
||||
};
|
||||
|
||||
virtual void SceneLoaded(RuntimeScene& scene) override {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
InventoryTools::ClearAll(scene);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(ANDROID)
|
||||
extern "C" ExtensionBase* CreateGDCppInventoryExtension() {
|
||||
return new InventoryCppExtension;
|
||||
}
|
||||
#elif !defined(EMSCRIPTEN)
|
||||
/**
|
||||
* Used by GDevelop to create the extension class
|
||||
* -- Do not need to be modified. --
|
||||
*/
|
||||
extern "C" ExtensionBase* GD_EXTENSION_API CreateGDExtension() {
|
||||
return new InventoryCppExtension;
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,111 +0,0 @@
|
||||
#include "Inventory.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
bool Inventory::Has(const gd::String& itemName) {
|
||||
return items.find(itemName) != items.end() && items[itemName].count > 0;
|
||||
}
|
||||
|
||||
size_t Inventory::Count(const gd::String& itemName) {
|
||||
if (items.find(itemName) == items.end()) return 0;
|
||||
|
||||
return items[itemName].count;
|
||||
}
|
||||
|
||||
bool Inventory::Add(const gd::String& itemName) {
|
||||
if (items.find(itemName) == items.end()) {
|
||||
MakeItemEntry(itemName);
|
||||
}
|
||||
|
||||
auto& item = items[itemName];
|
||||
if (item.unlimited || item.count < item.maxCount) {
|
||||
item.count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Inventory::SetCount(const gd::String& itemName, size_t count) {
|
||||
if (items.find(itemName) == items.end()) {
|
||||
MakeItemEntry(itemName);
|
||||
}
|
||||
|
||||
auto& item = items[itemName];
|
||||
size_t newCount = item.unlimited ? count : std::min(count, item.maxCount);
|
||||
item.count = newCount;
|
||||
|
||||
return item.unlimited || count <= item.maxCount;
|
||||
}
|
||||
|
||||
bool Inventory::IsFull(const gd::String& itemName) {
|
||||
if (items.find(itemName) == items.end()) return false;
|
||||
|
||||
auto& item = items[itemName];
|
||||
return !item.unlimited && item.count >= item.maxCount;
|
||||
}
|
||||
|
||||
bool Inventory::Remove(const gd::String& itemName) {
|
||||
if (items.find(itemName) == items.end()) return false;
|
||||
|
||||
auto& item = items[itemName];
|
||||
if (item.count > 0) {
|
||||
item.count--;
|
||||
|
||||
if (item.count == 0) {
|
||||
item.equipped = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Inventory::SetMaximum(const gd::String& itemName, size_t maxCount) {
|
||||
if (items.find(itemName) == items.end()) {
|
||||
MakeItemEntry(itemName);
|
||||
}
|
||||
|
||||
items[itemName].maxCount = maxCount;
|
||||
items[itemName].unlimited = false;
|
||||
}
|
||||
|
||||
void Inventory::SetUnlimited(const gd::String& itemName, bool enable) {
|
||||
if (items.find(itemName) == items.end()) {
|
||||
MakeItemEntry(itemName);
|
||||
}
|
||||
|
||||
items[itemName].unlimited = enable;
|
||||
}
|
||||
|
||||
void Inventory::MakeItemEntry(const gd::String& itemName) {
|
||||
Item item;
|
||||
items[itemName] = item;
|
||||
}
|
||||
|
||||
bool Inventory::Equip(const gd::String& itemName, bool equip) {
|
||||
if (items.find(itemName) == items.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& item = items[itemName];
|
||||
if (!equip) {
|
||||
item.equipped = false;
|
||||
return true;
|
||||
} else if (item.count > 0) {
|
||||
item.equipped = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Inventory::IsEquipped(const gd::String& itemName) {
|
||||
if (items.find(itemName) == items.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return items[itemName].equipped;
|
||||
}
|
||||
|
||||
void Inventory::Clear() { items.clear(); }
|
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include "GDCore/String.h"
|
||||
|
||||
class GD_EXTENSION_API Inventory {
|
||||
public:
|
||||
Inventory(){};
|
||||
virtual ~Inventory(){};
|
||||
|
||||
class Item {
|
||||
public:
|
||||
bool unlimited = true;
|
||||
size_t count = 0;
|
||||
size_t maxCount = 0;
|
||||
bool equipped = false;
|
||||
};
|
||||
|
||||
bool Has(const gd::String& itemName);
|
||||
size_t Count(const gd::String& itemName);
|
||||
bool Add(const gd::String& itemName);
|
||||
bool SetCount(const gd::String& itemName, size_t count);
|
||||
bool IsFull(const gd::String& itemName);
|
||||
bool Remove(const gd::String& itemName);
|
||||
void SetMaximum(const gd::String& itemName, size_t maxCount);
|
||||
void SetUnlimited(const gd::String& itemName, bool enable = true);
|
||||
bool Equip(const gd::String& itemName, bool equip = true);
|
||||
bool IsEquipped(const gd::String& itemName);
|
||||
void Clear();
|
||||
|
||||
const std::map<gd::String, Item>& GetAllItems() { return items; };
|
||||
|
||||
private:
|
||||
void MakeItemEntry(const gd::String& itemName);
|
||||
|
||||
std::map<gd::String, Item> items;
|
||||
};
|
@@ -1,4 +0,0 @@
|
||||
#include "InventoryTools.h"
|
||||
|
||||
std::map<RuntimeGame *, std::map<gd::String, Inventory>>
|
||||
InventoryTools::inventories;
|
@@ -1,106 +0,0 @@
|
||||
#pragma once
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
#include "Inventory.h"
|
||||
|
||||
class GD_EXTENSION_API InventoryTools {
|
||||
public:
|
||||
static bool Add(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
const gd::String &itemName) {
|
||||
return Get(scene, inventoryName).Add(itemName);
|
||||
}
|
||||
|
||||
static size_t Count(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
const gd::String &itemName) {
|
||||
return Get(scene, inventoryName).Count(itemName);
|
||||
}
|
||||
|
||||
static bool Remove(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
const gd::String &itemName) {
|
||||
return Get(scene, inventoryName).Remove(itemName);
|
||||
}
|
||||
|
||||
static bool Has(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
const gd::String &itemName) {
|
||||
return Get(scene, inventoryName).Has(itemName);
|
||||
}
|
||||
|
||||
static void SetMaximum(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
const gd::String &itemName,
|
||||
size_t maxCount) {
|
||||
return Get(scene, inventoryName).SetMaximum(itemName, maxCount);
|
||||
}
|
||||
|
||||
static void SetUnlimited(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
const gd::String &itemName,
|
||||
bool enable) {
|
||||
return Get(scene, inventoryName).SetUnlimited(itemName, enable);
|
||||
}
|
||||
|
||||
static bool Equip(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
const gd::String &itemName,
|
||||
bool equip) {
|
||||
return Get(scene, inventoryName).Equip(itemName, equip);
|
||||
}
|
||||
|
||||
static bool IsEquipped(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
const gd::String &itemName) {
|
||||
return Get(scene, inventoryName).IsEquipped(itemName);
|
||||
}
|
||||
|
||||
static void SerializeToVariable(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
gd::Variable &variable) {
|
||||
auto &allItems = Get(scene, inventoryName).GetAllItems();
|
||||
for (auto &it : allItems) {
|
||||
Inventory::Item item = it.second;
|
||||
gd::Variable &serializedItem = variable.GetChild(it.first);
|
||||
serializedItem.GetChild("count").SetValue(item.count);
|
||||
serializedItem.GetChild("maxCount").SetValue(item.maxCount);
|
||||
serializedItem.GetChild("unlimited")
|
||||
.SetString(item.unlimited ? "true" : "false");
|
||||
serializedItem.GetChild("equipped")
|
||||
.SetString(item.equipped ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
static void UnserializeFromVariable(RuntimeScene &scene,
|
||||
const gd::String &inventoryName,
|
||||
const gd::Variable &variable) {
|
||||
Inventory &inventory = Get(scene, inventoryName);
|
||||
inventory.Clear();
|
||||
|
||||
for (auto &child : variable.GetAllChildren()) {
|
||||
const gd::String &name = child.first;
|
||||
const auto &serializedItem = child.second;
|
||||
inventory.SetMaximum(name,
|
||||
serializedItem->GetChild("maxCount").GetValue());
|
||||
inventory.SetUnlimited(
|
||||
name, serializedItem->GetChild("unlimited").GetString() == "true");
|
||||
inventory.SetCount(name, serializedItem->GetChild("count").GetValue());
|
||||
inventory.Equip(
|
||||
name, serializedItem->GetChild("equipped").GetString() == "true");
|
||||
}
|
||||
}
|
||||
|
||||
static void ClearAll(RuntimeScene &scene) {
|
||||
std::map<gd::String, Inventory> clearedInventories;
|
||||
inventories[scene.game] = clearedInventories;
|
||||
}
|
||||
|
||||
private:
|
||||
static Inventory &Get(RuntimeScene &scene, const gd::String &name) {
|
||||
return inventories[scene.game][name];
|
||||
}
|
||||
|
||||
static std::map<RuntimeGame *, std::map<gd::String, Inventory>> inventories;
|
||||
|
||||
InventoryTools(){};
|
||||
};
|
@@ -6,6 +6,7 @@ This project is released under the MIT License.
|
||||
*/
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
#include <iostream>
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - Inventory Extension
|
||||
Copyright (c) 2011-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
/**
|
||||
* @file Tests for the Inventory extension.
|
||||
*/
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "../Inventory.h"
|
||||
|
||||
TEST_CASE( "Inventory", "[game-engine][inventory]" ) {
|
||||
SECTION("Inventory") {
|
||||
Inventory inventory;
|
||||
|
||||
// Is empty when constructed") {
|
||||
REQUIRE(inventory.Has("sword") == false);
|
||||
REQUIRE(inventory.Has("soul reaver") == false);
|
||||
|
||||
// Can receive one or more items") {
|
||||
REQUIRE(inventory.Add("sword") == true);
|
||||
REQUIRE(inventory.Has("sword") == true);
|
||||
REQUIRE(inventory.Has("soul reaver") == false);
|
||||
|
||||
REQUIRE(inventory.Add("soul reaver") == true);
|
||||
REQUIRE(inventory.Add("sword") == true);
|
||||
REQUIRE(inventory.Has("sword") == true);
|
||||
REQUIRE(inventory.Has("soul reaver") == true);
|
||||
|
||||
// Can return the number of items") {
|
||||
REQUIRE(inventory.Count("sword") == 2);
|
||||
REQUIRE(inventory.Count("soul reaver") == 1);
|
||||
|
||||
// Can equip items") {
|
||||
REQUIRE(inventory.Equip("soul reaver", true) == true);
|
||||
REQUIRE(inventory.IsEquipped("soul reaver") == true);
|
||||
|
||||
REQUIRE(inventory.Equip("sword", true) == true);
|
||||
REQUIRE(inventory.IsEquipped("sword") == true);
|
||||
REQUIRE(inventory.Equip("sword", false) == true);
|
||||
REQUIRE(inventory.IsEquipped("sword") == false);
|
||||
REQUIRE(inventory.Equip("sword", true) == true);
|
||||
|
||||
REQUIRE(inventory.Equip("nothing", true) == false);
|
||||
REQUIRE(inventory.IsEquipped("nothing") == false);
|
||||
|
||||
// Support removing an item") {
|
||||
REQUIRE(inventory.Remove("sword") == true);
|
||||
REQUIRE(inventory.Count("sword") == 1);
|
||||
REQUIRE(inventory.IsEquipped("sword") == true);
|
||||
|
||||
REQUIRE(inventory.Remove("sword") == true);
|
||||
REQUIRE(inventory.Count("sword") == 0);
|
||||
REQUIRE(inventory.IsEquipped("sword") == false);
|
||||
|
||||
REQUIRE(inventory.Remove("sword") == false);
|
||||
REQUIRE(inventory.Count("sword") == 0);
|
||||
|
||||
REQUIRE(inventory.Count("soul reaver") == 1);
|
||||
REQUIRE(inventory.IsEquipped("soul reaver") == true);
|
||||
|
||||
// Can support having a limited number of objects") {
|
||||
REQUIRE(inventory.Count("heavy sword") == 0);
|
||||
inventory.SetMaximum("heavy sword", 2);
|
||||
REQUIRE(inventory.Add("heavy sword") == true);
|
||||
REQUIRE(inventory.Count("heavy sword") == 1);
|
||||
REQUIRE(inventory.Has("heavy sword") == true);
|
||||
|
||||
REQUIRE(inventory.Add("heavy sword") == true);
|
||||
REQUIRE(inventory.Count("heavy sword") == 2);
|
||||
REQUIRE(inventory.Add("heavy sword") == false);
|
||||
REQUIRE(inventory.Count("heavy sword") == 2);
|
||||
inventory.SetUnlimited("heavy sword", true);
|
||||
REQUIRE(inventory.Count("heavy sword") == 2);
|
||||
REQUIRE(inventory.Add("heavy sword") == true);
|
||||
REQUIRE(inventory.Add("heavy sword") == true);
|
||||
REQUIRE(inventory.Count("heavy sword") == 4);
|
||||
|
||||
inventory.SetMaximum("never sword", 0);
|
||||
REQUIRE(inventory.Add("never sword") == false);
|
||||
REQUIRE(inventory.Has("never sword") == false);
|
||||
REQUIRE(inventory.Count("never sword") == 0);
|
||||
}
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - Inventory Extension
|
||||
Copyright (c) 2011-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
#include "../InventoryTools.h"
|
||||
#include "GDCpp/Runtime/Project/Variable.h"
|
||||
#include "GDCpp/Runtime/Serialization/Serializer.h"
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
#include "GDCpp/Runtime/RuntimeGame.h"
|
||||
|
||||
TEST_CASE( "InventoryTools", "[game-engine][inventory-tools]" ) {
|
||||
SECTION("InventoryTools") {
|
||||
RuntimeGame game;
|
||||
RuntimeScene scene(NULL, &game);
|
||||
|
||||
InventoryTools::Add(scene, "MyInventory", "sword");
|
||||
InventoryTools::Add(scene, "MyInventory", "sword");
|
||||
InventoryTools::Equip(scene, "MyInventory", "sword", true);
|
||||
InventoryTools::Add(scene, "MyInventory", "armor");
|
||||
InventoryTools::SetMaximum(scene, "MyInventory", "armor", 1);
|
||||
|
||||
gd::Variable variable;
|
||||
InventoryTools::SerializeToVariable(scene, "MyInventory", variable);
|
||||
InventoryTools::UnserializeFromVariable(scene, "MyInventory2", variable);
|
||||
|
||||
REQUIRE(InventoryTools::Count(scene, "MyInventory2", "sword") == 2);
|
||||
REQUIRE(InventoryTools::IsEquipped(scene, "MyInventory2", "sword") == true);
|
||||
REQUIRE(InventoryTools::Count(scene, "MyInventory2", "armor") == 1);
|
||||
REQUIRE(InventoryTools::Add(scene, "MyInventory2", "armor") == false);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -13,20 +13,8 @@ gd_add_extension_definitions(LinkedObjects)
|
||||
include_directories(.)
|
||||
file(GLOB source_files *.cpp *.h)
|
||||
gd_add_clang_utils(LinkedObjects "${source_files}")
|
||||
|
||||
gd_add_extension_target(LinkedObjects "${source_files}")
|
||||
gdcpp_add_runtime_extension_target(LinkedObjects_Runtime "${source_files}")
|
||||
|
||||
#Linker files for the IDE extension
|
||||
###
|
||||
gd_extension_link_libraries(LinkedObjects)
|
||||
|
||||
|
||||
#Linker files for the GD C++ Runtime extension
|
||||
###
|
||||
gdcpp_runtime_extension_link_libraries(LinkedObjects_Runtime)
|
||||
|
||||
#Tests for the GD C++ Runtime extension
|
||||
###
|
||||
file(GLOB_RECURSE test_source_files tests/*)
|
||||
gdcpp_add_tests_extension_target(LinkedObjects_Runtime_tests "${test_source_files}")
|
||||
gd_extension_link_libraries(LinkedObjects)
|
@@ -7,8 +7,8 @@ This project is released under the MIT License.
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "ObjectsLinksManager.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
void DeclareLinkedObjectsExtension(gd::PlatformExtension& extension) {
|
||||
extension
|
||||
@@ -112,60 +112,3 @@ void DeclareLinkedObjectsExtension(gd::PlatformExtension& extension) {
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief This class declares information about the extension.
|
||||
*/
|
||||
class LinkedObjectsCppExtension : public ExtensionBase {
|
||||
public:
|
||||
/**
|
||||
* Constructor of an extension declares everything the extension contains:
|
||||
* objects, actions, conditions and expressions.
|
||||
*/
|
||||
LinkedObjectsCppExtension() {
|
||||
DeclareLinkedObjectsExtension(*this);
|
||||
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
|
||||
};
|
||||
|
||||
/**
|
||||
* The extension must be aware of objects deletion
|
||||
*/
|
||||
virtual bool ToBeNotifiedOnObjectDeletion() { return true; }
|
||||
|
||||
/**
|
||||
* Be sure to remove all links when an object is deleted
|
||||
*/
|
||||
virtual void ObjectDeletedFromScene(RuntimeScene& scene,
|
||||
RuntimeObject* object) {
|
||||
GDpriv::LinkedObjects::ObjectsLinksManager::managers[&scene]
|
||||
.RemoveAllLinksOf(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize manager of linked objects of scene
|
||||
*/
|
||||
virtual void SceneLoaded(RuntimeScene& scene) {
|
||||
GDpriv::LinkedObjects::ObjectsLinksManager::managers[&scene].ClearAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy manager of linked objects of scene
|
||||
*/
|
||||
virtual void SceneUnloaded(RuntimeScene& scene) {
|
||||
GDpriv::LinkedObjects::ObjectsLinksManager::managers.erase(&scene);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(ANDROID)
|
||||
extern "C" ExtensionBase* CreateGDCppLinkedObjectsExtension() {
|
||||
return new LinkedObjectsCppExtension;
|
||||
}
|
||||
#elif !defined(EMSCRIPTEN)
|
||||
/**
|
||||
* Used by GDevelop to create the extension class
|
||||
* -- Do not need to be modified. --
|
||||
*/
|
||||
extern "C" ExtensionBase* GD_EXTENSION_API CreateGDExtension() {
|
||||
return new LinkedObjectsCppExtension;
|
||||
}
|
||||
#endif
|
||||
|
@@ -6,6 +6,7 @@ This project is released under the MIT License.
|
||||
*/
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
#include <iostream>
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - LinkedObjects Extension
|
||||
Copyright (c) 2011-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "LinkedObjectsTools.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <memory>
|
||||
#include "GDCpp/Runtime/RuntimeObject.h"
|
||||
#include "GDCpp/Runtime/RuntimeObjectsListsTools.h"
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
#include "ObjectsLinksManager.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace GDpriv {
|
||||
namespace LinkedObjects {
|
||||
|
||||
std::map<RuntimeScene*, ObjectsLinksManager> ObjectsLinksManager::managers;
|
||||
|
||||
bool GD_EXTENSION_API PickObjectsLinkedTo(
|
||||
RuntimeScene& scene,
|
||||
std::map<gd::String, std::vector<RuntimeObject*>*> pickedObjectsLists,
|
||||
RuntimeObject* object) {
|
||||
if (!object) return false;
|
||||
|
||||
std::vector<RuntimeObject*> linkedObjects =
|
||||
ObjectsLinksManager::managers[&scene].GetObjectsLinkedWith(object);
|
||||
return PickObjectsIf(
|
||||
pickedObjectsLists, false, [&linkedObjects](RuntimeObject* obj) {
|
||||
return std::find(linkedObjects.begin(), linkedObjects.end(), obj) !=
|
||||
linkedObjects.end();
|
||||
});
|
||||
}
|
||||
|
||||
void GD_EXTENSION_API LinkObjects(RuntimeScene& scene,
|
||||
RuntimeObject* a,
|
||||
RuntimeObject* b) {
|
||||
if (!a || !b) return;
|
||||
ObjectsLinksManager::managers[&scene].LinkObjects(a, b);
|
||||
}
|
||||
|
||||
void GD_EXTENSION_API RemoveLinkBetween(RuntimeScene& scene,
|
||||
RuntimeObject* a,
|
||||
RuntimeObject* b) {
|
||||
if (!a || !b) return;
|
||||
ObjectsLinksManager::managers[&scene].RemoveLinkBetween(a, b);
|
||||
}
|
||||
|
||||
void GD_EXTENSION_API RemoveAllLinksOf(RuntimeScene& scene,
|
||||
RuntimeObject* object) {
|
||||
if (!object) return;
|
||||
ObjectsLinksManager::managers[&scene].RemoveAllLinksOf(object);
|
||||
}
|
||||
|
||||
} // namespace LinkedObjects
|
||||
} // namespace GDpriv
|
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - LinkedObjects Extension
|
||||
Copyright (c) 2011-2013 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef LINKEDOBJECTSTOOLS_H_INCLUDED
|
||||
#define LINKEDOBJECTSTOOLS_H_INCLUDED
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "GDCpp/Runtime/String.h"
|
||||
class RuntimeObject;
|
||||
class RuntimeScene;
|
||||
|
||||
namespace GDpriv {
|
||||
|
||||
namespace LinkedObjects {
|
||||
|
||||
void GD_EXTENSION_API LinkObjects(RuntimeScene &scene,
|
||||
RuntimeObject *a,
|
||||
RuntimeObject *b);
|
||||
void GD_EXTENSION_API RemoveLinkBetween(RuntimeScene &scene,
|
||||
RuntimeObject *a,
|
||||
RuntimeObject *b);
|
||||
void GD_EXTENSION_API RemoveAllLinksOf(RuntimeScene &scene,
|
||||
RuntimeObject *object);
|
||||
bool GD_EXTENSION_API PickObjectsLinkedTo(
|
||||
RuntimeScene &scene,
|
||||
std::map<gd::String, std::vector<RuntimeObject *> *> pickedObjectsLists,
|
||||
RuntimeObject *object);
|
||||
|
||||
} // namespace LinkedObjects
|
||||
|
||||
} // namespace GDpriv
|
||||
|
||||
#endif // LINKEDOBJECTSTOOLS_H_INCLUDED
|
@@ -1,78 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - LinkedObjects Extension
|
||||
Copyright (c) 2011-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "ObjectsLinksManager.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "LinkedObjectsTools.h"
|
||||
|
||||
#include <memory>
|
||||
#include "GDCpp/Runtime/RuntimeObject.h"
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace GDpriv {
|
||||
namespace LinkedObjects {
|
||||
|
||||
void ObjectsLinksManager::LinkObjects(RuntimeObject* a, RuntimeObject* b) {
|
||||
{
|
||||
std::set<RuntimeObject*>& objectLinks = links[a];
|
||||
objectLinks.insert(b);
|
||||
}
|
||||
{
|
||||
std::set<RuntimeObject*>& objectLinks = links[b];
|
||||
objectLinks.insert(a);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectsLinksManager::RemoveLinkBetween(RuntimeObject* a,
|
||||
RuntimeObject* b) {
|
||||
{
|
||||
std::set<RuntimeObject*>& objectLinks = links[a];
|
||||
objectLinks.erase(b);
|
||||
}
|
||||
{
|
||||
std::set<RuntimeObject*>& objectLinks = links[b];
|
||||
objectLinks.erase(a);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectsLinksManager::RemoveAllLinksOf(RuntimeObject* object) {
|
||||
std::set<RuntimeObject*>& objectLinks = links[object];
|
||||
for (std::set<RuntimeObject*>::iterator linkedObj = objectLinks.begin();
|
||||
linkedObj != objectLinks.end();
|
||||
++linkedObj) {
|
||||
std::set<RuntimeObject*>& linkedObjectLinks = links[*linkedObj];
|
||||
linkedObjectLinks.erase(object);
|
||||
}
|
||||
|
||||
links.erase(object); // Remove all links of object
|
||||
}
|
||||
|
||||
std::vector<RuntimeObject*> ObjectsLinksManager::GetObjectsLinkedWith(
|
||||
RuntimeObject* object) {
|
||||
// Get links of object
|
||||
const std::set<RuntimeObject*>& objectLinks = links[object];
|
||||
std::vector<RuntimeObject*> list;
|
||||
list.reserve(objectLinks.size());
|
||||
|
||||
// Create the list, avoiding dead links or links to just deleted objects
|
||||
for (std::set<RuntimeObject*>::iterator linkedObj = objectLinks.begin();
|
||||
linkedObj != objectLinks.end();
|
||||
++linkedObj) {
|
||||
if (!(*linkedObj)->GetName().empty()) list.push_back((*linkedObj));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void ObjectsLinksManager::ClearAll() { links.clear(); }
|
||||
|
||||
} // namespace LinkedObjects
|
||||
} // namespace GDpriv
|
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - LinkedObjects Extension
|
||||
Copyright (c) 2011-2013 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef OBJECTSLINKSMANAGER_H
|
||||
#define OBJECTSLINKSMANAGER_H
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class RuntimeObject;
|
||||
class RuntimeScene;
|
||||
|
||||
namespace GDpriv {
|
||||
|
||||
namespace LinkedObjects {
|
||||
|
||||
/**
|
||||
* \brief Manage links between objects of a scene
|
||||
*/
|
||||
class GD_EXTENSION_API ObjectsLinksManager {
|
||||
public:
|
||||
/**
|
||||
* \brief Link two object
|
||||
*/
|
||||
void LinkObjects(RuntimeObject* a, RuntimeObject* b);
|
||||
|
||||
/**
|
||||
* \brief Remove link between a and b
|
||||
*/
|
||||
void RemoveLinkBetween(RuntimeObject* a, RuntimeObject* b);
|
||||
|
||||
/**
|
||||
* \brief Remove all links concerning the object
|
||||
*/
|
||||
void RemoveAllLinksOf(RuntimeObject* object);
|
||||
|
||||
/**
|
||||
* \brief Get a list of (raw pointers to) all objects linked with the
|
||||
* specified object
|
||||
*/
|
||||
std::vector<RuntimeObject*> GetObjectsLinkedWith(RuntimeObject* object);
|
||||
|
||||
/**
|
||||
* \brief Delete all links
|
||||
*/
|
||||
void ClearAll();
|
||||
|
||||
static std::map<RuntimeScene*, ObjectsLinksManager>
|
||||
managers; // List of managers associated with scenes.
|
||||
|
||||
private:
|
||||
std::map<RuntimeObject*, std::set<RuntimeObject*> > links;
|
||||
};
|
||||
|
||||
} // namespace LinkedObjects
|
||||
} // namespace GDpriv
|
||||
|
||||
#endif // OBJECTSLINKSMANAGER_H
|
@@ -1,88 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - LinkedObjects Extension
|
||||
Copyright (c) 2011-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
/**
|
||||
* @file Tests for the Linked Objects extension.
|
||||
*/
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
#include "GDCpp/Runtime/RuntimeGame.h"
|
||||
#include "GDCpp/Runtime/RuntimeObject.h"
|
||||
#include "GDCpp/Extensions/Builtin/ObjectTools.h"
|
||||
#include "GDCpp/Extensions/Builtin/ObjectTools.h"
|
||||
#include "../LinkedObjectsTools.h"
|
||||
#include "../ObjectsLinksManager.h"
|
||||
|
||||
TEST_CASE( "LinkedObjects", "[game-engine][linked-objects]" ) {
|
||||
SECTION("LinkedObjectsTools") {
|
||||
//Prepare some objects and the context
|
||||
gd::Object obj1("1");
|
||||
gd::Object obj2("2");
|
||||
|
||||
RuntimeGame game;
|
||||
RuntimeScene scene(NULL, &game);
|
||||
|
||||
RuntimeObject obj1A(scene, obj1);
|
||||
RuntimeObject obj1B(scene, obj1);
|
||||
RuntimeObject obj1C(scene, obj1);
|
||||
|
||||
RuntimeObject obj2A(scene, obj2);
|
||||
RuntimeObject obj2B(scene, obj2);
|
||||
RuntimeObject obj2C(scene, obj2);
|
||||
|
||||
//Link two objects
|
||||
GDpriv::LinkedObjects::ObjectsLinksManager & manager = GDpriv::LinkedObjects::ObjectsLinksManager::managers[&scene];
|
||||
manager.LinkObjects(&obj1A, &obj2A);
|
||||
{
|
||||
std::vector<RuntimeObject*> linkedObjects = manager.GetObjectsLinkedWith(&obj1A);
|
||||
REQUIRE(linkedObjects.size() == 1);
|
||||
REQUIRE(linkedObjects[0] == &obj2A);
|
||||
}
|
||||
{
|
||||
std::vector<RuntimeObject*> linkedObjects = manager.GetObjectsLinkedWith(&obj2A);
|
||||
REQUIRE(linkedObjects.size() == 1);
|
||||
REQUIRE(linkedObjects[0] == &obj1A);
|
||||
}
|
||||
|
||||
//Link more objects
|
||||
manager.LinkObjects(&obj1A, &obj2A); //Including the same objects as before
|
||||
manager.LinkObjects(&obj1A, &obj2B);
|
||||
manager.LinkObjects(&obj1A, &obj2C);
|
||||
{
|
||||
std::vector<RuntimeObject*> linkedObjects = manager.GetObjectsLinkedWith(&obj1A);
|
||||
REQUIRE(linkedObjects.size() == 3);
|
||||
}
|
||||
{
|
||||
std::vector<RuntimeObject*> linkedObjects = manager.GetObjectsLinkedWith(&obj2C);
|
||||
REQUIRE(linkedObjects.size() == 1);
|
||||
REQUIRE(linkedObjects[0] == &obj1A);
|
||||
}
|
||||
|
||||
//Remove all links
|
||||
manager.LinkObjects(&obj2B, &obj2C);
|
||||
manager.RemoveAllLinksOf(&obj1A);
|
||||
manager.RemoveAllLinksOf(&obj1A);
|
||||
{
|
||||
std::vector<RuntimeObject*> linkedObjects = manager.GetObjectsLinkedWith(&obj1A);
|
||||
REQUIRE(linkedObjects.size() == 0);
|
||||
}
|
||||
{
|
||||
std::vector<RuntimeObject*> linkedObjects = manager.GetObjectsLinkedWith(&obj2A);
|
||||
REQUIRE(linkedObjects.size() == 0);
|
||||
}
|
||||
{
|
||||
std::vector<RuntimeObject*> linkedObjects = manager.GetObjectsLinkedWith(&obj2C);
|
||||
REQUIRE(linkedObjects.size() == 1);
|
||||
REQUIRE(linkedObjects[0] == &obj2B);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -13,14 +13,8 @@ gd_add_extension_definitions(PanelSpriteObject)
|
||||
include_directories(.)
|
||||
file(GLOB source_files *.cpp *.h)
|
||||
gd_add_clang_utils(PanelSpriteObject "${source_files}")
|
||||
|
||||
gd_add_extension_target(PanelSpriteObject "${source_files}")
|
||||
gdcpp_add_runtime_extension_target(PanelSpriteObject_Runtime "${source_files}")
|
||||
|
||||
#Linker files for the IDE extension
|
||||
###
|
||||
gd_extension_link_libraries(PanelSpriteObject)
|
||||
|
||||
#Linker files for the GD C++ Runtime extension
|
||||
###
|
||||
gdcpp_runtime_extension_link_libraries(PanelSpriteObject_Runtime)
|
||||
|
@@ -9,7 +9,8 @@ This project is released under the MIT License.
|
||||
* Florian Rival ( Minor changes and adaptations )
|
||||
*/
|
||||
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "PanelSpriteObject.h"
|
||||
|
||||
void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
|
||||
@@ -177,36 +178,3 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
|
||||
.SetIncludeFile("PanelSpriteObject/PanelSpriteObject.h");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief This class declares information about the extension.
|
||||
*/
|
||||
class PanelSpriteObjectCppExtension : public ExtensionBase {
|
||||
public:
|
||||
/**
|
||||
* Constructor of an extension declares everything the extension contains:
|
||||
* objects, actions, conditions and expressions.
|
||||
*/
|
||||
PanelSpriteObjectCppExtension() {
|
||||
DeclarePanelSpriteObjectExtension(*this);
|
||||
AddRuntimeObject<PanelSpriteObject, RuntimePanelSpriteObject>(
|
||||
GetObjectMetadata("PanelSpriteObject::PanelSprite"),
|
||||
"RuntimePanelSpriteObject");
|
||||
|
||||
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
|
||||
};
|
||||
};
|
||||
|
||||
#if defined(ANDROID)
|
||||
extern "C" ExtensionBase* CreateGDCppPanelSpriteObjectExtension() {
|
||||
return new PanelSpriteObjectCppExtension;
|
||||
}
|
||||
#elif !defined(EMSCRIPTEN)
|
||||
/**
|
||||
* Used by GDevelop to create the extension class
|
||||
* -- Do not need to be modified. --
|
||||
*/
|
||||
extern "C" ExtensionBase* GD_EXTENSION_API CreateGDExtension() {
|
||||
return new PanelSpriteObjectCppExtension;
|
||||
}
|
||||
#endif
|
||||
|
@@ -7,16 +7,11 @@ This project is released under the MIT License.
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCpp/Runtime/CommonTools.h"
|
||||
#include "GDCpp/Runtime/FontManager.h"
|
||||
#include "GDCpp/Runtime/ImageManager.h"
|
||||
#include "GDCpp/Runtime/Polygon2d.h"
|
||||
#include "GDCpp/Runtime/Project/InitialInstance.h"
|
||||
#include "GDCpp/Runtime/Project/Object.h"
|
||||
#include "GDCpp/Runtime/Project/Project.h"
|
||||
#include "GDCpp/Runtime/RuntimeGame.h"
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Project/InitialInstance.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "PanelSpriteObject.h"
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
@@ -60,194 +55,8 @@ void PanelSpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
|
||||
element.SetAttribute("bottomMargin", bottomMargin);
|
||||
element.SetAttribute("tiled", tiled);
|
||||
}
|
||||
#endif
|
||||
|
||||
RuntimePanelSpriteObject::RuntimePanelSpriteObject(
|
||||
RuntimeScene& scene, const PanelSpriteObject& panelSpriteObject)
|
||||
: RuntimeObject(scene, panelSpriteObject), width(32), height(32), angle(0) {
|
||||
SetRightMargin(panelSpriteObject.GetRightMargin());
|
||||
SetLeftMargin(panelSpriteObject.GetLeftMargin());
|
||||
SetBottomMargin(panelSpriteObject.GetBottomMargin());
|
||||
SetTopMargin(panelSpriteObject.GetTopMargin());
|
||||
SetWidth(panelSpriteObject.GetWidth());
|
||||
SetHeight(panelSpriteObject.GetHeight());
|
||||
|
||||
textureName = panelSpriteObject.textureName;
|
||||
ChangeAndReloadImage(textureName, scene);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render object at runtime
|
||||
*/
|
||||
bool RuntimePanelSpriteObject::Draw(sf::RenderTarget& window) {
|
||||
// Don't draw anything if hidden
|
||||
if (hidden) return true;
|
||||
if (!texture) return true;
|
||||
|
||||
sf::Vector2f centerPosition =
|
||||
sf::Vector2f(GetX() + GetCenterX(), GetY() + GetCenterY());
|
||||
|
||||
float imageWidth = texture->texture.getSize().x;
|
||||
float imageHeight = texture->texture.getSize().y;
|
||||
|
||||
sf::Vertex centerVertices[] = {
|
||||
sf::Vertex(sf::Vector2f(-width / 2 + leftMargin, -height / 2 + topMargin),
|
||||
sf::Vector2f(leftMargin, topMargin)),
|
||||
sf::Vertex(
|
||||
sf::Vector2f(+width / 2 - rightMargin, -height / 2 + topMargin),
|
||||
sf::Vector2f(imageWidth - rightMargin, topMargin)),
|
||||
sf::Vertex(
|
||||
sf::Vector2f(-width / 2 + leftMargin, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(leftMargin, imageHeight - bottomMargin)),
|
||||
sf::Vertex(
|
||||
sf::Vector2f(+width / 2 - rightMargin, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(imageWidth - rightMargin, imageHeight - bottomMargin)),
|
||||
};
|
||||
|
||||
sf::Vertex topVertices[] = {
|
||||
// Top-left
|
||||
sf::Vertex(sf::Vector2f(-width / 2, -height / 2), sf::Vector2f(0, 0)),
|
||||
sf::Vertex(sf::Vector2f(-width / 2, -height / 2 + topMargin),
|
||||
sf::Vector2f(0, topMargin)),
|
||||
sf::Vertex(sf::Vector2f(-width / 2 + leftMargin, -height / 2),
|
||||
sf::Vector2f(leftMargin, 0)),
|
||||
sf::Vertex(sf::Vector2f(-width / 2 + leftMargin, -height / 2 + topMargin),
|
||||
sf::Vector2f(leftMargin, topMargin)),
|
||||
|
||||
// Top
|
||||
sf::Vertex(sf::Vector2f(+width / 2 - rightMargin, -height / 2),
|
||||
sf::Vector2f(imageWidth - rightMargin, 0)),
|
||||
sf::Vertex(
|
||||
sf::Vector2f(+width / 2 - rightMargin, -height / 2 + topMargin),
|
||||
sf::Vector2f(imageWidth - rightMargin, topMargin)),
|
||||
|
||||
// Top-right
|
||||
sf::Vertex(sf::Vector2f(+width / 2, -height / 2),
|
||||
sf::Vector2f(imageWidth, 0)),
|
||||
sf::Vertex(sf::Vector2f(+width / 2, -height / 2 + topMargin),
|
||||
sf::Vector2f(imageWidth, topMargin)),
|
||||
};
|
||||
|
||||
sf::Vertex rightVertices[] = {
|
||||
sf::Vertex(
|
||||
sf::Vector2f(+width / 2 - rightMargin, -height / 2 + topMargin),
|
||||
sf::Vector2f(imageWidth - rightMargin, topMargin)),
|
||||
sf::Vertex(sf::Vector2f(+width / 2, -height / 2 + topMargin),
|
||||
sf::Vector2f(imageWidth, topMargin)),
|
||||
sf::Vertex(
|
||||
sf::Vector2f(+width / 2 - rightMargin, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(imageWidth - rightMargin, imageHeight - bottomMargin)),
|
||||
sf::Vertex(sf::Vector2f(+width / 2, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(imageWidth, imageHeight - bottomMargin))};
|
||||
|
||||
sf::Vertex bottomVertices[] = {
|
||||
// Bottom-left
|
||||
sf::Vertex(sf::Vector2f(-width / 2, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(0, imageHeight - bottomMargin)),
|
||||
sf::Vertex(sf::Vector2f(-width / 2, +height / 2),
|
||||
sf::Vector2f(0, imageHeight)),
|
||||
sf::Vertex(
|
||||
sf::Vector2f(-width / 2 + leftMargin, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(leftMargin, imageHeight - bottomMargin)),
|
||||
sf::Vertex(sf::Vector2f(-width / 2 + leftMargin, +height / 2),
|
||||
sf::Vector2f(leftMargin, imageHeight)),
|
||||
|
||||
// Bottom
|
||||
sf::Vertex(
|
||||
sf::Vector2f(+width / 2 - rightMargin, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(imageWidth - rightMargin, imageHeight - bottomMargin)),
|
||||
sf::Vertex(sf::Vector2f(+width / 2 - rightMargin, +height / 2),
|
||||
sf::Vector2f(imageWidth - rightMargin, imageHeight)),
|
||||
|
||||
// Bottom-right
|
||||
sf::Vertex(sf::Vector2f(+width / 2, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(imageWidth, imageHeight - bottomMargin)),
|
||||
sf::Vertex(sf::Vector2f(+width / 2, +height / 2),
|
||||
sf::Vector2f(imageWidth, imageHeight))};
|
||||
|
||||
sf::Vertex leftVertices[] = {
|
||||
sf::Vertex(sf::Vector2f(-width / 2, -height / 2 + topMargin),
|
||||
sf::Vector2f(0, topMargin)),
|
||||
sf::Vertex(sf::Vector2f(-width / 2 + leftMargin, -height / 2 + topMargin),
|
||||
sf::Vector2f(leftMargin, topMargin)),
|
||||
sf::Vertex(sf::Vector2f(-width / 2, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(0, imageHeight - bottomMargin)),
|
||||
sf::Vertex(
|
||||
sf::Vector2f(-width / 2 + leftMargin, +height / 2 - bottomMargin),
|
||||
sf::Vector2f(leftMargin, imageHeight - bottomMargin))};
|
||||
|
||||
sf::Transform matrix;
|
||||
matrix.translate(centerPosition);
|
||||
matrix.rotate(angle);
|
||||
|
||||
sf::RenderStates states;
|
||||
states.transform = matrix;
|
||||
states.texture = &texture->texture;
|
||||
|
||||
window.draw(centerVertices, 4, sf::TrianglesStrip, states);
|
||||
window.draw(leftVertices, 4, sf::TrianglesStrip, states);
|
||||
window.draw(rightVertices, 4, sf::TrianglesStrip, states);
|
||||
window.draw(topVertices, 8, sf::TrianglesStrip, states);
|
||||
window.draw(bottomVertices, 8, sf::TrianglesStrip, states);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void PanelSpriteObject::ExposeResources(gd::ArbitraryResourceWorker& worker) {
|
||||
worker.ExposeImage(textureName);
|
||||
}
|
||||
|
||||
void RuntimePanelSpriteObject::GetPropertyForDebugger(std::size_t propertyNb,
|
||||
gd::String& name,
|
||||
gd::String& value) const {
|
||||
if (propertyNb == 0) {
|
||||
name = _("Width");
|
||||
value = gd::String::From(width);
|
||||
} else if (propertyNb == 1) {
|
||||
name = _("Height");
|
||||
value = gd::String::From(height);
|
||||
} else if (propertyNb == 2) {
|
||||
name = _("Left Margin");
|
||||
value = gd::String::From(leftMargin);
|
||||
} else if (propertyNb == 3) {
|
||||
name = _("Top Margin");
|
||||
value = gd::String::From(topMargin);
|
||||
} else if (propertyNb == 4) {
|
||||
name = _("Right Margin");
|
||||
value = gd::String::From(rightMargin);
|
||||
} else if (propertyNb == 5) {
|
||||
name = _("Bottom Margin");
|
||||
value = gd::String::From(bottomMargin);
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimePanelSpriteObject::ChangeProperty(std::size_t propertyNb,
|
||||
gd::String newValue) {
|
||||
if (propertyNb == 0) {
|
||||
width = newValue.To<float>();
|
||||
} else if (propertyNb == 1) {
|
||||
height = newValue.To<float>();
|
||||
} else if (propertyNb == 2) {
|
||||
leftMargin = newValue.To<float>();
|
||||
} else if (propertyNb == 3) {
|
||||
topMargin = newValue.To<float>();
|
||||
} else if (propertyNb == 4) {
|
||||
rightMargin = newValue.To<float>();
|
||||
} else if (propertyNb == 5) {
|
||||
bottomMargin = newValue.To<float>();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t RuntimePanelSpriteObject::GetNumberOfProperties() const {
|
||||
return 6;
|
||||
}
|
||||
#endif
|
||||
|
||||
void RuntimePanelSpriteObject::ChangeAndReloadImage(const gd::String& txtName,
|
||||
const RuntimeScene& scene) {
|
||||
textureName = txtName;
|
||||
texture = scene.GetImageManager()->GetSFMLTexture(textureName);
|
||||
}
|
||||
|
@@ -8,10 +8,7 @@ This project is released under the MIT License.
|
||||
#ifndef PANELSPRITEOBJECT_H
|
||||
#define PANELSPRITEOBJECT_H
|
||||
#include <memory>
|
||||
#include "GDCpp/Runtime/Project/Object.h"
|
||||
#include "GDCpp/Runtime/RuntimeObject.h"
|
||||
class SFMLTextureWrapper;
|
||||
class RuntimeScene;
|
||||
#include "GDCore/Project/Object.h"
|
||||
namespace gd {
|
||||
class Object;
|
||||
class InitialInstance;
|
||||
@@ -84,77 +81,6 @@ class GD_EXTENSION_API PanelSpriteObject : public gd::Object {
|
||||
float bottomMargin;
|
||||
|
||||
bool tiled;
|
||||
|
||||
std::shared_ptr<SFMLTextureWrapper> texture;
|
||||
};
|
||||
|
||||
class GD_EXTENSION_API RuntimePanelSpriteObject : public RuntimeObject {
|
||||
public:
|
||||
RuntimePanelSpriteObject(RuntimeScene &scene,
|
||||
const PanelSpriteObject &panelSpriteObject);
|
||||
virtual ~RuntimePanelSpriteObject(){};
|
||||
virtual std::unique_ptr<RuntimeObject> Clone() const {
|
||||
return gd::make_unique<RuntimePanelSpriteObject>(*this);
|
||||
}
|
||||
|
||||
virtual bool Draw(sf::RenderTarget &renderTarget);
|
||||
|
||||
virtual float GetWidth() const { return width; };
|
||||
virtual float GetHeight() const { return height; };
|
||||
|
||||
virtual inline void SetWidth(float newWidth) {
|
||||
width = newWidth >= (leftMargin + rightMargin) ? newWidth
|
||||
: (leftMargin + rightMargin);
|
||||
};
|
||||
virtual inline void SetHeight(float newHeight) {
|
||||
height = newHeight >= (topMargin + bottomMargin)
|
||||
? newHeight
|
||||
: (topMargin + bottomMargin);
|
||||
};
|
||||
|
||||
virtual bool SetAngle(float newAngle) {
|
||||
angle = newAngle;
|
||||
return true;
|
||||
};
|
||||
virtual float GetAngle() const { return angle; };
|
||||
|
||||
float GetLeftMargin() const { return leftMargin; };
|
||||
void SetLeftMargin(float newMargin) { leftMargin = newMargin; };
|
||||
|
||||
float GetTopMargin() const { return topMargin; };
|
||||
void SetTopMargin(float newMargin) { topMargin = newMargin; };
|
||||
|
||||
float GetRightMargin() const { return rightMargin; };
|
||||
void SetRightMargin(float newMargin) { rightMargin = newMargin; };
|
||||
|
||||
float GetBottomMargin() const { return bottomMargin; };
|
||||
void SetBottomMargin(float newMargin) { bottomMargin = newMargin; };
|
||||
|
||||
void ChangeAndReloadImage(const gd::String &texture,
|
||||
const RuntimeScene &scene);
|
||||
|
||||
gd::String textureName;
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
virtual void GetPropertyForDebugger(std::size_t propertyNb,
|
||||
gd::String &name,
|
||||
gd::String &value) const;
|
||||
virtual bool ChangeProperty(std::size_t propertyNb, gd::String newValue);
|
||||
virtual std::size_t GetNumberOfProperties() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
float width;
|
||||
float height;
|
||||
|
||||
float leftMargin;
|
||||
float topMargin;
|
||||
float rightMargin;
|
||||
float bottomMargin;
|
||||
|
||||
float angle;
|
||||
|
||||
std::shared_ptr<SFMLTextureWrapper> texture;
|
||||
};
|
||||
|
||||
#endif // PANELSPRITEOBJECT_H
|
||||
|
@@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 2.6)
|
||||
cmake_policy(SET CMP0015 NEW)
|
||||
|
||||
project(ParticleSystem)
|
||||
|
||||
gd_add_extension_includes()
|
||||
|
||||
#Defines
|
||||
@@ -11,19 +10,12 @@ gd_add_extension_definitions(ParticleSystem)
|
||||
|
||||
#The targets
|
||||
###
|
||||
include_directories(./SPARK/include)
|
||||
include_directories(.)
|
||||
file(GLOB source_files *.cpp *.h "SPARK/src/SPK_All.cpp" "SPARK/src/SPK_GL_All.cpp") #Also compiles the SPARK particle engine files.
|
||||
file(GLOB formatted_source_files *.cpp *.h)
|
||||
gd_add_clang_utils(ParticleSystem "${formatted_source_files}")
|
||||
|
||||
file(GLOB source_files *.cpp *.h)
|
||||
gd_add_clang_utils(ParticleSystem "${source_files}")
|
||||
gd_add_extension_target(ParticleSystem "${source_files}")
|
||||
gdcpp_add_runtime_extension_target(ParticleSystem_Runtime "${source_files}")
|
||||
|
||||
|
||||
#Linker files for the IDE extension
|
||||
###
|
||||
gd_extension_link_libraries(ParticleSystem)
|
||||
|
||||
#Linker files for the GD C++ Runtime extension
|
||||
###
|
||||
gdcpp_runtime_extension_link_libraries(ParticleSystem_Runtime)
|
||||
|
@@ -10,8 +10,9 @@ This project is released under the MIT License.
|
||||
#include "ExtensionSubDeclaration1.h"
|
||||
#include "ExtensionSubDeclaration2.h"
|
||||
#include "ExtensionSubDeclaration3.h"
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "GDCpp/Runtime/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "ParticleEmitterObject.h"
|
||||
|
||||
void DeclareParticleSystemExtension(gd::PlatformExtension& extension) {
|
||||
@@ -45,393 +46,4 @@ void DeclareParticleSystemExtension(gd::PlatformExtension& extension) {
|
||||
ExtensionSubDeclaration3(obj);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor of an extension declares everything the extension contains:
|
||||
* objects, actions, conditions and expressions.
|
||||
*/
|
||||
ParticleSystemCppExtension::ParticleSystemCppExtension() {
|
||||
DeclareParticleSystemExtension(*this);
|
||||
AddRuntimeObject<ParticleEmitterObject, RuntimeParticleEmitterObject>(
|
||||
GetObjectMetadata("ParticleSystem::ParticleEmitter"),
|
||||
"RuntimeParticleEmitterObject");
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
auto& actions = GetAllActionsForObject("ParticleSystem::ParticleEmitter");
|
||||
auto& conditions =
|
||||
GetAllConditionsForObject("ParticleSystem::ParticleEmitter");
|
||||
auto& expressions =
|
||||
GetAllExpressionsForObject("ParticleSystem::ParticleEmitter");
|
||||
auto& strExpressions =
|
||||
GetAllStrExpressionsForObject("ParticleSystem::ParticleEmitter");
|
||||
|
||||
actions["ParticleSystem::EmitterForceMin"]
|
||||
.SetFunctionName("SetEmitterForceMin")
|
||||
.SetGetter("GetEmitterForceMin")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::EmitterForceMax"]
|
||||
.SetFunctionName("SetEmitterForceMax")
|
||||
.SetGetter("GetEmitterForceMax")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::EmitterXDirection"]
|
||||
.SetFunctionName("SetEmitterXDirection")
|
||||
.SetGetter("GetEmitterXDirection")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::EmitterXDirection"]
|
||||
.SetFunctionName("GetEmitterXDirection")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::EmitterYDirection"]
|
||||
.SetFunctionName("SetEmitterYDirection")
|
||||
.SetGetter("GetEmitterYDirection")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::EmitterYDirection"]
|
||||
.SetFunctionName("GetEmitterYDirection")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::EmitterZDirection"]
|
||||
.SetFunctionName("SetEmitterZDirection")
|
||||
.SetGetter("GetEmitterZDirection")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::EmitterZDirection"]
|
||||
.SetFunctionName("GetEmitterZDirection")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::EmitterAngle"]
|
||||
.SetFunctionName("SetAngle")
|
||||
.SetGetter("GetAngle")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::EmitterAngle"]
|
||||
.SetFunctionName("GetAngle")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::EmitterAngleA"]
|
||||
.SetFunctionName("SetEmitterAngleA")
|
||||
.SetGetter("GetEmitterAngleA")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::EmitterAngleA"]
|
||||
.SetFunctionName("GetEmitterAngleA")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::EmitterAngleB"]
|
||||
.SetFunctionName("SetEmitterAngleB")
|
||||
.SetGetter("GetEmitterAngleB")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::EmitterAngleB"]
|
||||
.SetFunctionName("GetEmitterAngleB")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ConeSprayAngle"]
|
||||
.SetFunctionName("SetConeSprayAngle")
|
||||
.SetGetter("GetConeSprayAngle")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ConeSprayAngle"]
|
||||
.SetFunctionName("GetConeSprayAngle")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::Friction"]
|
||||
.SetFunctionName("SetFriction")
|
||||
.SetGetter("GetFriction")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::Friction"]
|
||||
.SetFunctionName("GetFriction")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ZoneRadius"]
|
||||
.SetFunctionName("SetZoneRadius")
|
||||
.SetGetter("GetZoneRadius")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ZoneRadius"]
|
||||
.SetFunctionName("GetZoneRadius")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleLifeTimeMin"]
|
||||
.SetFunctionName("SetParticleLifeTimeMin")
|
||||
.SetGetter("GetParticleLifeTimeMin")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleLifeTimeMin"]
|
||||
.SetFunctionName("GetParticleLifeTimeMin")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleLifeTimeMax"]
|
||||
.SetFunctionName("SetParticleLifeTimeMax")
|
||||
.SetGetter("GetParticleLifeTimeMax")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleLifeTimeMax"]
|
||||
.SetFunctionName("GetParticleLifeTimeMax")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleGravityX"]
|
||||
.SetFunctionName("SetParticleGravityX")
|
||||
.SetGetter("GetParticleGravityX")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleGravityX"]
|
||||
.SetFunctionName("GetParticleGravityX")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleGravityY"]
|
||||
.SetFunctionName("SetParticleGravityY")
|
||||
.SetGetter("GetParticleGravityY")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleGravityY"]
|
||||
.SetFunctionName("GetParticleGravityY")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleGravityZ"]
|
||||
.SetFunctionName("SetParticleGravityZ")
|
||||
.SetGetter("GetParticleGravityZ")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleGravityZ"]
|
||||
.SetFunctionName("GetParticleGravityZ")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleGravityAngle"]
|
||||
.SetFunctionName("SetParticleGravityAngle")
|
||||
.SetGetter("GetParticleGravityAngle")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleGravityAngle"]
|
||||
.SetFunctionName("GetParticleGravityAngle")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleGravityLength"]
|
||||
.SetFunctionName("SetParticleGravityLength")
|
||||
.SetGetter("GetParticleGravityLength")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleGravityLength"]
|
||||
.SetFunctionName("GetParticleGravityLength")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
|
||||
actions["ParticleSystem::ParticleColor1"]
|
||||
.SetFunctionName("SetParticleColor1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleColor2"]
|
||||
.SetFunctionName("SetParticleColor2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleRed1"]
|
||||
.SetFunctionName("SetParticleRed1")
|
||||
.SetGetter("GetParticleRed1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleRed1"]
|
||||
.SetFunctionName("GetParticleRed1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleRed2"]
|
||||
.SetFunctionName("SetParticleRed2")
|
||||
.SetGetter("GetParticleRed2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleRed2"]
|
||||
.SetFunctionName("GetParticleRed2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleBlue1"]
|
||||
.SetFunctionName("SetParticleBlue1")
|
||||
.SetGetter("GetParticleBlue1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleBlue1"]
|
||||
.SetFunctionName("GetParticleBlue1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleBlue2"]
|
||||
.SetFunctionName("SetParticleBlue2")
|
||||
.SetGetter("GetParticleBlue2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleBlue2"]
|
||||
.SetFunctionName("GetParticleBlue2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleGreen1"]
|
||||
.SetFunctionName("SetParticleGreen1")
|
||||
.SetGetter("GetParticleGreen1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleGreen1"]
|
||||
.SetFunctionName("GetParticleGreen1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleGreen2"]
|
||||
.SetFunctionName("SetParticleGreen2")
|
||||
.SetGetter("GetParticleGreen2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleGreen2"]
|
||||
.SetFunctionName("GetParticleGreen2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleSize1"]
|
||||
.SetFunctionName("SetParticleSize1")
|
||||
.SetGetter("GetParticleSize1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleSize1"]
|
||||
.SetFunctionName("GetParticleSize1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleSize2"]
|
||||
.SetFunctionName("SetParticleSize2")
|
||||
.SetGetter("GetParticleSize2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleSize2"]
|
||||
.SetFunctionName("GetParticleSize2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleAngle1"]
|
||||
.SetFunctionName("SetParticleAngle1")
|
||||
.SetGetter("GetParticleAngle1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleAngle1"]
|
||||
.SetFunctionName("GetParticleAngle1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleAngle2"]
|
||||
.SetFunctionName("SetParticleAngle2")
|
||||
.SetGetter("GetParticleAngle2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleAngle2"]
|
||||
.SetFunctionName("GetParticleAngle2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleAlpha1"]
|
||||
.SetFunctionName("SetParticleAlpha1")
|
||||
.SetGetter("GetParticleAlpha1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleAlpha1"]
|
||||
.SetFunctionName("GetParticleAlpha1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::ParticleAlpha2"]
|
||||
.SetFunctionName("SetParticleAlpha2")
|
||||
.SetGetter("GetParticleAlpha2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::ParticleAlpha2"]
|
||||
.SetFunctionName("GetParticleAlpha2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::NoMoreParticles"]
|
||||
.SetFunctionName("NoMoreParticles")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
|
||||
actions["ParticleSystem::RecreateParticleSystem"]
|
||||
.SetFunctionName("RecreateParticleSystem")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::RendererParam1"]
|
||||
.SetFunctionName("SetRendererParam1")
|
||||
.SetGetter("GetRendererParam1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::RendererParam1"]
|
||||
.SetFunctionName("GetRendererParam1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::RendererParam2"]
|
||||
.SetFunctionName("SetRendererParam2")
|
||||
.SetGetter("GetRendererParam2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::RendererParam2"]
|
||||
.SetFunctionName("GetRendererParam2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::Tank"]
|
||||
.SetFunctionName("SetTank")
|
||||
.SetGetter("GetTank")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::Tank"].SetFunctionName("GetTank").SetIncludeFile(
|
||||
"ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::Flow"]
|
||||
.SetFunctionName("SetFlow")
|
||||
.SetGetter("GetFlow")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::Flow"].SetFunctionName("GetFlow").SetIncludeFile(
|
||||
"ParticleSystem/ParticleEmitterObject.h");
|
||||
actions["ParticleSystem::Texture"]
|
||||
.SetFunctionName("SetTexture")
|
||||
.SetGetter("GetTexture")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
conditions["ParticleSystem::Texture"]
|
||||
.SetFunctionName("GetTexture")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
|
||||
strExpressions["Texture"]
|
||||
.SetFunctionName("GetTexture")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["NbParticles"]
|
||||
.SetFunctionName("GetNbParticles")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["RendererParam1"]
|
||||
.SetFunctionName("GetRendererParam1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["RendererParam2"]
|
||||
.SetFunctionName("GetRendererParam2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["Tank"].SetFunctionName("GetTank").SetIncludeFile(
|
||||
"ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["Flow"].SetFunctionName("GetFlow").SetIncludeFile(
|
||||
"ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["EmitterForceMin"]
|
||||
.SetFunctionName("GetEmitterForceMin")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["EmitterForceMax"]
|
||||
.SetFunctionName("GetEmitterForceMax")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["EmitterXDirection"]
|
||||
.SetFunctionName("GetEmitterXDirection")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["EmitterYDirection"]
|
||||
.SetFunctionName("GetEmitterYDirection")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["EmitterZDirection"]
|
||||
.SetFunctionName("GetEmitterZDirection")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["EmitterAngle"]
|
||||
.SetFunctionName("GetAngle")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["EmitterAngleA"]
|
||||
.SetFunctionName("GetEmitterAngleA")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["EmitterAngleB"]
|
||||
.SetFunctionName("GetEmitterAngleB")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ZoneRadius"]
|
||||
.SetFunctionName("GetZoneRadius")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleGravityX"]
|
||||
.SetFunctionName("GetParticleGravityX")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleGravityY"]
|
||||
.SetFunctionName("GetParticleGravityY")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleGravityZ"]
|
||||
.SetFunctionName("GetParticleGravityZ")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleGravityAngle"]
|
||||
.SetFunctionName("GetParticleGravityAngle")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleGravityLength"]
|
||||
.SetFunctionName("GetParticleGravityLength")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["Friction"]
|
||||
.SetFunctionName("GetFriction")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleLifeTimeMin"]
|
||||
.SetFunctionName("GetParticleLifeTimeMin")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleLifeTimeMax"]
|
||||
.SetFunctionName("GetParticleLifeTimeMax")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleRed1"]
|
||||
.SetFunctionName("GetParticleRed1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleRed2"]
|
||||
.SetFunctionName("GetParticleRed2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleBlue1"]
|
||||
.SetFunctionName("GetParticleBlue1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleBlue2"]
|
||||
.SetFunctionName("GetParticleBlue2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleGreen1"]
|
||||
.SetFunctionName("GetParticleGreen1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleGreen2"]
|
||||
.SetFunctionName("GetParticleGreen2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleAlpha1"]
|
||||
.SetFunctionName("GetParticleAlpha1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleAlpha2"]
|
||||
.SetFunctionName("GetParticleAlpha2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleSize1"]
|
||||
.SetFunctionName("GetParticleSize1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleSize2"]
|
||||
.SetFunctionName("GetParticleSize2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleAngle1"]
|
||||
.SetFunctionName("GetParticleAngle1")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
expressions["ParticleAngle2"]
|
||||
.SetFunctionName("GetParticleAngle2")
|
||||
.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
|
||||
|
||||
StripUnimplementedInstructionsAndExpressions();
|
||||
#endif
|
||||
|
||||
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
|
||||
};
|
||||
|
||||
/**
|
||||
* Used by GDevelop to create the extension class
|
||||
* -- Do not need to be modified. --
|
||||
*/
|
||||
extern "C" ExtensionBase* GD_EXTENSION_API CreateGDExtension() {
|
||||
return new ParticleSystemCppExtension;
|
||||
}
|
||||
}
|
@@ -7,23 +7,13 @@ This project is released under the MIT License.
|
||||
|
||||
#ifndef EXTENSION_H_INCLUDED
|
||||
#define EXTENSION_H_INCLUDED
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
namespace gd {
|
||||
class ObjectMetadata;
|
||||
}
|
||||
namespace gd {
|
||||
class PlatformExtension;
|
||||
}
|
||||
|
||||
void DeclareParticleSystemExtension(gd::PlatformExtension& extension);
|
||||
|
||||
/**
|
||||
* \brief This class declares information about the extension.
|
||||
*/
|
||||
class ParticleSystemCppExtension : public ExtensionBase {
|
||||
public:
|
||||
ParticleSystemCppExtension();
|
||||
virtual ~ParticleSystemCppExtension(){};
|
||||
};
|
||||
|
||||
#endif // EXTENSION_H_INCLUDED
|
||||
|
@@ -5,7 +5,8 @@ Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
#include "Extension.h"
|
||||
#include "ParticleEmitterObject.h"
|
||||
|
@@ -5,7 +5,8 @@ Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
#include "Extension.h"
|
||||
#include "ParticleEmitterObject.h"
|
||||
|
@@ -5,7 +5,8 @@ Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "GDCpp/Extensions/ExtensionBase.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
#include "Extension.h"
|
||||
#include "ParticleEmitterObject.h"
|
||||
|
@@ -6,6 +6,7 @@ This project is released under the MIT License.
|
||||
*/
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "ParticleEmitterObject.h"
|
||||
|
||||
void DeclareParticleSystemExtension(gd::PlatformExtension& extension);
|
||||
|
@@ -5,32 +5,19 @@ Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/OpenGL.hpp>
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCpp/Runtime/CommonTools.h"
|
||||
#include "GDCpp/Runtime/FontManager.h"
|
||||
#include "GDCpp/Runtime/ImageManager.h"
|
||||
#include "GDCpp/Runtime/Polygon2d.h"
|
||||
#include "GDCpp/Runtime/Project/InitialInstance.h"
|
||||
#include "GDCpp/Runtime/Project/Object.h"
|
||||
#include "GDCpp/Runtime/Project/Project.h"
|
||||
#include "GDCpp/Runtime/RuntimeGame.h"
|
||||
#include "GDCpp/Runtime/RuntimeScene.h"
|
||||
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Project/InitialInstance.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "ParticleEmitterObject.h"
|
||||
#include "ParticleSystemWrapper.h"
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCpp/Runtime/CommonTools.h"
|
||||
#include "GDCore/CommonTools.h"
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
#include <SPK.h>
|
||||
#include <SPK_GL.h>
|
||||
// clang-format on
|
||||
|
||||
using namespace std;
|
||||
|
||||
ParticleEmitterBase::ParticleEmitterBase()
|
||||
@@ -79,8 +66,7 @@ ParticleEmitterBase::ParticleEmitterBase()
|
||||
particleAngleRandomness1(0),
|
||||
particleAngleRandomness2(0),
|
||||
maxParticleNb(300),
|
||||
destroyWhenNoParticles(true),
|
||||
particleSystem(NULL) {}
|
||||
destroyWhenNoParticles(true) {}
|
||||
|
||||
ParticleEmitterObject::ParticleEmitterObject(gd::String name_)
|
||||
: Object(name_)
|
||||
@@ -326,294 +312,7 @@ void ParticleEmitterBase::SerializeParticleEmitterBaseTo(
|
||||
}
|
||||
#endif
|
||||
|
||||
void ParticleEmitterBase::CreateParticleSystem() {
|
||||
if (particleSystem) delete particleSystem;
|
||||
particleSystem = new ParticleSystemWrapper;
|
||||
|
||||
int enabledFlag = 0;
|
||||
int mutableFlag = 0;
|
||||
int randomFlag = 0;
|
||||
|
||||
if (redParam == Enabled)
|
||||
enabledFlag |= SPK::FLAG_RED;
|
||||
else if (redParam == Mutable) {
|
||||
enabledFlag |= SPK::FLAG_RED;
|
||||
mutableFlag |= SPK::FLAG_RED;
|
||||
} else if (redParam == Random) {
|
||||
enabledFlag |= SPK::FLAG_RED;
|
||||
randomFlag |= SPK::FLAG_RED;
|
||||
}
|
||||
|
||||
if (greenParam == Enabled)
|
||||
enabledFlag |= SPK::FLAG_RED;
|
||||
else if (greenParam == Mutable) {
|
||||
enabledFlag |= SPK::FLAG_GREEN;
|
||||
mutableFlag |= SPK::FLAG_GREEN;
|
||||
} else if (greenParam == Random) {
|
||||
enabledFlag |= SPK::FLAG_GREEN;
|
||||
randomFlag |= SPK::FLAG_GREEN;
|
||||
}
|
||||
|
||||
if (blueParam == Enabled)
|
||||
enabledFlag |= SPK::FLAG_BLUE;
|
||||
else if (blueParam == Mutable) {
|
||||
enabledFlag |= SPK::FLAG_BLUE;
|
||||
mutableFlag |= SPK::FLAG_BLUE;
|
||||
} else if (blueParam == Random) {
|
||||
enabledFlag |= SPK::FLAG_BLUE;
|
||||
randomFlag |= SPK::FLAG_BLUE;
|
||||
}
|
||||
|
||||
if (alphaParam == Enabled)
|
||||
enabledFlag |= SPK::FLAG_ALPHA;
|
||||
else if (alphaParam == Mutable) {
|
||||
enabledFlag |= SPK::FLAG_ALPHA;
|
||||
randomFlag |= SPK::FLAG_ALPHA;
|
||||
mutableFlag |= SPK::FLAG_ALPHA;
|
||||
} else if (alphaParam == Random) {
|
||||
enabledFlag |= SPK::FLAG_ALPHA;
|
||||
randomFlag |= SPK::FLAG_ALPHA;
|
||||
}
|
||||
|
||||
if (sizeParam == Mutable) {
|
||||
enabledFlag |= SPK::FLAG_SIZE;
|
||||
randomFlag |= SPK::FLAG_SIZE;
|
||||
mutableFlag |= SPK::FLAG_SIZE;
|
||||
} else if (sizeParam == Random) {
|
||||
enabledFlag |= SPK::FLAG_SIZE;
|
||||
randomFlag |= SPK::FLAG_SIZE;
|
||||
}
|
||||
|
||||
if (angleParam == Mutable) {
|
||||
enabledFlag |= SPK::FLAG_ANGLE;
|
||||
randomFlag |= SPK::FLAG_ANGLE;
|
||||
mutableFlag |= SPK::FLAG_ANGLE;
|
||||
} else if (angleParam == Random) {
|
||||
enabledFlag |= SPK::FLAG_ANGLE;
|
||||
randomFlag |= SPK::FLAG_ANGLE;
|
||||
}
|
||||
|
||||
if (rendererType == Quad) enabledFlag |= SPK::PARAM_TEXTURE_INDEX;
|
||||
|
||||
// Create the model
|
||||
particleSystem->particleModel =
|
||||
SPK::Model::create(enabledFlag, mutableFlag, randomFlag);
|
||||
UpdateRedParameters();
|
||||
UpdateGreenParameters();
|
||||
UpdateBlueParameters();
|
||||
UpdateAlphaParameters();
|
||||
UpdateSizeParameters();
|
||||
UpdateAngleParameters();
|
||||
UpdateLifeTime();
|
||||
|
||||
// Create the renderer
|
||||
if (rendererType == Line)
|
||||
particleSystem->renderer =
|
||||
SPK::GL::GLLineRenderer::create(rendererParam1, rendererParam2);
|
||||
else if (rendererType == Quad) {
|
||||
SPK::GL::GLQuadRenderer* quadRenderer =
|
||||
new SPK::GL::GLQuadRenderer(rendererParam1, rendererParam2);
|
||||
|
||||
if (particleSystem->textureParticle) {
|
||||
quadRenderer->setTexturingMode(SPK::TEXTURE_2D);
|
||||
quadRenderer->setTexture(
|
||||
particleSystem->textureParticle->texture.getNativeHandle());
|
||||
}
|
||||
|
||||
particleSystem->renderer = quadRenderer;
|
||||
} else {
|
||||
SPK::GL::GLPointRenderer* pointRenderer =
|
||||
SPK::GL::GLPointRenderer::create();
|
||||
pointRenderer->setType(SPK::POINT_CIRCLE);
|
||||
pointRenderer->setSize(rendererParam1);
|
||||
|
||||
particleSystem->renderer = pointRenderer;
|
||||
}
|
||||
|
||||
particleSystem->renderer->enableBlending(true);
|
||||
if (additive)
|
||||
particleSystem->renderer->setBlendingFunctions(GL_SRC_ALPHA, GL_ONE);
|
||||
else
|
||||
particleSystem->renderer->setBlendingFunctions(GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA);
|
||||
particleSystem->renderer->setTextureBlending(
|
||||
GL_MODULATE); // Texture color modulated with particle color
|
||||
particleSystem->renderer->enableRenderingHint(
|
||||
SPK::DEPTH_TEST, false); // No depth test for performance
|
||||
|
||||
// Create the zone
|
||||
particleSystem->zone = SPK::Sphere::create(SPK::Vector3D(0, 0), zoneRadius);
|
||||
|
||||
// Create the emitter
|
||||
particleSystem->emitter = SPK::SphericEmitter::create(
|
||||
SPK::Vector3D(emitterXDirection, -emitterYDirection, emitterZDirection),
|
||||
emitterAngleA / 180.0f * 3.14159f,
|
||||
emitterAngleB / 180.0f * 3.14159f);
|
||||
particleSystem->emitter->setForce(emitterForceMin, emitterForceMax);
|
||||
particleSystem->emitter->setZone(particleSystem->zone);
|
||||
particleSystem->emitter->setTank(tank);
|
||||
particleSystem->emitter->setFlow(flow);
|
||||
|
||||
// Create the Group
|
||||
particleSystem->group =
|
||||
SPK::Group::create(particleSystem->particleModel, maxParticleNb);
|
||||
particleSystem->group->addEmitter(particleSystem->emitter);
|
||||
particleSystem->group->setGravity(
|
||||
SPK::Vector3D(particleGravityX, -particleGravityY, particleGravityZ));
|
||||
particleSystem->group->setFriction(friction);
|
||||
particleSystem->group->setRenderer(particleSystem->renderer);
|
||||
|
||||
// Create the System
|
||||
particleSystem->particleSystem = SPK::System::create();
|
||||
particleSystem->particleSystem->addGroup(particleSystem->group);
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::UpdateRedParameters() {
|
||||
if (!particleSystem || !particleSystem->particleModel) return;
|
||||
|
||||
if (redParam == Mutable || redParam == Random)
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_RED, particleRed1 / 255.0f, particleRed2 / 255.0f);
|
||||
else
|
||||
particleSystem->particleModel->setParam(SPK::PARAM_RED,
|
||||
particleRed1 / 255.0f);
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::UpdateGreenParameters() {
|
||||
if (!particleSystem || !particleSystem->particleModel) return;
|
||||
|
||||
if (greenParam == Mutable || greenParam == Random)
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_GREEN, particleGreen1 / 255.0f, particleGreen2 / 255.0f);
|
||||
else
|
||||
particleSystem->particleModel->setParam(SPK::PARAM_GREEN,
|
||||
particleGreen1 / 255.0f);
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::UpdateBlueParameters() {
|
||||
if (!particleSystem || !particleSystem->particleModel) return;
|
||||
|
||||
if (blueParam == Mutable || blueParam == Random)
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_BLUE, particleBlue1 / 255.0f, particleBlue2 / 255.0f);
|
||||
else
|
||||
particleSystem->particleModel->setParam(SPK::PARAM_BLUE,
|
||||
particleBlue1 / 255.0f);
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::UpdateAlphaParameters() {
|
||||
if (!particleSystem || !particleSystem->particleModel) return;
|
||||
|
||||
if (alphaParam == Mutable)
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_ALPHA,
|
||||
(particleAlpha1 - particleAlphaRandomness1 / 2.0f) / 255.0f,
|
||||
(particleAlpha1 + particleAlphaRandomness1 / 2.0f) / 255.0f,
|
||||
(particleAlpha2 - particleAlphaRandomness2 / 2.0f) / 255.0f,
|
||||
(particleAlpha2 + particleAlphaRandomness2 / 2.0f) / 255.0f);
|
||||
else if (alphaParam == Random)
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_ALPHA, (particleAlpha1) / 255.0f, (particleAlpha2) / 255.0f);
|
||||
else
|
||||
particleSystem->particleModel->setParam(SPK::PARAM_ALPHA,
|
||||
particleAlpha1 / 255.0f);
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::UpdateSizeParameters() {
|
||||
if (!particleSystem || !particleSystem->particleModel) return;
|
||||
|
||||
if (sizeParam == Mutable)
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_SIZE,
|
||||
(particleSize1 - particleSizeRandomness1 / 2.0f) / 100.0f,
|
||||
(particleSize1 + particleSizeRandomness1 / 2.0f) / 100.0f,
|
||||
(particleSize2 - particleSizeRandomness2 / 2.0f) / 100.0f,
|
||||
(particleSize2 + particleSizeRandomness2 / 2.0f) / 100.0f);
|
||||
else if (sizeParam == Random)
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_SIZE, (particleSize1) / 100.0f, (particleSize2) / 100.0f);
|
||||
else
|
||||
particleSystem->particleModel->setParam(SPK::PARAM_SIZE,
|
||||
particleSize1 / 100.0f);
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::UpdateAngleParameters() {
|
||||
if (!particleSystem || !particleSystem->particleModel) return;
|
||||
|
||||
if (angleParam == Mutable)
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_ANGLE,
|
||||
-(particleAngle1 - particleAngleRandomness1 / 2.0f) / 180.0f * 3.14159f,
|
||||
-(particleAngle1 + particleAngleRandomness1 / 2.0f) / 180.0f * 3.14159f,
|
||||
-(particleAngle2 - particleAngleRandomness2 / 2.0f) / 180.0f * 3.14159f,
|
||||
-(particleAngle2 + particleAngleRandomness2 / 2.0f) / 180.0f *
|
||||
3.14159f);
|
||||
else if (angleParam == Random)
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_ANGLE,
|
||||
-(particleAngle1) / 180.0f * 3.14159f,
|
||||
-(particleAngle2) / 180.0f * 3.14159f);
|
||||
else
|
||||
particleSystem->particleModel->setParam(
|
||||
SPK::PARAM_ANGLE, -particleAngle1 / 180.0f * 3.14159f);
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::UpdateLifeTime() {
|
||||
if (!particleSystem || !particleSystem->particleModel) return;
|
||||
|
||||
particleSystem->particleModel->setLifeTime(particleLifeTimeMin,
|
||||
particleLifeTimeMax);
|
||||
}
|
||||
|
||||
RuntimeParticleEmitterObject::RuntimeParticleEmitterObject(
|
||||
RuntimeScene& scene, const ParticleEmitterObject& particleEmitterObject)
|
||||
: RuntimeObject(scene, particleEmitterObject), hasSomeParticles(true) {
|
||||
ParticleEmitterBase::operator=(particleEmitterObject);
|
||||
|
||||
CreateParticleSystem();
|
||||
SetTexture(scene, GetParticleTexture());
|
||||
|
||||
OnPositionChanged();
|
||||
}
|
||||
|
||||
ParticleEmitterBase::~ParticleEmitterBase() {
|
||||
if (particleSystem) delete particleSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render object at runtime
|
||||
*/
|
||||
bool RuntimeParticleEmitterObject::Draw(sf::RenderTarget& renderTarget) {
|
||||
// Don't draw anything if hidden
|
||||
if (hidden) return true;
|
||||
|
||||
renderTarget.popGLStates();
|
||||
|
||||
float xView = renderTarget.getView().getCenter().x * 0.25f;
|
||||
float yView = -renderTarget.getView().getCenter().y * 0.25f;
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glRotatef(renderTarget.getView().getRotation(), 0, 0, 1);
|
||||
glTranslatef(
|
||||
-xView, -yView, -75.0f * (renderTarget.getView().getSize().y / 600.0f));
|
||||
|
||||
SPK::GL::GLRenderer::saveGLStates();
|
||||
|
||||
GetParticleSystem()->particleSystem->render();
|
||||
SPK::GL::GLRenderer::restoreGLStates();
|
||||
|
||||
renderTarget.pushGLStates();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeParticleEmitterObject::OnPositionChanged() {
|
||||
if (GetParticleSystem() && GetParticleSystem()->zone)
|
||||
GetParticleSystem()->zone->setPosition(
|
||||
SPK::Vector3D(GetX() * 0.25f, -GetY() * 0.25f, 0));
|
||||
}
|
||||
ParticleEmitterBase::~ParticleEmitterBase() {}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void ParticleEmitterObject::ExposeResources(
|
||||
@@ -622,120 +321,49 @@ void ParticleEmitterObject::ExposeResources(
|
||||
worker.ExposeImage(texture);
|
||||
SetParticleTexture(texture);
|
||||
}
|
||||
|
||||
void RuntimeParticleEmitterObject::GetPropertyForDebugger(
|
||||
std::size_t propertyNb, gd::String& name, gd::String& value) const {
|
||||
if (!GetParticleSystem() || !GetParticleSystem()->particleSystem) return;
|
||||
|
||||
if (propertyNb == 0) {
|
||||
name = _("Particles number");
|
||||
value =
|
||||
gd::String::From(GetParticleSystem()->particleSystem->getNbParticles());
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimeParticleEmitterObject::ChangeProperty(std::size_t propertyNb,
|
||||
gd::String newValue) {
|
||||
if (propertyNb == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t RuntimeParticleEmitterObject::GetNumberOfProperties() const {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ParticleEmitterBase::SetTank(float newValue) {
|
||||
tank = newValue;
|
||||
if (particleSystem && particleSystem->emitter)
|
||||
particleSystem->emitter->setFlow(tank);
|
||||
}
|
||||
void ParticleEmitterBase::SetFlow(float newValue) {
|
||||
flow = newValue;
|
||||
if (particleSystem && particleSystem->emitter)
|
||||
particleSystem->emitter->setFlow(flow);
|
||||
}
|
||||
void ParticleEmitterBase::SetEmitterForceMin(float newValue) {
|
||||
emitterForceMin = newValue;
|
||||
if (particleSystem && particleSystem->emitter)
|
||||
particleSystem->emitter->setForce(emitterForceMin, emitterForceMax);
|
||||
}
|
||||
void ParticleEmitterBase::SetEmitterForceMax(float newValue) {
|
||||
emitterForceMax = newValue;
|
||||
if (particleSystem && particleSystem->emitter)
|
||||
particleSystem->emitter->setForce(emitterForceMin, emitterForceMax);
|
||||
}
|
||||
void ParticleEmitterBase::SetParticleGravityX(float newValue) {
|
||||
particleGravityX = newValue;
|
||||
if (particleSystem && particleSystem->group)
|
||||
particleSystem->group->setGravity(
|
||||
SPK::Vector3D(particleGravityX, -particleGravityY, particleGravityZ));
|
||||
}
|
||||
void ParticleEmitterBase::SetParticleGravityY(float newValue) {
|
||||
particleGravityY = newValue;
|
||||
if (particleSystem && particleSystem->group)
|
||||
particleSystem->group->setGravity(
|
||||
SPK::Vector3D(particleGravityX, -particleGravityY, particleGravityZ));
|
||||
}
|
||||
void ParticleEmitterBase::SetParticleGravityZ(float newValue) {
|
||||
particleGravityZ = newValue;
|
||||
if (particleSystem && particleSystem->group)
|
||||
particleSystem->group->setGravity(
|
||||
SPK::Vector3D(particleGravityX, -particleGravityY, particleGravityZ));
|
||||
}
|
||||
void ParticleEmitterBase::SetFriction(float newValue) {
|
||||
friction = newValue;
|
||||
if (particleSystem && particleSystem->group)
|
||||
particleSystem->group->setFriction(friction);
|
||||
}
|
||||
void ParticleEmitterBase::SetEmitterXDirection(float newValue) {
|
||||
emitterXDirection = newValue;
|
||||
if (particleSystem && particleSystem->emitter)
|
||||
particleSystem->emitter->setDirection(SPK::Vector3D(
|
||||
emitterXDirection, -emitterYDirection, emitterZDirection));
|
||||
}
|
||||
void ParticleEmitterBase::SetEmitterYDirection(float newValue) {
|
||||
emitterYDirection = newValue;
|
||||
if (particleSystem && particleSystem->emitter)
|
||||
particleSystem->emitter->setDirection(SPK::Vector3D(
|
||||
emitterXDirection, -emitterYDirection, emitterZDirection));
|
||||
}
|
||||
void ParticleEmitterBase::SetEmitterZDirection(float newValue) {
|
||||
emitterZDirection = newValue;
|
||||
if (particleSystem && particleSystem->emitter)
|
||||
particleSystem->emitter->setDirection(SPK::Vector3D(
|
||||
emitterXDirection, -emitterYDirection, emitterZDirection));
|
||||
}
|
||||
void ParticleEmitterBase::SetEmitterAngleA(float newValue) {
|
||||
emitterAngleA = newValue;
|
||||
if (particleSystem && particleSystem->emitter)
|
||||
particleSystem->emitter->setAngles(emitterAngleA / 180.0f * 3.14159f,
|
||||
emitterAngleB / 180.0f * 3.14159f);
|
||||
}
|
||||
void ParticleEmitterBase::SetEmitterAngleB(float newValue) {
|
||||
emitterAngleB = newValue;
|
||||
if (particleSystem && particleSystem->emitter)
|
||||
particleSystem->emitter->setAngles(emitterAngleA / 180.0f * 3.14159f,
|
||||
emitterAngleB / 180.0f * 3.14159f);
|
||||
}
|
||||
void ParticleEmitterBase::SetZoneRadius(float newValue) {
|
||||
zoneRadius = newValue;
|
||||
if (particleSystem && particleSystem->zone)
|
||||
particleSystem->zone->setRadius(zoneRadius);
|
||||
}
|
||||
|
||||
void RuntimeParticleEmitterObject::Update(const RuntimeScene& scene) {
|
||||
double elapsedTimeInSeconds =
|
||||
static_cast<double>(GetElapsedTime(scene)) / 1000000.0;
|
||||
if (GetParticleSystem())
|
||||
hasSomeParticles =
|
||||
GetParticleSystem()->particleSystem->update(elapsedTimeInSeconds);
|
||||
|
||||
if (GetDestroyWhenNoParticles() && !hasSomeParticles)
|
||||
DeleteFromScene(const_cast<RuntimeScene&>(scene)); // Ugly const cast
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::SetParticleGravityAngle(float newAngleInDegree) {
|
||||
@@ -761,18 +389,6 @@ float ParticleEmitterBase::GetParticleGravityLength() const {
|
||||
GetParticleGravityX() * GetParticleGravityX());
|
||||
}
|
||||
|
||||
bool RuntimeParticleEmitterObject::SetAngle(float newAngleInDegrees) {
|
||||
SetEmitterXDirection(cos(newAngleInDegrees / 180.0f * 3.14159f));
|
||||
SetEmitterYDirection(sin(newAngleInDegrees / 180.0f * 3.14159f));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float RuntimeParticleEmitterObject::GetAngle() const {
|
||||
return atan2f(GetEmitterYDirection(), GetEmitterXDirection()) * 180.0f /
|
||||
3.14159f;
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::SetParticleColor1(const gd::String& color) {
|
||||
std::vector<gd::String> colors = color.Split(U';');
|
||||
|
||||
@@ -782,6 +398,7 @@ void ParticleEmitterBase::SetParticleColor1(const gd::String& color) {
|
||||
SetParticleGreen1(colors[1].To<int>());
|
||||
SetParticleBlue1(colors[2].To<int>());
|
||||
}
|
||||
|
||||
void ParticleEmitterBase::SetParticleColor2(const gd::String& color) {
|
||||
std::vector<gd::String> colors = color.Split(U';');
|
||||
|
||||
@@ -792,40 +409,12 @@ void ParticleEmitterBase::SetParticleColor2(const gd::String& color) {
|
||||
SetParticleBlue2(colors[2].To<int>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the texture
|
||||
*/
|
||||
void ParticleEmitterBase::SetTexture(RuntimeScene& scene,
|
||||
const gd::String& textureParticleName_) {
|
||||
textureParticleName = textureParticleName_;
|
||||
if (particleSystem && rendererType == Quad) {
|
||||
// Load new texture
|
||||
particleSystem->textureParticle =
|
||||
scene.GetImageManager()->GetSFMLTexture(textureParticleName);
|
||||
|
||||
// Notify the renderer of the change
|
||||
SPK::GL::GLQuadRenderer* quadRenderer =
|
||||
dynamic_cast<SPK::GL::GLQuadRenderer*>(particleSystem->renderer);
|
||||
|
||||
if (quadRenderer) {
|
||||
quadRenderer->setTexturingMode(SPK::TEXTURE_2D);
|
||||
quadRenderer->setTexture(
|
||||
particleSystem->textureParticle->texture.getNativeHandle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by copy constructor and assignment operator.
|
||||
* \warning Do not forget to update me if members were changed!
|
||||
*/
|
||||
void ParticleEmitterBase::Init(const ParticleEmitterBase& other) {
|
||||
if (particleSystem) delete particleSystem;
|
||||
if (other.particleSystem)
|
||||
particleSystem = new ParticleSystemWrapper(*other.particleSystem);
|
||||
else
|
||||
particleSystem = NULL;
|
||||
|
||||
// TODO: might be useless to redefine the copy ctor/assignment operator.
|
||||
textureParticleName = other.textureParticleName;
|
||||
rendererType = other.rendererType;
|
||||
rendererParam1 = other.rendererParam1;
|
||||
|
@@ -8,19 +8,11 @@ This project is released under the MIT License.
|
||||
#ifndef PARTICLEEMITTEROBJECT_H
|
||||
#define PARTICLEEMITTEROBJECT_H
|
||||
|
||||
#include "GDCpp/Runtime/Project/Object.h"
|
||||
#include "GDCpp/Runtime/RuntimeObject.h"
|
||||
class ParticleSystemWrapper;
|
||||
class RuntimeScene;
|
||||
#include "GDCore/Project/Object.h"
|
||||
namespace gd {
|
||||
class ImageManager;
|
||||
class InitialInstance;
|
||||
}
|
||||
#if defined(GD_IDE_ONLY)
|
||||
namespace gd {
|
||||
class Project;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Base class containing the parameters of an emitter as well as the
|
||||
@@ -30,7 +22,7 @@ class GD_EXTENSION_API ParticleEmitterBase {
|
||||
public:
|
||||
ParticleEmitterBase();
|
||||
virtual ~ParticleEmitterBase();
|
||||
ParticleEmitterBase(const ParticleEmitterBase& other) : particleSystem(NULL) {
|
||||
ParticleEmitterBase(const ParticleEmitterBase& other) {
|
||||
Init(other);
|
||||
};
|
||||
ParticleEmitterBase& operator=(const ParticleEmitterBase& other) {
|
||||
@@ -38,36 +30,11 @@ class GD_EXTENSION_API ParticleEmitterBase {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Change texture at runtime
|
||||
*/
|
||||
void SetTexture(RuntimeScene& scene, const gd::String& textureParticleName);
|
||||
|
||||
/** Change texture name without changing it effectively at runtime
|
||||
*/
|
||||
void SetParticleTexture(const gd::String & imageName) {
|
||||
textureParticleName = imageName;
|
||||
};
|
||||
const gd::String & GetParticleTexture() const { return textureParticleName; };
|
||||
|
||||
/**
|
||||
* \brief Initialize the particle system with the current objects settings.
|
||||
*/
|
||||
void CreateParticleSystem();
|
||||
|
||||
void UpdateRedParameters();
|
||||
void UpdateGreenParameters();
|
||||
void UpdateBlueParameters();
|
||||
void UpdateAlphaParameters();
|
||||
void UpdateSizeParameters();
|
||||
void UpdateAngleParameters();
|
||||
void UpdateLifeTime();
|
||||
void RecreateParticleSystem();
|
||||
const ParticleSystemWrapper* GetParticleSystem() const {
|
||||
return particleSystem;
|
||||
}
|
||||
ParticleSystemWrapper* GetParticleSystem() { return particleSystem; }
|
||||
|
||||
// Getters/Setters
|
||||
void SetRendererParam1(float newValue) { rendererParam1 = newValue; };
|
||||
void SetRendererParam2(float newValue) { rendererParam2 = newValue; };
|
||||
void SetTank(float newValue);
|
||||
@@ -101,83 +68,63 @@ class GD_EXTENSION_API ParticleEmitterBase {
|
||||
|
||||
void SetParticleRed1(float newValue) {
|
||||
particleRed1 = newValue;
|
||||
UpdateRedParameters();
|
||||
};
|
||||
void SetParticleRed2(float newValue) {
|
||||
particleRed2 = newValue;
|
||||
UpdateRedParameters();
|
||||
};
|
||||
void SetParticleGreen1(float newValue) {
|
||||
particleGreen1 = newValue;
|
||||
UpdateGreenParameters();
|
||||
};
|
||||
void SetParticleGreen2(float newValue) {
|
||||
particleGreen2 = newValue;
|
||||
UpdateGreenParameters();
|
||||
};
|
||||
void SetParticleBlue1(float newValue) {
|
||||
particleBlue1 = newValue;
|
||||
UpdateBlueParameters();
|
||||
};
|
||||
void SetParticleBlue2(float newValue) {
|
||||
particleBlue2 = newValue;
|
||||
UpdateBlueParameters();
|
||||
};
|
||||
void SetParticleAlpha1(float newValue) {
|
||||
particleAlpha1 = newValue;
|
||||
UpdateAlphaParameters();
|
||||
};
|
||||
void SetParticleAlpha2(float newValue) {
|
||||
particleAlpha2 = newValue;
|
||||
UpdateAlphaParameters();
|
||||
};
|
||||
void SetParticleSize1(float newValue) {
|
||||
particleSize1 = newValue;
|
||||
UpdateSizeParameters();
|
||||
};
|
||||
void SetParticleSize2(float newValue) {
|
||||
particleSize2 = newValue;
|
||||
UpdateSizeParameters();
|
||||
};
|
||||
void SetParticleAngle1(float newValue) {
|
||||
particleAngle1 = newValue;
|
||||
UpdateAngleParameters();
|
||||
};
|
||||
void SetParticleAngle2(float newValue) {
|
||||
particleAngle2 = newValue;
|
||||
UpdateAngleParameters();
|
||||
};
|
||||
void SetParticleAlphaRandomness1(float newValue) {
|
||||
particleAlphaRandomness1 = newValue;
|
||||
UpdateAlphaParameters();
|
||||
};
|
||||
void SetParticleAlphaRandomness2(float newValue) {
|
||||
particleAlphaRandomness2 = newValue;
|
||||
UpdateAlphaParameters();
|
||||
};
|
||||
void SetParticleSizeRandomness1(float newValue) {
|
||||
particleSizeRandomness1 = newValue;
|
||||
UpdateSizeParameters();
|
||||
};
|
||||
void SetParticleSizeRandomness2(float newValue) {
|
||||
particleSizeRandomness2 = newValue;
|
||||
UpdateSizeParameters();
|
||||
};
|
||||
void SetParticleAngleRandomness1(float newValue) {
|
||||
particleAngleRandomness1 = newValue;
|
||||
UpdateAngleParameters();
|
||||
};
|
||||
void SetParticleAngleRandomness2(float newValue) {
|
||||
particleAngleRandomness2 = newValue;
|
||||
UpdateAngleParameters();
|
||||
};
|
||||
void SetParticleLifeTimeMin(float newValue) {
|
||||
particleLifeTimeMin = newValue;
|
||||
UpdateLifeTime();
|
||||
};
|
||||
void SetParticleLifeTimeMax(float newValue) {
|
||||
particleLifeTimeMax = newValue;
|
||||
UpdateLifeTime();
|
||||
};
|
||||
void SetMaxParticleNb(std::size_t newValue) { maxParticleNb = newValue; };
|
||||
void SetDestroyWhenNoParticles(bool enable = true) {
|
||||
@@ -291,11 +238,6 @@ class GD_EXTENSION_API ParticleEmitterBase {
|
||||
bool destroyWhenNoParticles; ///< If set to true, the object will removed
|
||||
///< itself from the scene when it has no more
|
||||
///< particles.
|
||||
|
||||
ParticleSystemWrapper*
|
||||
particleSystem; ///< Pointer to the class wrapping all the real particle
|
||||
///< engine related stuff. This pointer is managed by the
|
||||
///< object.
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -328,54 +270,4 @@ class GD_EXTENSION_API ParticleEmitterObject : public gd::Object,
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Particle Emitter object used by the game engine.
|
||||
*/
|
||||
class GD_EXTENSION_API RuntimeParticleEmitterObject
|
||||
: public RuntimeObject,
|
||||
public ParticleEmitterBase {
|
||||
public:
|
||||
RuntimeParticleEmitterObject(
|
||||
RuntimeScene& scene, const ParticleEmitterObject& particleEmitterObject);
|
||||
virtual ~RuntimeParticleEmitterObject(){};
|
||||
virtual std::unique_ptr<RuntimeObject> Clone() const {
|
||||
return gd::make_unique<RuntimeParticleEmitterObject>(*this);
|
||||
}
|
||||
|
||||
virtual bool Draw(sf::RenderTarget& renderTarget);
|
||||
|
||||
virtual void OnPositionChanged();
|
||||
|
||||
virtual float GetWidth() const { return 32; };
|
||||
virtual float GetHeight() const { return 32; };
|
||||
|
||||
virtual void Update(const RuntimeScene& scene);
|
||||
|
||||
bool NoMoreParticles() const { return !hasSomeParticles; };
|
||||
|
||||
/**
|
||||
* Changing object angle is equivalent to changing emission X/Y direction
|
||||
*/
|
||||
virtual bool SetAngle(float newAngleInDegrees);
|
||||
virtual float GetAngle() const;
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
virtual void GetPropertyForDebugger(std::size_t propertyNb,
|
||||
gd::String& name,
|
||||
gd::String& value) const;
|
||||
virtual bool ChangeProperty(std::size_t propertyNb, gd::String newValue);
|
||||
virtual std::size_t GetNumberOfProperties() const;
|
||||
#endif
|
||||
|
||||
const ParticleSystemWrapper& GetAssociatedParticleSystemWrapper() const {
|
||||
return *GetParticleSystem();
|
||||
};
|
||||
ParticleSystemWrapper& GetAssociatedParticleSystemWrapper() {
|
||||
return *GetParticleSystem();
|
||||
};
|
||||
|
||||
private:
|
||||
bool hasSomeParticles;
|
||||
};
|
||||
|
||||
#endif // PARTICLEEMITTEROBJECT_H
|
||||
|
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - Particle System Extension
|
||||
Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "ParticleSystemWrapper.h"
|
||||
#include <SPK.h>
|
||||
#include <SPK_GL.h>
|
||||
#include <ctime>
|
||||
|
||||
bool ParticleSystemWrapper::SPKinitialized = false;
|
||||
|
||||
ParticleSystemWrapper::ParticleSystemWrapper()
|
||||
: particleSystem(NULL),
|
||||
particleModel(NULL),
|
||||
emitter(NULL),
|
||||
zone(NULL),
|
||||
group(NULL),
|
||||
renderer(NULL) {
|
||||
if (!SPKinitialized) {
|
||||
SPK::randomSeed = static_cast<unsigned int>(time(NULL));
|
||||
SPK::System::setClampStep(true, 0.1f); // clamp the step to 100 ms
|
||||
SPK::System::useAdaptiveStep(
|
||||
0.001f,
|
||||
0.01f); // use an adaptive step from 1ms to 10ms (1000fps to 100fps)
|
||||
|
||||
SPKinitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
ParticleSystemWrapper::~ParticleSystemWrapper() {
|
||||
if (particleSystem) delete particleSystem;
|
||||
if (particleModel) delete particleModel;
|
||||
if (emitter) delete emitter;
|
||||
if (zone) delete zone;
|
||||
if (group) delete group;
|
||||
if (renderer) delete renderer;
|
||||
}
|
||||
|
||||
void ParticleSystemWrapper::Init(const ParticleSystemWrapper& other) {
|
||||
textureParticle = other.textureParticle;
|
||||
if (particleSystem) delete particleSystem;
|
||||
if (particleModel) delete particleModel;
|
||||
if (emitter) delete emitter;
|
||||
if (zone) delete zone;
|
||||
if (group) delete group;
|
||||
if (renderer) delete renderer;
|
||||
|
||||
// Don't initialize members if the other object's member are NULL.
|
||||
if (other.particleModel == NULL) return;
|
||||
|
||||
particleModel = new SPK::Model(*other.particleModel);
|
||||
|
||||
zone = new SPK::Sphere(*other.zone);
|
||||
emitter = new SPK::SphericEmitter(*other.emitter);
|
||||
emitter->setZone(zone);
|
||||
|
||||
group = new SPK::Group(*other.group);
|
||||
group->setModel(particleModel);
|
||||
group->removeEmitter(other.emitter);
|
||||
group->addEmitter(emitter);
|
||||
|
||||
particleSystem = new SPK::System(*other.particleSystem);
|
||||
particleSystem->removeGroup(other.group);
|
||||
particleSystem->addGroup(group);
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
/**
|
||||
|
||||
GDevelop - Particle System Extension
|
||||
Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PARTICLESYSTEMWRAPPER_H
|
||||
#define PARTICLESYSTEMWRAPPER_H
|
||||
|
||||
#include <memory>
|
||||
class SFMLTextureWrapper;
|
||||
|
||||
namespace SPK {
|
||||
class System;
|
||||
class Model;
|
||||
class SphericEmitter;
|
||||
class Sphere;
|
||||
class Group;
|
||||
namespace GL {
|
||||
class GLRenderer;
|
||||
}
|
||||
} // namespace SPK
|
||||
|
||||
/**
|
||||
* Wrapper around SPARK related stuff.
|
||||
* This class gives direct access to these stuff,
|
||||
* it only manages the destruction and automatize the copy behaviour.
|
||||
*/
|
||||
class GD_EXTENSION_API ParticleSystemWrapper {
|
||||
public:
|
||||
ParticleSystemWrapper();
|
||||
virtual ~ParticleSystemWrapper();
|
||||
ParticleSystemWrapper(
|
||||
const ParticleSystemWrapper& other) // What a bad design
|
||||
{
|
||||
particleSystem = NULL;
|
||||
particleModel = NULL;
|
||||
emitter = NULL;
|
||||
zone = NULL;
|
||||
group = NULL;
|
||||
renderer = NULL;
|
||||
Init(other);
|
||||
};
|
||||
ParticleSystemWrapper& operator=(const ParticleSystemWrapper& other) {
|
||||
if (&other != this) Init(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SPK::System* particleSystem;
|
||||
SPK::Model* particleModel;
|
||||
SPK::SphericEmitter* emitter;
|
||||
SPK::Sphere* zone;
|
||||
SPK::Group* group;
|
||||
SPK::GL::GLRenderer* renderer;
|
||||
std::shared_ptr<SFMLTextureWrapper> textureParticle;
|
||||
|
||||
private:
|
||||
void Init(const ParticleSystemWrapper& other);
|
||||
|
||||
static bool SPKinitialized;
|
||||
};
|
||||
|
||||
#endif // PARTICLESYSTEMWRAPPER_H
|
1
Extensions/ParticleSystem/SPARK/Version.txt
vendored
1
Extensions/ParticleSystem/SPARK/Version.txt
vendored
@@ -1 +0,0 @@
|
||||
SPARK-1.5.5
|
@@ -1,171 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_ARRAYBUFFER
|
||||
#define H_SPK_ARRAYBUFFER
|
||||
|
||||
#include "Core/SPK_Buffer.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Group;
|
||||
template<class T> class ArrayBufferCreator;
|
||||
|
||||
/**
|
||||
* @brief A template buffer that holds an array of elements of type T
|
||||
* @since 1.03.02
|
||||
*/
|
||||
template<class T>
|
||||
class ArrayBuffer : public Buffer
|
||||
{
|
||||
friend class ArrayBufferCreator<T>;
|
||||
|
||||
public :
|
||||
|
||||
/**
|
||||
* @brief Gets the starting address of the inner array
|
||||
* @return the starting address of the first element of the inner array
|
||||
*/
|
||||
T* getData() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of elements for a single particle
|
||||
* @return the number of elements for a single particle
|
||||
*/
|
||||
const size_t getParticleSize() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the total number of T in the inner array
|
||||
* The value is equal to <i>particleSize * nbParticles</i>.
|
||||
* @return the total number of T in the inner array
|
||||
*/
|
||||
size_t getDataSize() const;
|
||||
|
||||
private :
|
||||
|
||||
T* data;
|
||||
|
||||
size_t particleSize;
|
||||
size_t dataSize;
|
||||
|
||||
ArrayBuffer<T>(size_t nbParticles,size_t particleSize);
|
||||
ArrayBuffer<T>(const ArrayBuffer<T>& buffer);
|
||||
virtual ~ArrayBuffer<T>();
|
||||
|
||||
virtual void swap(size_t index0,size_t index1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Template class to create an ArrayBuffer
|
||||
* @since 1.03.02
|
||||
*/
|
||||
template<class T>
|
||||
class ArrayBufferCreator : public BufferCreator
|
||||
{
|
||||
public :
|
||||
|
||||
/**
|
||||
* @brief Constructor of ArrayBuffer
|
||||
* @param particleSize : the number of elements per particle in the buffer to be created
|
||||
*/
|
||||
ArrayBufferCreator<T>(size_t particleSize);
|
||||
|
||||
private :
|
||||
|
||||
size_t particleSize;
|
||||
|
||||
virtual ArrayBuffer<T>* createBuffer(size_t nbParticles,const Group& group) const;
|
||||
};
|
||||
|
||||
// Typedefs
|
||||
/** @brief A buffer storing an array of floats */
|
||||
typedef ArrayBuffer<float> FloatBuffer;
|
||||
/** @brief the buffer creator of the float buffer */
|
||||
typedef ArrayBufferCreator<float> FloatBufferCreator;
|
||||
|
||||
|
||||
template<class T>
|
||||
ArrayBuffer<T>::ArrayBuffer(size_t nbParticles,size_t particleSize) :
|
||||
Buffer(),
|
||||
dataSize(nbParticles * particleSize),
|
||||
particleSize(particleSize)
|
||||
{
|
||||
data = new T[dataSize];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
ArrayBuffer<T>::ArrayBuffer(const ArrayBuffer<T>& buffer) :
|
||||
Buffer(buffer),
|
||||
dataSize(buffer.dataSize),
|
||||
particleSize(buffer.particleSize)
|
||||
{
|
||||
data = new T[dataSize];
|
||||
std::memcpy(data,buffer.data,dataSize * sizeof(T));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
ArrayBuffer<T>::~ArrayBuffer()
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T* ArrayBuffer<T>::getData() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const size_t ArrayBuffer<T>::getParticleSize() const
|
||||
{
|
||||
return particleSize;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline size_t ArrayBuffer<T>::getDataSize() const
|
||||
{
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayBuffer<T>::swap(size_t index0,size_t index1)
|
||||
{
|
||||
T* address0 = data + index0 * particleSize;
|
||||
T* address1 = data + index1 * particleSize;
|
||||
for (size_t i = 0; i < particleSize; ++i)
|
||||
std::swap(address0[i],address1[i]);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
ArrayBufferCreator<T>::ArrayBufferCreator(size_t particleSize) :
|
||||
BufferCreator(),
|
||||
particleSize(particleSize)
|
||||
{}
|
||||
|
||||
template<class T>
|
||||
ArrayBuffer<T>* ArrayBufferCreator<T>::createBuffer(size_t nbParticles,const Group& group) const
|
||||
{
|
||||
return new ArrayBuffer<T>(nbParticles,particleSize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,131 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_BUFFER
|
||||
#define H_SPK_BUFFER
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Particle;
|
||||
class Group;
|
||||
|
||||
/**
|
||||
* @brief An abstract class that defines the interface for the additional buffers of Group
|
||||
*
|
||||
* A buffer allows a Group to hold additional data.<br>
|
||||
* Typically, they are used for rendering as the GPU or the rendering engine needs data to be organized in a specific way.<br>
|
||||
* <br>
|
||||
* Their use can be extended to anything to store data within a group.<br>
|
||||
* Buffers can also be swapped as particles are swap within a group. This allows to have the ordering of data consistent with the ordering of particles.<br>
|
||||
* However, if the buffers are only used for temporary storage on a single frame (most of the renderers), it is not necessary to swap the data.<br>
|
||||
* <br>
|
||||
* A buffer also contains a flag which is an unsigned integer that can be used to check the validity of the buffer from frame to frame.<br>
|
||||
* <br>
|
||||
* Note that only a group can create and delete a buffer. The user can ask a group to create a new buffer by passing a BufferCreator object to it.<br>
|
||||
* Check out the group interface about buffers for more info.
|
||||
*
|
||||
* @since 1.03.02
|
||||
*/
|
||||
class Buffer
|
||||
{
|
||||
friend class BufferCreator;
|
||||
friend class Group;
|
||||
friend void swapParticles(Particle& a,Particle& b);
|
||||
|
||||
public :
|
||||
|
||||
/**
|
||||
* @brief Gets the current flag of this buffer
|
||||
* @return the current flag of this buffer
|
||||
*/
|
||||
unsigned int getFlag() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether data is swapped as particles in the group are swapped
|
||||
* @return true if data must be swapped with particles, false if not
|
||||
*/
|
||||
bool isSwapEnabled() const;
|
||||
|
||||
protected :
|
||||
|
||||
Buffer() {};
|
||||
virtual ~Buffer() {};
|
||||
|
||||
private :
|
||||
|
||||
unsigned int flag;
|
||||
bool swapEnabled;
|
||||
|
||||
/**
|
||||
* @brief Swaps 2 particles data in this buffer
|
||||
*
|
||||
* This is a pure virtual method that must be implemented by inherited classes of buffer.
|
||||
*
|
||||
* @param index0 : the index of the first particle to swap
|
||||
* @param index1 : the index of the second particle to swap
|
||||
*/
|
||||
virtual void swap(size_t index0,size_t index1) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class used by a Group to create an additional Buffer
|
||||
*
|
||||
* This class defines a temporary object to pass to a Group so that it can create and store a new buffer.
|
||||
* Check out the method <i>Group::createBuffer(const std::string&,const BufferCreator&,unsigned int,bool)</i> for more information.
|
||||
*
|
||||
* @since 1.03.02
|
||||
*/
|
||||
class BufferCreator
|
||||
{
|
||||
friend class Group;
|
||||
|
||||
protected :
|
||||
|
||||
virtual ~BufferCreator() {}
|
||||
|
||||
private :
|
||||
|
||||
/**
|
||||
* @brief Creates a new buffer
|
||||
*
|
||||
* This method is called internally by a group to create and store an new buffer.<br>
|
||||
* This is a pure virtual method that must be implemented by inherited classes of buffer.
|
||||
*
|
||||
* @param nbParticles : the number of particles the buffer must be able to store
|
||||
* @param group : the group which contains the buffer
|
||||
*/
|
||||
virtual Buffer* createBuffer(size_t nbParticles,const Group& group) const = 0;
|
||||
};
|
||||
|
||||
|
||||
inline unsigned int Buffer::getFlag() const
|
||||
{
|
||||
return flag;
|
||||
}
|
||||
|
||||
inline bool Buffer::isSwapEnabled() const
|
||||
{
|
||||
return swapEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,146 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_BUFFERHANDLER
|
||||
#define H_SPK_BUFFERHANDLER
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Group;
|
||||
|
||||
/**
|
||||
* @class BufferHandler
|
||||
* @brief A base interface that allows manipulation on Buffer
|
||||
* @since 1.04.00
|
||||
*/
|
||||
class SPK_PREFIX BufferHandler
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////
|
||||
// Destructor //
|
||||
////////////////
|
||||
|
||||
/** @brief Destructor of BufferHandler */
|
||||
virtual ~BufferHandler() {}
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the automatic buffers creation in a static way
|
||||
*
|
||||
* By default, the buffers creation is enabled.
|
||||
*
|
||||
* @param creation : true to enable the buffers creation, false to disable it
|
||||
*/
|
||||
static void enableBuffersCreation(bool creation);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Tells whether the automatic buffers creation is enabled or not
|
||||
* @return true if the buffers creation is enabled, false if it is disabled
|
||||
*/
|
||||
static bool isBuffersCreationEnabled();
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Creates the buffers for this buffer handler in the given group
|
||||
*
|
||||
* If the buffers for this type of buffer handler already exists within the Group, they are priorly destroyed.<br>
|
||||
* The type of buffers created depends on the state of the buffer handler at the time this method is called.<br>
|
||||
* <br>
|
||||
* This method has to be overridden in derived classes that use buffers
|
||||
*
|
||||
* @param group : the Group in which to create the buffers for this buffer handler
|
||||
*/
|
||||
virtual void createBuffers(const Group& group) {};
|
||||
|
||||
/**
|
||||
* @brief Destroys the buffers for this buffer handler in the given group
|
||||
*
|
||||
* if the buffers dont exist, nothing happens.<br>
|
||||
* <br>
|
||||
* This method has to be overridden in derived classes that use buffers
|
||||
*
|
||||
* @param group : the Group in which to destroy the buffers for this buffer handler
|
||||
*/
|
||||
virtual void destroyBuffers(const Group& group) {};
|
||||
|
||||
|
||||
protected :
|
||||
|
||||
// The constructor is private so that the class is not instanciable
|
||||
BufferHandler() {}
|
||||
|
||||
/**
|
||||
* @brief prepares the buffers of the given Group for processing
|
||||
*
|
||||
* Internally, this methods perfoms the following operations :<pre><i>
|
||||
* if check buffers is false
|
||||
* if buffers creation is enabled
|
||||
* destroy buffers
|
||||
* create buffers
|
||||
* return true
|
||||
* else return false
|
||||
* else return true
|
||||
* </i></pre>
|
||||
*
|
||||
* @param group : the group whose buffers must be prepared
|
||||
* @return true if the buffers are ready, false if not
|
||||
*/
|
||||
bool prepareBuffers(const Group& group);
|
||||
|
||||
/**
|
||||
* @brief checks the buffers and prepare them
|
||||
*
|
||||
* This method has to be implemented in derived class that uses buffers.<br>
|
||||
* true must be returned if the buffers are found and initialized, false otherwise.
|
||||
*
|
||||
* @param group : the group in which to check the buffers
|
||||
* @return true if buffers are ready, false otherwise
|
||||
*/
|
||||
virtual bool checkBuffers(const Group& group);
|
||||
|
||||
private :
|
||||
|
||||
static bool bufferCreation;
|
||||
};
|
||||
|
||||
|
||||
inline bool BufferHandler::checkBuffers(const Group& group)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,158 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_DEF
|
||||
#define H_SPK_DEF
|
||||
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
// 1.02.02 Compatibility with older versions
|
||||
#ifdef SPK_DLL
|
||||
#define SPK_CORE_IMPORT
|
||||
#endif
|
||||
|
||||
#ifdef SPK_CORE_EXPORT
|
||||
#define SPK_PREFIX __declspec(dllexport)
|
||||
#elif defined(SPK_IMPORT) || defined(SPK_CORE_IMPORT)
|
||||
#define SPK_PREFIX __declspec(dllimport)
|
||||
#else
|
||||
#define SPK_PREFIX
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4251) // disables the warning about exporting STL classes in DLLs
|
||||
#endif
|
||||
|
||||
// Trace for debugging
|
||||
//#define SPK_DEBUG
|
||||
|
||||
#ifdef SPK_DEBUG
|
||||
#define SPK_TRACE(text) std::cout << text << std::endl;
|
||||
#else
|
||||
#define SPK_TRACE(text)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @mainpage SPARK Particle Engine
|
||||
*
|
||||
* SPARK is an open source library allowing to easily implement full particle systems in C++ applications.<br>
|
||||
* <br>
|
||||
* SPARK has been designed to be :
|
||||
* <ul>
|
||||
* <li>user friendly and easy to implement</li>
|
||||
* <li>very configurable and as complete as possible</li>
|
||||
* <li>evolving and upgradable by users</li>
|
||||
* <li>portable and library free (it only uses the standard library)</li>
|
||||
* </ul>
|
||||
* <br>
|
||||
* @section intro_sec Global Description
|
||||
* in SPARK, a SPK::System is a collection of Groups of Particles.
|
||||
* A SPK::Group contains a SPK::Pool of Particles and defines an complete universe for Particle evolution.
|
||||
* This universe holds 3 types of physical objects :
|
||||
* <ul>
|
||||
* <li>the Emitters : an SPK::Emitter is an object that generates Particles</li>
|
||||
* <li>the Modifiers : a SPK::Modifier is an object that will modify Particles behavior</li>
|
||||
* <li>the Particles themselves : a SPK::Particle is a point that will follow physical laws and will be given some parameters that will evolve from their birth to their death.</li>
|
||||
* </ul>
|
||||
* Those parameters are defined by a SPK::Model of Particles.<br>
|
||||
* The Emitters and Modifiers are physical entities whose body is represented by a SPK::Zone.<br>
|
||||
* A SPK::Vector3D is the primitive object used in SPARK to represents triplets of coordinates in a universe 3D.<br>
|
||||
* <br>
|
||||
* Finally a system/groups can be renderered using a SPK::Renderer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @namespace SPK
|
||||
* @brief the namespace for the whole SPARK library
|
||||
*/
|
||||
namespace SPK
|
||||
{
|
||||
/** @brief the random seed for the pseudo random numbers generation (1 by default) */
|
||||
extern SPK_PREFIX unsigned int randomSeed;
|
||||
|
||||
/**
|
||||
* @brief Returns a random number in the range [min,max[
|
||||
*
|
||||
* Note that the sequence of pseudo random number generated depends on the initial seed which can be set by setting randomSeed.<br>
|
||||
*
|
||||
* @param min : the minimum value
|
||||
* @param max : the maximum value
|
||||
*
|
||||
* @return a random number within [min,max[
|
||||
*/
|
||||
template<typename T>
|
||||
T random(T min,T max)
|
||||
{
|
||||
// optimized standard minimal
|
||||
long tmp0 = 16807L * (randomSeed & 0xFFFFL);
|
||||
long tmp1 = 16807L * (randomSeed >> 16);
|
||||
long tmp2 = (tmp0 >> 16) + tmp1;
|
||||
tmp0 = ((tmp0 & 0xFFFF)|((tmp2 & 0x7FFF) << 16)) + (tmp2 >> 15);
|
||||
|
||||
// correction of the error
|
||||
if ((tmp0 & 0x80000000L) != 0)
|
||||
tmp0 = (tmp0 + 1) & 0x7FFFFFFFL;
|
||||
|
||||
randomSeed = tmp0;
|
||||
|
||||
// find a random number in the interval
|
||||
return static_cast<T>(min + ((randomSeed - 1) / 2147483646.0) * (max - min));
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// global enumerations //
|
||||
/////////////////////////
|
||||
|
||||
/**
|
||||
* @enum ModelParam
|
||||
* @brief Constants for the Model parameters
|
||||
*/
|
||||
enum ModelParam
|
||||
{
|
||||
PARAM_RED = 0, /**< The red component of the Particle */
|
||||
PARAM_GREEN = 1, /**< The green component of the Particle */
|
||||
PARAM_BLUE = 2, /**< The blue component of the Particle */
|
||||
PARAM_ALPHA = 3, /**< The alpha component of the Particle */
|
||||
PARAM_SIZE = 4, /**< The size of the Particle */
|
||||
PARAM_MASS = 5, /**< The mass of the Particle */
|
||||
PARAM_ANGLE = 6, /**< The angle of the texture of the Particle */
|
||||
PARAM_TEXTURE_INDEX = 7, /**< the index of texture of the Particle */
|
||||
PARAM_ROTATION_SPEED = 8, /**< the rotation speed of the particle (must be used with a rotator modifier) */
|
||||
PARAM_CUSTOM_0 = 9, /**< Reserved for a user custom parameter. This is not used by SPARK */
|
||||
PARAM_CUSTOM_1 = 10, /**< Reserved for a user custom parameter. This is not used by SPARK */
|
||||
PARAM_CUSTOM_2 = 11, /**< Reserved for a user custom parameter. This is not used by SPARK */
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,364 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_EMITTER
|
||||
#define H_SPK_EMITTER
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Registerable.h"
|
||||
#include "Core/SPK_Transformable.h"
|
||||
#include "Core/SPK_Zone.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Group;
|
||||
class Particle;
|
||||
|
||||
|
||||
/**
|
||||
* @class Emitter
|
||||
* @brief An abstract class that defines an emitter of particles
|
||||
*
|
||||
*
|
||||
* An Emitter is an object that will launch particles by giving them a velocity and a position.<br>
|
||||
* the position is derived from the Zone of the Emitter.<br>
|
||||
* the velocity is derived from the Emitter itself.<br>
|
||||
* <br>
|
||||
* An Emitter has a flow and a tank of particles.
|
||||
* The flow defines the rate at which particles are launched and the tank defines the total number of Particles the Emitter can launched.<br>
|
||||
* Note that the flow and the tank of an Emitter are only used when the Emitter emits automatically from a Group
|
||||
* but the user can also emit manually outside a Group.
|
||||
*/
|
||||
class SPK_PREFIX Emitter : public Registerable, public Transformable
|
||||
{
|
||||
friend class Group;
|
||||
|
||||
public :
|
||||
|
||||
/////////////////
|
||||
// Constructor //
|
||||
/////////////////
|
||||
|
||||
/** @brief Constructor of Emitter */
|
||||
Emitter();
|
||||
|
||||
////////////////
|
||||
// Destructor //
|
||||
////////////////
|
||||
|
||||
/** @brief Destructor of Emitter */
|
||||
virtual ~Emitter() {}
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets this Emitter active or not.
|
||||
*
|
||||
* An inactive Emitter will not emit in its parent Group during update.<br>
|
||||
* However it can still be used manually by the user.
|
||||
*
|
||||
* @param active : true to activate this Emitter, false to deactivate it
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void setActive(bool active);
|
||||
|
||||
/**
|
||||
* @brief Sets the number of particles in this Emitter's tank
|
||||
*
|
||||
* Each time the Emitter is updated, the number of particles emitted is deduced from the Emitter tank.
|
||||
* When the tank reaches 0, the Emitter will not emit any longer until it is refilled.<br>
|
||||
* <br>
|
||||
* A number of -1 (or any negative number) means the Emitter has an infinite tank which will never be empty.
|
||||
*
|
||||
* @param tank : the number of particles in this Emitters's tank
|
||||
*/
|
||||
void setTank(int tank);
|
||||
|
||||
/**
|
||||
* @brief Changes the number of particles in this Emitters's tank
|
||||
*
|
||||
* The new number of particles in the tank is equal to : <i>number of particles in the tank + n</i>.<br>
|
||||
* This method has no effect for Emitters with infinite tank (a negative number of particles) and an Emitter cannot become infinite with this method (the new number is clamped to 0).
|
||||
*
|
||||
* @param deltaTank : the number to add to the current tank
|
||||
*/
|
||||
void changeTank(int deltaTank);
|
||||
|
||||
/**
|
||||
* @brief Sets the flow of this Emitter
|
||||
*
|
||||
* The flow is in the unit : nb of particle per step.
|
||||
* A flow of -1 (or any negative number) indicates an infinite flow which means all particles in the Emitters(s tank are generated instantly.<br>
|
||||
* Note that if both the flow and the tank are infinite, nothing will happen.
|
||||
*
|
||||
* @param flow : the flow of this Emitter
|
||||
*/
|
||||
void setFlow(float flow);
|
||||
|
||||
/**
|
||||
* @brief Changes the flow of particles of this Emitter
|
||||
*
|
||||
* The new flow is equal to : <i>flow of the Emitter + deltaFlow</i>.<br>
|
||||
* This method has no effect for Emitters with infinite flow (a negative flow of particles) and an Emitter's flow cannot become infinite with this method (the new flow is clamped to 0).
|
||||
*
|
||||
* @param deltaFlow : the number to add to the current flow
|
||||
*/
|
||||
void changeFlow(float deltaFlow);
|
||||
|
||||
/**
|
||||
* @brief Sets the force of this Emitter
|
||||
*
|
||||
* The force of the Emitter vary for each launch of a Particle between a minimum and a maximum.
|
||||
* To have a fixed force for the Emitter, just have <i>min = max</i>.<br>
|
||||
* <br>
|
||||
* the speed at which a Particle will be launched is equal to : <i>force / weight of the Particle</i>.
|
||||
*
|
||||
* @param min : the minimum force of the Emitter
|
||||
* @param max : the maximum force of the Emitter
|
||||
*/
|
||||
void setForce(float min,float max);
|
||||
|
||||
/**
|
||||
* @brief Sets the Zone of this Emitter
|
||||
*
|
||||
* If the Zone is NULL, the default Zone will be used (A Point centered at the origin)
|
||||
*
|
||||
* @param zone : the Zone of this Emitter
|
||||
* @param full : true to generate particles in the whole Zone, false to generate particles only at the Zone borders.
|
||||
*/
|
||||
void setZone(Zone* zone,bool full = true);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Emitter is active or not
|
||||
* @return true if this Emitter is active, false if is is inactive
|
||||
* @since 1.05.00
|
||||
*/
|
||||
bool isActive() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of particles in this Emitter's tank
|
||||
* @return the number of particles in this Emitters's tanl
|
||||
*/
|
||||
int getTank() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the flow of this Emitter
|
||||
* @return the flow of this Emitter
|
||||
*/
|
||||
float getFlow() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the minimum force of this Emitter
|
||||
* @return the minimum force of this Emitter
|
||||
*/
|
||||
float getForceMin() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the maximum force of this Emitter
|
||||
* @return the maximum force of this Emitter
|
||||
*/
|
||||
float getForceMax() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the Zone of this Emitter
|
||||
* @return the Zone of this Emitter
|
||||
*/
|
||||
Zone* getZone() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Emitter emits in the whole Zone or only at its borders
|
||||
* @return true if this EMitter emits in the whole Zone, false if it is only at its borders
|
||||
*/
|
||||
bool isFullZone() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Emitter is sleeping or not
|
||||
*
|
||||
* An Emitter is considered as sleeping if his flow or his tank is equal to 0.
|
||||
*
|
||||
* @return true if this Emitter is sleeping, false if it is active
|
||||
* @since 1.03.00
|
||||
*/
|
||||
bool isSleeping() const;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Emits a Particle from this Emitter
|
||||
*
|
||||
* The Particle's velocity is updated with a call to generateVelocity(Particle&).<br>
|
||||
* The Particle's position is updated with a call to Zone::generatePosition(Particle&) of the Emitter's Zone.<br>
|
||||
*
|
||||
* Note that this will not decrease the number of particles in the Emitter's tank.
|
||||
* To do it, the user has to manually make a call to changeNumber(-1) after this call.
|
||||
*
|
||||
* @param particle : the Particle to emit from this Emitter
|
||||
*/
|
||||
void emit(Particle& particle) const;
|
||||
|
||||
/**
|
||||
* @brief Generates the velocity of the Particle
|
||||
*
|
||||
* The velocity of the Particle is updated in function of the Emitter's nature and parameters.<br>
|
||||
* Unlike emit() the position of the Particle remains unchanged.
|
||||
*
|
||||
* @param particle : the Particle whose velocity has to be updated
|
||||
*/
|
||||
void generateVelocity(Particle& particle) const;
|
||||
|
||||
virtual Registerable* findByName(const std::string& name);
|
||||
|
||||
protected :
|
||||
|
||||
virtual void registerChildren(bool registerAll);
|
||||
virtual void copyChildren(const Registerable& object,bool createBase);
|
||||
virtual void destroyChildren(bool keepChildren);
|
||||
|
||||
virtual void propagateUpdateTransform();
|
||||
|
||||
private :
|
||||
|
||||
Zone* zone;
|
||||
bool full;
|
||||
|
||||
bool active;
|
||||
|
||||
int tank;
|
||||
float flow;
|
||||
|
||||
float forceMin;
|
||||
float forceMax;
|
||||
|
||||
mutable float fraction;
|
||||
|
||||
static Zone& getDefaultZone();
|
||||
|
||||
unsigned int updateNumber(float deltaTime);
|
||||
|
||||
/////////////////////////
|
||||
// pure virtual method //
|
||||
/////////////////////////
|
||||
|
||||
/**
|
||||
* @brief A pure virtual method that generates the velocity of the Particle in function of a speed
|
||||
*
|
||||
* This is a pure virtual method to be implemented by children.<br>
|
||||
* <br>
|
||||
* the Particle velocity has to be set by this method.<br>
|
||||
* the generated velocity of the Particle must have a norm equal to speed.
|
||||
*
|
||||
* @param particle : the Particle whose velocity has to be generated
|
||||
* @param speed : the speed that the velocity must have
|
||||
*/
|
||||
virtual void generateVelocity(Particle& particle,float speed) const = 0;
|
||||
};
|
||||
|
||||
|
||||
inline void Emitter::setActive(bool active)
|
||||
{
|
||||
this->active = active;
|
||||
}
|
||||
|
||||
inline void Emitter::setTank(int tank)
|
||||
{
|
||||
this->tank = tank;
|
||||
}
|
||||
|
||||
inline void Emitter::setFlow(float flow)
|
||||
{
|
||||
this->flow = flow;
|
||||
}
|
||||
|
||||
inline void Emitter::setForce(float min,float max)
|
||||
{
|
||||
forceMin = min;
|
||||
forceMax = max;
|
||||
}
|
||||
|
||||
inline bool Emitter::isActive() const
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
inline int Emitter::getTank() const
|
||||
{
|
||||
return tank;
|
||||
}
|
||||
|
||||
inline float Emitter::getFlow() const
|
||||
{
|
||||
return flow;
|
||||
}
|
||||
|
||||
inline float Emitter::getForceMin() const
|
||||
{
|
||||
return forceMin;
|
||||
}
|
||||
|
||||
inline float Emitter::getForceMax() const
|
||||
{
|
||||
return forceMax;
|
||||
}
|
||||
|
||||
inline Zone* Emitter::getZone() const
|
||||
{
|
||||
return zone;
|
||||
}
|
||||
|
||||
inline bool Emitter::isFullZone() const
|
||||
{
|
||||
return full;
|
||||
}
|
||||
|
||||
inline bool Emitter::isSleeping() const
|
||||
{
|
||||
return ((tank == 0)||(flow == 0.0f));
|
||||
}
|
||||
|
||||
inline void Emitter::emit(Particle& particle) const
|
||||
{
|
||||
zone->generatePosition(particle,full);
|
||||
generateVelocity(particle);
|
||||
}
|
||||
|
||||
inline void Emitter::generateVelocity(Particle& particle) const
|
||||
{
|
||||
generateVelocity(particle,random(forceMin,forceMax) / particle.getParamCurrentValue(PARAM_MASS));
|
||||
}
|
||||
|
||||
inline void Emitter::propagateUpdateTransform()
|
||||
{
|
||||
zone->updateTransform(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,291 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_FACTORY
|
||||
#define H_SPK_FACTORY
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Registerable.h"
|
||||
|
||||
|
||||
/**
|
||||
* @def SPK_Copy(ClassName,arg)
|
||||
* @brief Creates a new registered object from an existing one
|
||||
*
|
||||
* This macro is simply a shortcut call to :<br>
|
||||
* <i>dynamic_cast<SPK::ClassName*>(SPK::SPKFactory::getInstance().create(arg)</i><br>
|
||||
* with <i>arg</i> being either an SPK_ID or a pointer to an object and ClassName being the class of the object.<br>
|
||||
* <br>
|
||||
* If the ID does not exist or the object is not registered, NULL is returned.<br>
|
||||
* <br>
|
||||
* Note that a bad_cast exception can be throw as there is a dynamic_cast call.
|
||||
*
|
||||
* @since 1.03.00
|
||||
*/
|
||||
#define SPK_Copy(ClassName,arg) \
|
||||
dynamic_cast<ClassName*>(SPK::SPKFactory::getInstance().copy(arg))
|
||||
|
||||
/**
|
||||
* @def SPK_Get(ClassName,ID)
|
||||
* @brief Gets a registered object
|
||||
*
|
||||
* This macro is simply a shortcut call to :<br>
|
||||
* <i>dynamic_cast<ClassName*>(SPK::SPKFactory::getInstance().get(ID)</i><br>
|
||||
* <br>
|
||||
* If the ID does not exist, NULL is returned.<br>
|
||||
* <br>
|
||||
* Note that a bad_cast exception can be throw as there is a dynamic_cast call.
|
||||
*
|
||||
* @since 1.03.00
|
||||
*/
|
||||
#define SPK_Get(ClassName,ID) \
|
||||
dynamic_cast<ClassName*>(SPK::SPKFactory::getInstance().get(ID))
|
||||
|
||||
/**
|
||||
* @def SPK_Copy(arg)
|
||||
* @brief Destroys a registered object
|
||||
* @since 1.03.00
|
||||
*/
|
||||
#define SPK_Destroy(arg) \
|
||||
SPK::SPKFactory::getInstance().destroy(arg)
|
||||
|
||||
/**
|
||||
* @def SPK_Create(object)
|
||||
* @brief Creates a registered object
|
||||
* @since 1.03.00
|
||||
*/
|
||||
#define SPK_Create(object) \
|
||||
SPK::SPKFactory::getInstance().create(object)
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
/**
|
||||
* @class SPKFactory
|
||||
* @brief A singleton class that allows to easily define, create, destroy and organize SPARK objects (Registerable)
|
||||
*
|
||||
* A Registerable can either be registered or not. A Registerable created with the SPKFactory becomes registered :
|
||||
* it is given a unique ID and is stored within a map in the SPKFactory.<br>
|
||||
* <br>
|
||||
* the SPKFactory allows the correct copy of a Registerable with all its children Registerable. Children registerable are only copied
|
||||
* within the given Registerable if they are not shared (see Registerable) else only the reference to the shared Registerable is copied<br>
|
||||
* <br>
|
||||
* Moreover, destruction of Registerable and all children is very easy with the factory. Destroying a Registerable will destroy and all its
|
||||
* children which are destroyable and only referenced within the Registerable being destroyed.<br>
|
||||
* Note that the process is recursive through the tree, so destroyable children of destroyable children will be destroyed as well and so on.<br>
|
||||
* <br>
|
||||
* 4 main actions are performed by the SPKFactory :
|
||||
* <ul>
|
||||
* <li>Create a registered Registerable : This is performed with create(const Registerable&). the passed Registerable is used to create a registered Registerable
|
||||
* which is an exact copy. Every elements will be copied even the shared ones. The base Registerable can be registered or not.</li>
|
||||
* <li>Copy a registered Registerable : This is performed with copy(SPK_ID) or copy(const Registerable*). A registered copy of the registered Registerable is created.
|
||||
* The shared children are only referenced while the not shared ones are copied as well. The same happens for children of children and so on.</li>
|
||||
* <li>Destroy a registered Registerable : This is performed with destroy(SPK_ID,bool) or destroy(Registerable*,bool). The Registerable and all its destroyable
|
||||
* registered children will be destroyed. The tree is parsed to destroy children of children and so on. the boolean tells whether to check the number of
|
||||
* references of children or not.</li>
|
||||
* <li>Gets a registered Registerable from its ID. This is performed with get(SPK_ID). Every registered Registerable is stored in a map. The user can retrieve
|
||||
* the address of the Registerable with its ID (if the ID exists in the map).</li>
|
||||
* </ul>
|
||||
* Note that macros are implemented to ease the syntax :
|
||||
* <ul>
|
||||
* <li>SPK_Create(object)</li>
|
||||
* <li>SPK_Copy(ClassName,arg)</li>
|
||||
* <li>SPK_Get(ClassName,arg)</li>
|
||||
* <li>SPK_Destroy(arg)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.03.00
|
||||
*/
|
||||
class SPK_PREFIX SPKFactory
|
||||
{
|
||||
friend class Registerable;
|
||||
|
||||
public :
|
||||
|
||||
/**
|
||||
* @brief Returns the unique instance of the SPKFactory
|
||||
* @return the unique instance of the SPKFactory
|
||||
*/
|
||||
static SPKFactory& getInstance();
|
||||
|
||||
static void destroyInstance();
|
||||
|
||||
/**
|
||||
* @brief Returns the number of Regiterable objects registered in the SPKFactory
|
||||
* @return the number of Regiterable objects registered in the SPKFactoty
|
||||
*/
|
||||
size_t getNbObjects() const;
|
||||
|
||||
/**
|
||||
* @brief Creates a registered Registerable from the passed Registerable
|
||||
* @param base : The Registerable to create the new registered Registerable from
|
||||
* @return the ID of the new registered object
|
||||
*/
|
||||
SPK_ID create(const Registerable& base);
|
||||
|
||||
/**
|
||||
* @brief Creates a new Registerable object which is a copy of the object at the given ID
|
||||
*
|
||||
* If no Registerable with this ID is registered, NULL is returned.
|
||||
*
|
||||
* @param ID : the ID of the Registerable to copy
|
||||
* @return a registered copy of the Registerable or NULL if the passed ID is not registered
|
||||
*/
|
||||
Registerable* copy(SPK_ID ID);
|
||||
|
||||
/**
|
||||
* @brief Creates a new Registerable object which is a copy of the object
|
||||
*
|
||||
* If the passed Registerable is NULL or not registered, NULL is returned.<br>
|
||||
* Note that this function call internally <i>copy(registerable->getSPKID())</i>.
|
||||
*
|
||||
* @param registerable : the registered Registerable to copy
|
||||
* @return a registered copy of the Registerable or NULL if the passed object is not registered
|
||||
*/
|
||||
Registerable* copy(const Registerable* registerable);
|
||||
|
||||
/**
|
||||
* @brief Gets the Registerable of the given ID
|
||||
*
|
||||
* If the ID is not registered, NULL is returned
|
||||
*
|
||||
* @param ID : the ID of the Registerable to get
|
||||
* @return the Registerable with the passed ID or NULL if the ID is not registered
|
||||
*/
|
||||
Registerable* get(SPK_ID ID);
|
||||
|
||||
/**
|
||||
* @brief Destroys the Registerable with the given ID and all its destroyable children
|
||||
*
|
||||
* If the ID is not registered, nothing is destroyed and false is returned.<br>
|
||||
* <br>
|
||||
* The checkNbReferences boolean tells the factory if the number of references of the Registerable to be destroyed
|
||||
* has to be checked.<br>
|
||||
* If set to true, the Registerable will be destroyed only if the number or references within the SPKFactory
|
||||
* (ie in all registered object in the SPKFactory) is 0.<br>
|
||||
* If set to false, the Registerable will be destroyed in any case. Meaning that any reference within the SPKFactory
|
||||
* becomes invalid.
|
||||
*
|
||||
* @param ID : the ID of the Registerable to destroy
|
||||
* @param checkNbReferences : true to destroy only a Registerable with no references in the SPKFactory (safer), false not to perform the check
|
||||
* @return true if the Registerable has been deleted, false if not
|
||||
*/
|
||||
bool destroy(SPK_ID ID,bool checkNbReferences = true);
|
||||
|
||||
/**
|
||||
* @brief Destroys the Registerable and all its destroyable children
|
||||
*
|
||||
* If the Registerable is NULL or is not registered, nothing is destroyed and false is returned.<br>
|
||||
* Note that this function call internally <i>destroy(registerable->getSPKID())</i>.<br>
|
||||
* <br>
|
||||
* see destroy(SPK_ID,bool) for more information.
|
||||
*
|
||||
* @param registerable the Registerable to destroy
|
||||
* @param checkNbReferences : true to destroy only a Registerable with no references in the SPKFactory (safer), false not to perform the check
|
||||
* @return true if the Registerable has been deleted, false if not
|
||||
*/
|
||||
bool destroy(Registerable* registerable,bool checkNbReferences = true);
|
||||
|
||||
/** @brief Destroys all the registered Registerable in the SPKFactory */
|
||||
void destroyAll();
|
||||
|
||||
/**
|
||||
* @brief Trace information on the Registerable with the given ID
|
||||
* @param ID : the ID of the Registerable to trace
|
||||
*/
|
||||
void trace(SPK_ID ID);
|
||||
|
||||
/**
|
||||
* @brief Trace information on the Registerable
|
||||
*
|
||||
* Note that this function call internally <i>trace(registerable->getSPKID())</i>.
|
||||
*
|
||||
* @param registerable : the Registerable to trace
|
||||
*/
|
||||
void trace(const Registerable* registerable);
|
||||
|
||||
/** @brief Trace information on all the registered Registerable within the SPKFactory */
|
||||
void traceAll();
|
||||
|
||||
/**
|
||||
* @brief Finds a registerable by name in the factory
|
||||
*
|
||||
* Note that this method only checks registerables in the SPKFactory.<br>
|
||||
* This method does not call the Registerable::findByName(const string&) of the registerables to check recursively.
|
||||
*
|
||||
* @param name : the name of the registerable to find in the factory
|
||||
* @return the first registerable with that name or NULL of none is found
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Registerable* findByName(const std::string& name);
|
||||
|
||||
private :
|
||||
|
||||
static SPKFactory* instance;
|
||||
static SPK_ID currentID;
|
||||
|
||||
std::map<SPK_ID,Registerable*> SPKRegister;
|
||||
std::map<const Registerable*,Registerable*> SPKAdresses;
|
||||
|
||||
void traceObject(const std::map<SPK_ID,Registerable*>::iterator& it,bool nextLine);
|
||||
|
||||
bool isAlreadyProcessed(const Registerable* source);
|
||||
Registerable* getProcessedObject(const Registerable* source);
|
||||
void markAsProcessed(const Registerable* source,Registerable* object);
|
||||
|
||||
Registerable* registerObject(Registerable* object);
|
||||
void unregisterObject(std::map<SPK_ID,Registerable*>::iterator& it,bool keepChildren = false);
|
||||
bool unregisterObject(SPK_ID ID,bool keepChildren = false);
|
||||
|
||||
// private constructors
|
||||
SPKFactory(){};
|
||||
SPKFactory(const SPKFactory&){};
|
||||
~SPKFactory(){this->destroyAll();}
|
||||
|
||||
#ifdef SPK_DEBUG
|
||||
size_t nbAlloc;
|
||||
size_t nbDesalloc;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
inline size_t SPKFactory::getNbObjects() const
|
||||
{
|
||||
return SPKRegister.size();
|
||||
}
|
||||
|
||||
inline bool SPKFactory::isAlreadyProcessed(const Registerable* source)
|
||||
{
|
||||
return SPKAdresses.find(source) != SPKAdresses.end();
|
||||
}
|
||||
|
||||
inline Registerable* SPKFactory::getProcessedObject(const Registerable* source)
|
||||
{
|
||||
return SPKAdresses.find(source)->second;
|
||||
}
|
||||
|
||||
inline void SPKFactory::markAsProcessed(const Registerable* source,Registerable* object)
|
||||
{
|
||||
SPKAdresses.insert(std::pair<const Registerable*,Registerable*>(source,object));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@@ -1,403 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_INTERPOLATOR
|
||||
#define H_SPK_INTERPOLATOR
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Particle;
|
||||
|
||||
/**
|
||||
* @enum InterpolationType
|
||||
* @brief Constants defining which type of value is used for interpolation
|
||||
* @since 1.05.00
|
||||
*/
|
||||
enum InterpolationType
|
||||
{
|
||||
INTERPOLATOR_LIFETIME, /**< Constant defining the life time as the value used to interpolate */
|
||||
INTERPOLATOR_AGE, /**< Constant defining the age as the value used to interpolate */
|
||||
INTERPOLATOR_PARAM, /**< Constant defining a parameter as the value used to interpolate */
|
||||
INTERPOLATOR_VELOCITY, /**< Constant defining the square norm of the velocity as the value used to interpolate */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An entry in the interpolator graph
|
||||
*
|
||||
* See the Interpolator description for more information
|
||||
*
|
||||
* @since 1.05.00
|
||||
*/
|
||||
struct InterpolatorEntry
|
||||
{
|
||||
float x; /**< x value of this entry */
|
||||
float y0; /**< y first value of this entry */
|
||||
float y1; /**< y second value of this entry */
|
||||
|
||||
/** @brief Default constructor of interpolator entry. All values are set to 0 */
|
||||
InterpolatorEntry() : x(0.0f),y0(0.0f),y1(0.0f) {}
|
||||
|
||||
/**
|
||||
* @brief Constructs an interpolator entry with y0 and y1 having the same value
|
||||
* @param x : the x value
|
||||
* @param y : the y value (value of y0 and y1)
|
||||
*/
|
||||
InterpolatorEntry(float x,float y) : x(x),y0(y),y1(y) {}
|
||||
|
||||
/**
|
||||
* @brief Constructs and interpolator entry
|
||||
* @param x : the x value
|
||||
* @param y0 : the y0 value
|
||||
* @param y1 : the y1 value
|
||||
*/
|
||||
InterpolatorEntry(float x,float y0,float y1) : x(x),y0(y0),y1(y1) {}
|
||||
|
||||
// used internally
|
||||
InterpolatorEntry(float x) : x(x) {}
|
||||
};
|
||||
|
||||
// forward declaration to allow the set of entries in interpolator to be constructed
|
||||
bool operator<(const InterpolatorEntry& entry0,const InterpolatorEntry& entry1);
|
||||
|
||||
/**
|
||||
* @class Interpolator
|
||||
* @brief An interpolator that offers flexible control over particle parameters
|
||||
*
|
||||
* An interpolator is created for each parameter of a model which is set as interpolated.<br>
|
||||
* The user can get the interpolator of a parameter for a given model by calling Model::getInterpolator(ModelParam).<br>
|
||||
* <br>
|
||||
* An interpolator can use several types of value to interpolate a given parameter :
|
||||
* <ul>
|
||||
* <li>the lifetime of a particle : it is defined in a range between 0 and 1, 0 being the birth of the particle and 1 being its death</li>
|
||||
* <li>the age of a particle</li>
|
||||
* <li>the value of another parameter of a particle (which can be any of the parameters)</li>
|
||||
* <li>the square norm of the velocity of a particle</li>
|
||||
* </ul>
|
||||
* Here is a description of how an interpolator works :<br>
|
||||
* <br>
|
||||
* Internally an interpolator holds a list of entries which defines a 2D graph. The entries are sorted internally along the x axis.<br>
|
||||
* Each entry have a unique x value and 2 y values (although both y can have the same value).<br>
|
||||
* <br>
|
||||
* The x defines the value that will be used to interpolate the parameter value. This value depends on the type set of the interpolator.<br>
|
||||
* For instance, if the type is INTERPOLATOR_AGE, the current x value will be the age of the particle.<br>
|
||||
* <br>
|
||||
* Knowing the current x value, the interpolator interpolates the y value in function of the entries y values.<br>
|
||||
* An interpolator holds 2 curves : the y0 one and the y1 one.<br>
|
||||
* Each particle is given a random value between 0 and 1 which defines where between the y0 and the y1 curve the interpolated y value will be.<br>
|
||||
* The final interpolated y value will be the value of the interpolated particle parameter for this frame.<br>
|
||||
* <br>
|
||||
* Moreover the graph can loop or not :
|
||||
* <ul>
|
||||
* <li>If the graph does not loop, the current x value is clamped between the minimum x and the maximum x of the graph.</li>
|
||||
* <li>If the graph loops, the current x is recomputed to fit in the range between the minimum x and the maximum x of the graph.</li>
|
||||
* </ul>
|
||||
* Finally, it is possible to set a variation in the offset and the scale of the current x computed :<br>
|
||||
* Each particle is given an offset and a scale to compute its current x depending on the variations set. The formula to compute the final current x is the following :<br>
|
||||
* <i>final current x = (current x + offset) * scale</i><br>
|
||||
* offset being randomly generated per particle in <i>[-offsetXVariation,+offsetXVariation]</i><br>
|
||||
* scale being randomly generated per particle in <i>1.0 + [-scaleXVariation,+scaleXVariation]</i><br>
|
||||
* <br>
|
||||
* The default values of the interpolator are the following :
|
||||
* <ul>
|
||||
* <li>type : INTERPOLATOR_LIFETIME</li>
|
||||
* <li>offset x variation : 0.0</li>
|
||||
* <li>scale x variation : 0.0</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.05.00
|
||||
*/
|
||||
class SPK_PREFIX Interpolator
|
||||
{
|
||||
friend class Particle;
|
||||
friend class Model;
|
||||
|
||||
public :
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets the value used to interpolate
|
||||
*
|
||||
* See the class description for more information.<br>
|
||||
* Note that the argument param is only used when the type is INTERPOLATOR_PARAM.
|
||||
*
|
||||
* @param type : the type of value used to interpolate
|
||||
* @param param : the parameter used to interpolate when the type is INTERPOLATOR_PARAM.
|
||||
*/
|
||||
void setType(InterpolationType type,ModelParam param = PARAM_SIZE);
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the looping of the graph
|
||||
*
|
||||
* The range of the graph is defined between the entry with the minimum x and the entry with the maximum y.<br>
|
||||
* If the looping is disabled, the x are clamped to the range.<br>
|
||||
* If the looping is enabled, the value of x is reported in the range. It is better that the xmin and xmax have
|
||||
* the same y values so that the graph tiles perfectly.
|
||||
*
|
||||
* @param loop : true to enabled the looping, false to disable it
|
||||
*/
|
||||
void enableLooping(bool loop);
|
||||
|
||||
/**
|
||||
* @brief Sets the scale variation in x
|
||||
*
|
||||
* See the class description for more information
|
||||
*
|
||||
* @param scaleXVariation : the scale variation in x
|
||||
*/
|
||||
void setScaleXVariation(float scaleXVariation);
|
||||
|
||||
/**
|
||||
* @brief Sets the offset variation in x
|
||||
*
|
||||
* See the class description for more information
|
||||
*
|
||||
* @param offsetXVariation : the offset variation in x
|
||||
*/
|
||||
void setOffsetXVariation(float offsetXVariation);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Gets the type of value used to interpolate
|
||||
* @return the type of value used to interpolate
|
||||
*/
|
||||
InterpolationType getType() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the parameter used to interpolate
|
||||
*
|
||||
* Note that the parameter is only used if the type is INTERPOLATOR_PARAM
|
||||
*
|
||||
* @return the parameter used to interpolate
|
||||
*/
|
||||
ModelParam getInterpolatorParam() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether the looping is enabled or not
|
||||
* @return true if the looping is enabled, false if not
|
||||
*/
|
||||
bool isLoopingEnabled() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the scale variation along x
|
||||
* @return the scale variation along x
|
||||
*/
|
||||
float getScaleXVariation() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the offset variation along x
|
||||
* @return the offset variation along x
|
||||
*/
|
||||
float getOffsetXVariation() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the graph of the interpolator
|
||||
* @return the graph of the interpolator
|
||||
*/
|
||||
std::set<InterpolatorEntry>& getGraph();
|
||||
|
||||
/**
|
||||
* @brief Gets the graph of the interpolator (constant version)
|
||||
* @return the graph of the interpolator
|
||||
*/
|
||||
const std::set<InterpolatorEntry>& getGraph() const;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Adds an entry to the graph
|
||||
* @param entry : the entry to add to the graph
|
||||
* @return true if the entry has been added to the graph, false if not (the graph already contains an entry with the same x)
|
||||
*/
|
||||
bool addEntry(const InterpolatorEntry& entry);
|
||||
|
||||
/**
|
||||
* @brief Adds an entry to the graph
|
||||
* @param x : the x of the entry to add
|
||||
* @param y : the y of the entry to add (y0 and y1 are set to y)
|
||||
* @return true if the entry has been added to the graph, false if not (the graph already contains an entry with the same x)
|
||||
*/
|
||||
bool addEntry(float x,float y);
|
||||
|
||||
/**
|
||||
* @brief Adds an entry to the graph
|
||||
* @param x : the x of the entry to add
|
||||
* @param y0 : the y0 of the entry to add
|
||||
* @param y1 : the y1 of the entry to add
|
||||
* @return true if the entry has been added to the graph, false if not (the graph already contains an entry with the same x)
|
||||
*/
|
||||
bool addEntry(float x,float y0,float y1);
|
||||
|
||||
/** @brief Clears the graph (removes all the entries) */
|
||||
void clearGraph();
|
||||
|
||||
/**
|
||||
* @brief Generates a sinusoidal curve
|
||||
*
|
||||
* Note that the graph is previously cleared from all its entries
|
||||
*/
|
||||
void generateSinCurve(float period,float amplitudeMin,float amplitudeMax,float offsetX,float offsetY,float startX,unsigned int length,unsigned int nbSamples);
|
||||
|
||||
/**
|
||||
* @brief Generates a polynomial curve
|
||||
*
|
||||
* Note that the graph is previously cleared from all its entries
|
||||
*/
|
||||
void generatePolyCurve(float constant,float linear,float quadratic,float cubic,float startX,float endX,unsigned int nbSamples);
|
||||
|
||||
private :
|
||||
|
||||
std::set<InterpolatorEntry> graph;
|
||||
|
||||
InterpolationType type;
|
||||
ModelParam param;
|
||||
bool loopingEnabled;
|
||||
|
||||
float scaleXVariation;
|
||||
float offsetXVariation;
|
||||
|
||||
float interpolate(const Particle& particle,ModelParam interpolatedParam,float ratioY,float offsetX,float scaleX);
|
||||
float interpolateY(const InterpolatorEntry& entry,float ratio);
|
||||
|
||||
// methods to compute X
|
||||
typedef float (Interpolator::*computeXFn)(const Particle&) const;
|
||||
static computeXFn COMPUTE_X_FN[4];
|
||||
|
||||
float computeXLifeTime(const Particle& particle) const;
|
||||
float computeXAge(const Particle& particle) const;
|
||||
float computeXParam(const Particle& particle) const;
|
||||
float computeXVelocity(const Particle& particle) const;
|
||||
|
||||
// Only a model can create and destroy an interpolator
|
||||
Interpolator();
|
||||
~Interpolator() {};
|
||||
};
|
||||
|
||||
|
||||
inline void Interpolator::setType(InterpolationType type,ModelParam param)
|
||||
{
|
||||
this->type = type;
|
||||
this->param = param;
|
||||
}
|
||||
|
||||
inline void Interpolator::enableLooping(bool loop)
|
||||
{
|
||||
loopingEnabled = loop;
|
||||
}
|
||||
|
||||
inline void Interpolator::setScaleXVariation(float scaleXVariation)
|
||||
{
|
||||
this->scaleXVariation = scaleXVariation;
|
||||
}
|
||||
|
||||
inline void Interpolator::setOffsetXVariation(float offsetXVariation)
|
||||
{
|
||||
this->offsetXVariation = offsetXVariation;
|
||||
}
|
||||
|
||||
inline InterpolationType Interpolator::getType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
inline ModelParam Interpolator::getInterpolatorParam() const
|
||||
{
|
||||
return param;
|
||||
}
|
||||
|
||||
inline bool Interpolator::isLoopingEnabled() const
|
||||
{
|
||||
return loopingEnabled;
|
||||
}
|
||||
|
||||
inline float Interpolator::getScaleXVariation() const
|
||||
{
|
||||
return scaleXVariation;
|
||||
}
|
||||
|
||||
inline float Interpolator::getOffsetXVariation() const
|
||||
{
|
||||
return offsetXVariation;
|
||||
}
|
||||
|
||||
inline std::set<InterpolatorEntry>& Interpolator::getGraph()
|
||||
{
|
||||
return graph;
|
||||
}
|
||||
|
||||
inline const std::set<InterpolatorEntry>& Interpolator::getGraph() const
|
||||
{
|
||||
return graph;
|
||||
}
|
||||
|
||||
inline bool Interpolator::addEntry(const InterpolatorEntry& entry)
|
||||
{
|
||||
return graph.insert(entry).second;
|
||||
}
|
||||
|
||||
inline bool Interpolator::addEntry(float x,float y)
|
||||
{
|
||||
return addEntry(InterpolatorEntry(x,y));
|
||||
}
|
||||
|
||||
inline bool Interpolator::addEntry(float x,float y0,float y1)
|
||||
{
|
||||
return addEntry(InterpolatorEntry(x,y0,y1));
|
||||
}
|
||||
|
||||
inline void Interpolator::clearGraph()
|
||||
{
|
||||
graph.clear();
|
||||
}
|
||||
|
||||
inline float Interpolator::interpolateY(const InterpolatorEntry& entry,float ratio)
|
||||
{
|
||||
return entry.y0 + (entry.y1 - entry.y0) * ratio;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Functions to sort the entries on the interpolator graph //
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool operator<(const InterpolatorEntry& entry0,const InterpolatorEntry& entry1)
|
||||
{
|
||||
return entry0.x < entry1.x;
|
||||
}
|
||||
|
||||
inline bool operator==(const InterpolatorEntry& entry0,const InterpolatorEntry& entry1)
|
||||
{
|
||||
return entry0.x == entry1.x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,570 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_MODEL
|
||||
#define H_SPK_MODEL
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Registerable.h"
|
||||
#include "Core/SPK_Interpolator.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
/**
|
||||
* @enum ModelParamFlag
|
||||
* @brief Constants used to set bits in Model flags
|
||||
*
|
||||
* These constant values are simply <i>1 << ModelParam</i> constants
|
||||
*/
|
||||
enum ModelParamFlag
|
||||
{
|
||||
FLAG_NONE = 0, /**< the flag bit for no parameter */
|
||||
FLAG_RED = 1 << PARAM_RED, /**< the flag bit for PARAM_RED */
|
||||
FLAG_GREEN = 1 << PARAM_GREEN, /**< the flag bit for PARAM_GREEN */
|
||||
FLAG_BLUE = 1 << PARAM_BLUE, /**< the flag bit for PARAM_BLUE */
|
||||
FLAG_ALPHA = 1 << PARAM_ALPHA, /**< the flag bit for PARAM_ALPHA */
|
||||
FLAG_SIZE = 1 << PARAM_SIZE, /**< the flag bit for PARAM_SIZE */
|
||||
FLAG_MASS = 1 << PARAM_MASS, /**< the flag bit for PARAM_MASS */
|
||||
FLAG_ANGLE = 1 << PARAM_ANGLE, /**< the flag bit for PARAM_ANGLE */
|
||||
FLAG_TEXTURE_INDEX = 1 << PARAM_TEXTURE_INDEX, /**< the flag bit for PARAM_TEXTURE_INDEX */
|
||||
FLAG_ROTATION_SPEED = 1 << PARAM_ROTATION_SPEED, /**< the flag bit for PARAM_ROTATION_SPEED */
|
||||
FLAG_CUSTOM_0 = 1 << PARAM_CUSTOM_0, /**< the flag bit for PARAM_CUSTOM_0 */
|
||||
FLAG_CUSTOM_1 = 1 << PARAM_CUSTOM_1, /**< the flag bit for PARAM_CUSTOM_1 */
|
||||
FLAG_CUSTOM_2 = 1 << PARAM_CUSTOM_2, /**< the flag bit for PARAM_CUSTOM_2 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Model
|
||||
* @brief A model of particles for particles' generation and evolution
|
||||
*
|
||||
* This class defines a behavior for particles generation and evolution over time.<br>
|
||||
* A Particle is generated under a Model that cannot be changed during its life time.
|
||||
* A Particle Model can however be changed but it will reinitialize the Particle parameters and life.<br>
|
||||
* <br>
|
||||
* A Model defines which parameters to use/update for a Particle. To do that an Model holds 4 flags that are :
|
||||
* <ul>
|
||||
* <li>Enabled : The parameter is enabled and can be set. Otherwise its default value is used.</li>
|
||||
* <li>Mutable : The parameter will vary linearly over the life time of the Particle.</li>
|
||||
* <li>Random : The parameter will be randomly generated for the Particle.</li>
|
||||
* <li>Interpolated : The parameter will be interpolated by an object Interpolator to allow flexible variations.</li>
|
||||
* </ul>
|
||||
* The flags are processed when building up a model so that they are consistent :
|
||||
* <ul>
|
||||
* <li>All flags are masked so that they have not bit set at a higher position than the number of parameters.</li>
|
||||
* <li>The mutable,random and interpolated flags are masked with the enabled flag : a parameter must be enabled to be either random, mutable or interpolated.</li>
|
||||
* <li>An interpolated parameter cannot be mutable or/and random as well. The interpolated flag has the priority.</li>
|
||||
* </ul>
|
||||
* The life time of a particle and immortality is also defined by the Model.<br>
|
||||
* <br>
|
||||
* The default values for the parameters are the following :
|
||||
* <ul>
|
||||
* <li>PARAM_RED : 1.0</li>
|
||||
* <li>PARAM_GREEN : 1.0</li>
|
||||
* <li>PARAM_BLUE : 1.0</li>
|
||||
* <li>PARAM_ALPHA : 1.0</li>
|
||||
* <li>PARAM_SIZE : 1.0</li>
|
||||
* <li>PARAM_MASS : 1.0</li>
|
||||
* <li>PARAM_ANGLE : 0.0</li>
|
||||
* <li>PARAM_TEXTURE_INDEX : 0.0</li>
|
||||
* <li>PARAM_ROTATION_SPEED : 0.0</li>
|
||||
* <li>PARAM_CUSTOM_0 : 0.0</li>
|
||||
* <li>PARAM_CUSTOM_1 : 0.0</li>
|
||||
* <li>PARAM_CUSTOM_2 : 0.0</li>
|
||||
* </ul>
|
||||
*/
|
||||
class SPK_PREFIX Model : public Registerable
|
||||
{
|
||||
friend class Particle;
|
||||
|
||||
SPK_IMPLEMENT_REGISTERABLE(Model)
|
||||
|
||||
public :
|
||||
|
||||
//////////////////
|
||||
// Constructors //
|
||||
//////////////////
|
||||
|
||||
/**
|
||||
* @brief The constructor for Model
|
||||
*
|
||||
* The user have to pass the Model flags that cannot be changed afterwards.<br>
|
||||
* To set up flags enumerators from ModelParamFlag can be used in a OR way.<br>
|
||||
* For instance, <i>Model(FLAG_RED | FLAG_GREEN | FLAG_BLUE | FLAG_ALPHA,FLAG_NONE,FLAG_NONE,FLAG_NONE)</i>
|
||||
* constructs a Model that will generate Particles with a defined color that will not change over time.<br>
|
||||
* <br>
|
||||
* Since 1.03.00, PARAM_RED, PARAM_GREEN and PARAM_BLUE are enabled by default.
|
||||
* This is needed to pass the values to the GPU in an optimized way.<br>
|
||||
* Note that even the enable flag passed by the user does not containt those params, they will be enabled anyway.
|
||||
*
|
||||
* @param enableFlag : the enable flag
|
||||
* @param mutableFlag : the mutable flag
|
||||
* @param randomFlag : the random flag
|
||||
* @param interpolatedFlag : the interpolated flag
|
||||
*/
|
||||
Model(int enableFlag = FLAG_RED | FLAG_GREEN | FLAG_BLUE,int mutableFlag = FLAG_NONE,int randomFlag = FLAG_NONE,int interpolatedFlag = FLAG_NONE);
|
||||
|
||||
/**
|
||||
* @brief The copy constructor for Model
|
||||
* @param model : The Model to construct the new Model from
|
||||
*/
|
||||
Model(const Model& model);
|
||||
|
||||
/**
|
||||
* @brief Creates and registers a new Model
|
||||
* @param enableFlag : the enable flag
|
||||
* @param mutableFlag : the mutable flag
|
||||
* @param randomFlag : the random flag
|
||||
* @param interpolatedFlag : the interpolated flag
|
||||
* @return A new registered Model
|
||||
* @since 1.04.00
|
||||
*/
|
||||
static Model* create(int enableFlag = FLAG_RED | FLAG_GREEN | FLAG_BLUE,int mutableFlag = FLAG_NONE,int randomFlag = FLAG_NONE,int interpolatedFlag = FLAG_NONE);
|
||||
|
||||
////////////////
|
||||
// Destructor //
|
||||
////////////////
|
||||
|
||||
/** @brief The destructor for Model */
|
||||
~Model();
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets the life time
|
||||
*
|
||||
* All particles generated under this Model will be given a life time randomly generated within [lifeTimeMin,lifeTimeMax[.<br>
|
||||
* To generate particles with a non random life time, simply use <i>setLifeTime(a,a)</i>.
|
||||
*
|
||||
* @param lifeTimeMin : the minimum life time
|
||||
* @param lifeTimeMax : the maximum life time
|
||||
*/
|
||||
void setLifeTime(float lifeTimeMin,float lifeTimeMax);
|
||||
|
||||
/**
|
||||
* @brief Defines whether to generate immortal particles or not
|
||||
*
|
||||
* Immortal particles will still be given a life time. However the age of immortal particles will not increase so that they cannot die.
|
||||
* An immortal Particle whose Model immortality is unset will grow older again.<br>
|
||||
* The immortality is therefore dynamic and can be granted or removed by impacting all particles generated under this Model.
|
||||
*
|
||||
* @param immortal : whether the Model will generate immortal particles or not
|
||||
*/
|
||||
void setImmortal(bool immortal);
|
||||
|
||||
/**
|
||||
* @brief Sets a given parameter with 4 values
|
||||
*
|
||||
* This method will only set parameters that are enabled, mutable and random.<br>
|
||||
* If not nothing will happen and the method will return false.
|
||||
*
|
||||
* @param type : the parameter to set
|
||||
* @param startMin : the minimum value at the Particle birth
|
||||
* @param startMax : the maximum value at the Particle birth
|
||||
* @param endMin : the minimum value at the Particle death
|
||||
* @param endMax : the maximum value at the Particle death
|
||||
* @return true if the parameter can be set (right flags), false otherwise
|
||||
*/
|
||||
bool setParam(ModelParam type,float startMin,float startMax,float endMin,float endMax);
|
||||
|
||||
/**
|
||||
* @brief Sets a given parameter with 2 values
|
||||
*
|
||||
* This method will only set parameters that are enabled and <b>either</b> mutable or random.<br>
|
||||
* If not nothing will happen and the method will return false.<br>
|
||||
* <br>
|
||||
* In case of a mutable parameter : value0 defines the birth value and value0 defines the death value.<br>
|
||||
* In case of a random parameter : value0 defines the minimum value and value1 defines the maximum value.<br>
|
||||
*
|
||||
* @param type : the parameter to set
|
||||
* @param value0 : the first value (the meaning depends on the flag)
|
||||
* @param value1 : the second value (the meaning depends on the flag)
|
||||
* @return true if the parameter can be set (right flags), false otherwise
|
||||
*/
|
||||
bool setParam(ModelParam type,float value0,float value1);
|
||||
|
||||
/**
|
||||
* @brief Sets a given parameter with 1 value
|
||||
*
|
||||
* This method will only set parameters that are enabled and <b>neither</b> mutable or random.<br>
|
||||
* If not nothing will happen and the method will return false.<br>
|
||||
* <br>
|
||||
* Note that to set the value of an interpolated parameter cannot be set with this function,
|
||||
* you must used the interpolator object associated to the parameter to control its value.
|
||||
*
|
||||
* @param type : the parameter to set
|
||||
* @param value : the value of the parameter
|
||||
* @return true if the parameter can be set (right flags), false otherwise
|
||||
*/
|
||||
bool setParam(ModelParam type,float value);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Gets the minimum life time
|
||||
* @return the minimum life time
|
||||
*/
|
||||
float getLifeTimeMin() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the maximum life time
|
||||
* @return the minimum life time
|
||||
*/
|
||||
float getLifeTimeMax() const;
|
||||
|
||||
/**
|
||||
* @brief Returns whether immortility is set or not
|
||||
* @return whether immortility is set or not
|
||||
*/
|
||||
bool isImmortal() const;
|
||||
|
||||
/**
|
||||
* @brief Checks whether a parameter is enabled or not
|
||||
* @param type : the parameter
|
||||
* @return 0 is the parameter is not enabled, a flag with the parameter bit set otherwise
|
||||
*/
|
||||
int isEnabled(ModelParam type) const;
|
||||
|
||||
/**
|
||||
* @brief Checks whether a parameter is mutable or not
|
||||
* @param type : the parameter
|
||||
* @return 0 is the parameter is not mutable, a flag with the parameter bit set otherwise
|
||||
*/
|
||||
int isMutable(ModelParam type) const;
|
||||
|
||||
/**
|
||||
* @brief Checks whether a parameter is random or not
|
||||
* @param type : the parameter
|
||||
* @return 0 is the parameter is not random, a flag with the parameter bit set otherwise
|
||||
*/
|
||||
int isRandom(ModelParam type) const;
|
||||
|
||||
/**
|
||||
* @brief Checks whether a parameter is interpolated or not
|
||||
* @param type : the parameter
|
||||
* @return 0 is the parameter is not interpolated, a flag with the parameter bit set otherwise
|
||||
* @since 1.05.00
|
||||
*/
|
||||
int isInterpolated(ModelParam type) const;
|
||||
|
||||
/**
|
||||
* @brief Gets a parameter value
|
||||
*
|
||||
* If index is superior or equal to the number of values for the parameter, the default value of the parameter is returned.<br>
|
||||
* Otherwise the value returned depending on the index is :
|
||||
* <ul>
|
||||
* <li>Enabled parameters :
|
||||
* <ul>
|
||||
* <li>0 : the value of the parameter</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Mutable parameters :
|
||||
* <ul>
|
||||
* <li>0 : the birth value of the parameter</li>
|
||||
* <li>1 : the death value of the parameter</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Random parameters :
|
||||
* <ul>
|
||||
* <li>0 : the minimum value of the parameter</li>
|
||||
* <li>1 : the maximum value of the parameter</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Mutable and random parameters :
|
||||
* <ul>
|
||||
* <li>0 : the minimum birth value of the parameter</li>
|
||||
* <li>1 : the maximum birth value of the parameter</li>
|
||||
* <li>2 : the minimum death value of the parameter</li>
|
||||
* <li>3 : the maximum death value of the parameter</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* Note that in case of an interpolated parameter, the default value is always returned.<br>
|
||||
* The user has to use the interpolator object associated to the parameter to get its values.
|
||||
*
|
||||
* @param type : the parameter
|
||||
* @param index : the index of the value to get
|
||||
* @return the value
|
||||
*/
|
||||
float getParamValue(ModelParam type,size_t index) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of values for a parameter
|
||||
*
|
||||
* The number of values depends on the Model flags :
|
||||
* <ul>
|
||||
* <li>Enabled parameter : 1</li>
|
||||
* <li>Mutable <b>or</b> random parameter : 2</li>
|
||||
* <li>Mutable <b>and</b> random parameter : 4</li>
|
||||
* <li>Interpolated parameter : 0</li>
|
||||
* <li>Not Enabled : 0</li>
|
||||
* </ul>
|
||||
* @param type : the parameter
|
||||
* @return the number of values stored in the Model for the parameter
|
||||
*/
|
||||
unsigned int getNbValues(ModelParam type) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of enabled parameters
|
||||
* @return the number of enabled parameters in the model
|
||||
* @since 1.05.00
|
||||
*/
|
||||
size_t getNbEnabled() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of mutable parameters
|
||||
* @return the number of mutable parameters in the model
|
||||
* @since 1.05.00
|
||||
*/
|
||||
size_t getNbMutable() const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the number of random parameters
|
||||
* @return the number of random parameters in the model
|
||||
* @since 1.05.00
|
||||
*/
|
||||
size_t getNRandom() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the interpolator for the given parameter
|
||||
* @param param : the parameter whose intepolator must be retrieved
|
||||
* @return a pointer to the interpolator of the given parameter or NULL if the parameter is not interpolated
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Interpolator* getInterpolator(ModelParam param);
|
||||
|
||||
/**
|
||||
* @brief Gets the number of interpolated parameters
|
||||
* @return the number of interpolated parameters in the model
|
||||
* @since 1.05.00
|
||||
*/
|
||||
size_t getNbInterpolated() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of float values in the particle current array
|
||||
*
|
||||
* The particle current array holds the current values of enabled parameters for a particle.<br>
|
||||
* This is used internally and should not be needed by the user.
|
||||
*
|
||||
* @return the number of float values in the particle current array
|
||||
* @since 1.02.00
|
||||
*/
|
||||
size_t getSizeOfParticleCurrentArray() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of float values in the particle extended array
|
||||
*
|
||||
* The particle extended array holds the extended values needed for parameters interpolation for a particle.<br>
|
||||
* This is used internally and should not be needed by the user.
|
||||
*
|
||||
* @return the number of float values in the particle extended array
|
||||
* @since 1.03.00
|
||||
*/
|
||||
size_t getSizeOfParticleExtendedArray() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of float values in the model array
|
||||
*
|
||||
* This is used internally and should not be needed by the user.
|
||||
*
|
||||
* @return the number of float values in the model array
|
||||
* @since 1.02.00
|
||||
*/
|
||||
size_t getSizeOfModelArray() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the offset of the given parameter in the current array
|
||||
*
|
||||
* This methods is used internally by the engine
|
||||
*
|
||||
* @param param : the parameter
|
||||
* @return the offset of the given parameter in the current array
|
||||
* @since 1.03.00
|
||||
*/
|
||||
size_t getParameterOffset(ModelParam param) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the default value of the parameter
|
||||
* @param param : the parameter to get the default value from
|
||||
* @return the default value of the parameter
|
||||
* @since 1.05.00
|
||||
*/
|
||||
static float getDefaultValue(ModelParam param);
|
||||
|
||||
private :
|
||||
|
||||
// total number of parameters
|
||||
static const size_t NB_PARAMS = 12;
|
||||
// default values for the parameters
|
||||
static const float DEFAULT_VALUES[NB_PARAMS];
|
||||
|
||||
// arrays storing the values of parameters for the model following that form :
|
||||
// enable : 1 value -> value
|
||||
// mutable : 2 values -> start value | end value
|
||||
// random : 2 values -> min value | max value
|
||||
// mutable and random : 4 values -> start min value | start max value | end min value | end max value
|
||||
// interpolated : 0 value
|
||||
float* params;
|
||||
size_t paramsSize;
|
||||
|
||||
// array storing the parameters that are enabled
|
||||
size_t nbEnableParams;
|
||||
int* enableParams;
|
||||
|
||||
// array storing the parameters that are mutable
|
||||
size_t nbMutableParams;
|
||||
int* mutableParams;
|
||||
|
||||
// array storing the parameters that are interpolated
|
||||
size_t nbInterpolatedParams;
|
||||
int* interpolatedParams;
|
||||
|
||||
// nb of random parameters
|
||||
size_t nbRandomParams;
|
||||
|
||||
// array of interpolators
|
||||
Interpolator* interpolators[NB_PARAMS];
|
||||
|
||||
// the flags of the model
|
||||
int enableFlag;
|
||||
int mutableFlag;
|
||||
int randomFlag;
|
||||
int interpolatedFlag;
|
||||
|
||||
int particleEnableIndices[NB_PARAMS]; // array storing the index of a parameter in the enableParams array
|
||||
int particleMutableIndices[NB_PARAMS]; // array storing the index of a parameter in the mutableParams array
|
||||
int indices[NB_PARAMS]; // array storing the index of a parameter in the model param array
|
||||
|
||||
float lifeTimeMin;
|
||||
float lifeTimeMax;
|
||||
bool immortal;
|
||||
|
||||
void initParamArrays(const Model& model);
|
||||
};
|
||||
|
||||
|
||||
inline Model* Model::create(int enableFlag,int mutableFlag,int randomFlag,int interpolatedFlag)
|
||||
{
|
||||
Model* obj = new Model(enableFlag,mutableFlag,randomFlag,interpolatedFlag);
|
||||
registerObject(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
inline void Model::setLifeTime(float lifeTimeMin,float lifeTimeMax)
|
||||
{
|
||||
this->lifeTimeMin = lifeTimeMin;
|
||||
this->lifeTimeMax = lifeTimeMax;
|
||||
}
|
||||
|
||||
inline void Model::setImmortal(bool immortal)
|
||||
{
|
||||
this->immortal = immortal;
|
||||
}
|
||||
|
||||
inline float Model::getLifeTimeMin() const
|
||||
{
|
||||
return lifeTimeMin;
|
||||
}
|
||||
|
||||
inline float Model::getLifeTimeMax() const
|
||||
{
|
||||
return lifeTimeMax;
|
||||
}
|
||||
|
||||
inline bool Model::isImmortal() const
|
||||
{
|
||||
return immortal;
|
||||
}
|
||||
|
||||
inline int Model::isEnabled(ModelParam type) const
|
||||
{
|
||||
return enableFlag & (1 << type);
|
||||
}
|
||||
|
||||
inline int Model::isMutable(ModelParam type) const
|
||||
{
|
||||
return mutableFlag & (1 << type);
|
||||
}
|
||||
|
||||
inline int Model::isRandom(ModelParam type) const
|
||||
{
|
||||
return randomFlag & (1 << type);
|
||||
}
|
||||
|
||||
inline int Model::isInterpolated(ModelParam type) const
|
||||
{
|
||||
return interpolatedFlag & (1 << type);
|
||||
}
|
||||
|
||||
inline size_t Model::getNbEnabled() const
|
||||
{
|
||||
return nbEnableParams;
|
||||
}
|
||||
|
||||
inline size_t Model::getNbMutable() const
|
||||
{
|
||||
return nbMutableParams;
|
||||
}
|
||||
|
||||
inline size_t Model::getNRandom() const
|
||||
{
|
||||
return nbRandomParams;
|
||||
}
|
||||
|
||||
inline Interpolator* Model::getInterpolator(ModelParam param)
|
||||
{
|
||||
return interpolators[param];
|
||||
}
|
||||
|
||||
inline size_t Model::getNbInterpolated() const
|
||||
{
|
||||
return nbInterpolatedParams;
|
||||
}
|
||||
|
||||
inline size_t Model::getSizeOfParticleCurrentArray() const
|
||||
{
|
||||
return nbEnableParams;
|
||||
}
|
||||
|
||||
inline size_t Model::getSizeOfParticleExtendedArray() const
|
||||
{
|
||||
return nbMutableParams + (nbInterpolatedParams << 1) + nbInterpolatedParams; // nbMutable + nbInterpolated * 3
|
||||
}
|
||||
|
||||
inline size_t Model::getSizeOfModelArray() const
|
||||
{
|
||||
return paramsSize;
|
||||
}
|
||||
|
||||
inline size_t Model::getParameterOffset(ModelParam param) const
|
||||
{
|
||||
return static_cast<size_t>(particleEnableIndices[param]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,375 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_MODIFIER
|
||||
#define H_SPK_MODIFIER
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Vector3D.h"
|
||||
#include "Core/SPK_Registerable.h"
|
||||
#include "Core/SPK_BufferHandler.h"
|
||||
#include "Core/SPK_Zone.h"
|
||||
#include "Core/SPK_Particle.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class ModifierGroup;
|
||||
|
||||
/**
|
||||
* @enum ModifierTrigger
|
||||
* @brief Constants defining the triggers for Modifier
|
||||
*/
|
||||
enum ModifierTrigger
|
||||
{
|
||||
ALWAYS = 1 << 0, /**< No trigger, a Particle is always modified */
|
||||
INSIDE_ZONE = 1 << 1, /**< Trigger defining a Particle inside the Zone */
|
||||
OUTSIDE_ZONE = 1 << 2, /**< Trigger defining a Particle outside the Zone */
|
||||
INTERSECT_ZONE = 1 << 3, /**< Trigger defining a Particle intersecting the Zone (in any direction) */
|
||||
ENTER_ZONE = 1 << 4, /**< Trigger defining a Particle entering the Zone */
|
||||
EXIT_ZONE = 1 << 5, /**< Trigger defining a Particle exiting the Zone */
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Modifier
|
||||
* @brief A abstract class that defines a physical object acting on particles
|
||||
*
|
||||
* A Modifier is first defined by a Zone and a trigger to that Zone.<br>
|
||||
* If the Particle triggers the Modifier, the Modifier's action is applied to the Particle.<br>
|
||||
* An action can be anything that has effect on the Particle's parameters, position, velocity, life...<br>
|
||||
* <br>
|
||||
* If no Zone is attached to a Modifier the Zone is considered to be the entire universe.<br>
|
||||
* <br>
|
||||
* Like an Emitter, a Modifier can either be used automatically within a Group or manually directly by the user.
|
||||
*/
|
||||
class SPK_PREFIX Modifier : public Registerable,
|
||||
public Transformable,
|
||||
public BufferHandler
|
||||
{
|
||||
friend class ModifierGroup;
|
||||
friend class Group;
|
||||
friend class Particle;
|
||||
|
||||
public :
|
||||
|
||||
/////////////////
|
||||
// Constructor //
|
||||
/////////////////
|
||||
|
||||
/**
|
||||
* @brief Constructor of Modifier
|
||||
* @param availableTriggers : the available triggers for this Modifier (OR-ed)
|
||||
* @param trigger : the default trigger of the Modifier
|
||||
* @param needsIntersection : true if the computation of the intersection is needed, false otherwise
|
||||
* @param needsNormal : true if the computation of the normal is needed, false otherwise
|
||||
* @param zone : the Zone of the Modifier
|
||||
*/
|
||||
Modifier(int availableTriggers = ALWAYS,ModifierTrigger trigger = ALWAYS,bool needsIntersection = false,bool needsNormal = false,Zone* zone = NULL);
|
||||
|
||||
////////////////
|
||||
// Destructor //
|
||||
////////////////
|
||||
|
||||
/** @brief Destructor of Modifier */
|
||||
virtual ~Modifier() {}
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets this Modifier active or not.
|
||||
*
|
||||
* An inactive Modifier will not affect its parent Group during update.<br>
|
||||
* However it can still be used manually by the user.
|
||||
*
|
||||
* @param active : true to activate this Modifier, false to deactivate it
|
||||
* @since 1.03.00
|
||||
*/
|
||||
void setActive(bool active);
|
||||
|
||||
/**
|
||||
* @brief Sets the Zone of this Modifier
|
||||
*
|
||||
* If the Zone is NULL, the Zone is considered to be the entire universe.
|
||||
*
|
||||
* @param zone : the Zone of this Modifier
|
||||
* @param full : true to consider the Zone as a full object so that particles are not allowed to be within
|
||||
*/
|
||||
void setZone(Zone* zone,bool full = false);
|
||||
|
||||
/**
|
||||
* @brief Sets the trigger of this Modifier
|
||||
*
|
||||
* if the trigger is not one of the available triggers (see getAvailableTriggers()) for this Modifier,
|
||||
* nothing happens ad false is returned else the trigger is set and true is returned.
|
||||
*
|
||||
* @param trigger : the trigger of this Modifier
|
||||
* @return true if the trigger can be set, false otherwise
|
||||
*/
|
||||
bool setTrigger(ModifierTrigger trigger);
|
||||
|
||||
/**
|
||||
* @brief Sets whether to consider this modifier local to a system or not
|
||||
*
|
||||
* A local modifier is transformed when its system is transformed, a non local one will not.
|
||||
*
|
||||
* @param local : true to consider the modifier local, false not to
|
||||
* @since 1.03.02
|
||||
*/
|
||||
void setLocalToSystem(bool local);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Modifier is active or not
|
||||
* @return true if this Modifier is active, false if is is inactive
|
||||
* @since 1.03.00
|
||||
*/
|
||||
bool isActive() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the Zone of this Modifier
|
||||
* @return the Zone of this Modifier
|
||||
*/
|
||||
Zone* getZone() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the trigger of this Modifier
|
||||
* @return the trigger of this Modifier
|
||||
*/
|
||||
ModifierTrigger getTrigger() const;
|
||||
|
||||
/**
|
||||
* @brief Gets a flag containing all the available triggers for this Modifier
|
||||
* @return a flag containing all the available triggers for this Modifier
|
||||
*/
|
||||
int getAvailableTriggers() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether the Zone of this Modifier is considerered to be full or not
|
||||
* @return true if the Zone of this Modifier is considerered to be full, false if not
|
||||
*/
|
||||
bool isFullZone() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether this modifier is considered as being local to a system or not
|
||||
*
|
||||
* A local modifier is transformed when its system is transformed, a non local one will not.
|
||||
*
|
||||
* @return true if it is local, false if not
|
||||
* @since 1.03.02
|
||||
*/
|
||||
bool isLocalToSystem() const;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
virtual Registerable* findByName(const std::string& name);
|
||||
|
||||
protected :
|
||||
|
||||
/** @brief the Vector3D that holds the intersection coordinates */
|
||||
static Vector3D intersection;
|
||||
|
||||
/** @brief the Vector3D that holds the intersection coordinates */
|
||||
static Vector3D normal;
|
||||
|
||||
/** @brief true if the Modifier needs the intersection computation, false if not */
|
||||
bool needsIntersection;
|
||||
|
||||
/** @brief true if the Modifier needs the normal computation, false if not */
|
||||
bool needsNormal;
|
||||
|
||||
/** @brief the current trigger of this Modifier */
|
||||
ModifierTrigger trigger;
|
||||
|
||||
/** @brief a flag containing all the available triggers */
|
||||
const int availableTriggers;
|
||||
|
||||
virtual void registerChildren(bool registerAll);
|
||||
virtual void copyChildren(const Registerable& object,bool createBase);
|
||||
virtual void destroyChildren(bool keepChildren);
|
||||
|
||||
virtual void propagateUpdateTransform();
|
||||
|
||||
private :
|
||||
|
||||
Zone* zone;
|
||||
bool full;
|
||||
|
||||
bool active;
|
||||
mutable bool savedActive;
|
||||
|
||||
bool local;
|
||||
|
||||
void beginProcess(Group& group);
|
||||
void endProcess(Group& group);
|
||||
void process(Particle& particle,float deltaTime) const;
|
||||
|
||||
//////////////////////////
|
||||
// Pure virtual methods //
|
||||
//////////////////////////
|
||||
|
||||
/**
|
||||
* @brief A pure virtual method that modifies the Particle
|
||||
*
|
||||
* This is a pure virtual method to be implemented by children.<br>
|
||||
* The Modifier on this Particle has already been triggered and the Particle must be modified by this method.
|
||||
*
|
||||
* @param particle : the Particle that has to be modified
|
||||
* @param deltaTime : the time step
|
||||
*/
|
||||
virtual void modify(Particle& particle,float deltaTime) const = 0;
|
||||
|
||||
/**
|
||||
* @brief A pure virtual method that handles particles on the wrong side of this Modifier Zone.
|
||||
*
|
||||
* This is a pure virtual method to be implemented by children.<br>
|
||||
* This method can be called internally with all triggers except SPK::TRIGGER_INTERSECTS.<br>
|
||||
* <br>
|
||||
* The method isFullZone() can be called to vary the behavior whether the Zone is full or not.<br>
|
||||
* The boolean inside indicates whether the wrong side is inside (true) or outside (false) the Zone.
|
||||
*
|
||||
* @param particle : the Particle which is on the wrong side
|
||||
* @param inside : true if the wrong side is inside, false if it is oustside
|
||||
*/
|
||||
virtual void modifyWrongSide(Particle& particle,bool inside) const {}
|
||||
};
|
||||
|
||||
|
||||
inline void Modifier::setActive(bool active)
|
||||
{
|
||||
this->active = active;
|
||||
}
|
||||
|
||||
inline void Modifier::setLocalToSystem(bool local)
|
||||
{
|
||||
this->local = local;
|
||||
}
|
||||
|
||||
inline bool Modifier::isActive() const
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
inline Zone* Modifier::getZone() const
|
||||
{
|
||||
return zone;
|
||||
}
|
||||
|
||||
inline ModifierTrigger Modifier::getTrigger() const
|
||||
{
|
||||
return trigger;
|
||||
}
|
||||
|
||||
inline int Modifier::getAvailableTriggers() const
|
||||
{
|
||||
return availableTriggers;
|
||||
}
|
||||
|
||||
inline bool Modifier::isFullZone() const
|
||||
{
|
||||
return full;
|
||||
}
|
||||
|
||||
inline bool Modifier::isLocalToSystem() const
|
||||
{
|
||||
return local;
|
||||
}
|
||||
|
||||
inline void Modifier::propagateUpdateTransform()
|
||||
{
|
||||
if (zone != NULL)
|
||||
zone->updateTransform(this);
|
||||
}
|
||||
|
||||
inline void Modifier::endProcess(Group& group)
|
||||
{
|
||||
active = savedActive; // Restores the active state of the modifier
|
||||
}
|
||||
|
||||
inline void Modifier::process(Particle& particle,float deltaTime) const
|
||||
{
|
||||
switch(trigger)
|
||||
{
|
||||
case ALWAYS :
|
||||
modify(particle,deltaTime);
|
||||
break;
|
||||
|
||||
case INSIDE_ZONE :
|
||||
if ((zone == NULL)||(zone->contains(particle.position())))
|
||||
modify(particle,deltaTime);
|
||||
else
|
||||
modifyWrongSide(particle,true);
|
||||
break;
|
||||
|
||||
case OUTSIDE_ZONE :
|
||||
if (zone == NULL)
|
||||
return;
|
||||
if (!zone->contains(particle.position()))
|
||||
modify(particle,deltaTime);
|
||||
else
|
||||
modifyWrongSide(particle,false);
|
||||
break;
|
||||
|
||||
case INTERSECT_ZONE :
|
||||
if (zone == NULL)
|
||||
return;
|
||||
if (zone->intersects(particle.oldPosition(),
|
||||
particle.position(),
|
||||
needsIntersection ? &intersection : NULL,
|
||||
needsNormal ? &normal : NULL))
|
||||
modify(particle,deltaTime);
|
||||
break;
|
||||
|
||||
case ENTER_ZONE :
|
||||
if (zone == NULL)
|
||||
return;
|
||||
if (zone->contains(particle.oldPosition()))
|
||||
modifyWrongSide(particle,true);
|
||||
else if (zone->intersects(particle.oldPosition(),
|
||||
particle.position(),
|
||||
needsIntersection ? &intersection : NULL,
|
||||
needsNormal ? &normal : NULL))
|
||||
modify(particle,deltaTime);
|
||||
break;
|
||||
|
||||
case EXIT_ZONE :
|
||||
if (zone == NULL)
|
||||
return;
|
||||
if (!zone->contains(particle.oldPosition()))
|
||||
modifyWrongSide(particle,false);
|
||||
else if (zone->intersects(particle.oldPosition(),
|
||||
particle.position(),
|
||||
needsIntersection ? &intersection : NULL,
|
||||
needsNormal ? &normal : NULL))
|
||||
modify(particle,deltaTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,430 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_PARTICLE
|
||||
#define H_SPK_PARTICLE
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Vector3D.h"
|
||||
#include "Core/SPK_Pool.h"
|
||||
#include "Core/SPK_Model.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Group;
|
||||
|
||||
/**
|
||||
* @class Particle
|
||||
* @brief A single particle (a point in space with a velocity and different parameters)
|
||||
*
|
||||
* A Particle is the primitive on which all the SPARK engine relies.<br>
|
||||
* Particles are designed to be handled in large amounts (called Group).
|
||||
* This is why the user cannot update or render directly a single Particle.<br>
|
||||
* <br>
|
||||
* Note that the Particle class is only a class that presents an interface to the user (since 1.02.00), particles data are stored in the groups.
|
||||
* This is why copying a Particle will not copy its data.<br>
|
||||
*/
|
||||
class SPK_PREFIX Particle
|
||||
{
|
||||
friend bool isFurtherToCamera(const Particle&,const Particle&);
|
||||
friend void swapParticles(Particle& a,Particle& b);
|
||||
friend class Group;
|
||||
friend class Pool<Particle>;
|
||||
|
||||
|
||||
public :
|
||||
|
||||
/**
|
||||
* @brief Sets the current value for the given parameter
|
||||
*
|
||||
* Note that the method will have no effect if the parameter is not enabled in the Particle's Model.
|
||||
* In this case, the method returns false.
|
||||
*
|
||||
* @param type : the parameter to set
|
||||
* @param value : the value of the parameter
|
||||
* @return true if the parameter can be set, false otherwise (if the parameter is not enabled)
|
||||
*/
|
||||
bool setParamCurrentValue(ModelParam type,float value);
|
||||
|
||||
/**
|
||||
* @brief Sets the final value for the given parameter
|
||||
*
|
||||
* The final value is the value the parameter will have at the end of the Particle's life.<br>
|
||||
* Note that the method will have no effect if the parameter is not mutable in the Particle's Model.
|
||||
* In this case, the method returns false and setParamCurrentValue(ModelParam,float) should be used.
|
||||
*
|
||||
* @param type : the parameter to set
|
||||
* @param value : the value of the parameter
|
||||
* @return true if the parameter can be set, false otherwise (if the parameter is not mutable)
|
||||
*/
|
||||
bool setParamFinalValue(ModelParam type,float value);
|
||||
|
||||
/**
|
||||
* @brief Changes the current value for the given parameter
|
||||
*
|
||||
* The delta is added to the current value of the parameter.<br>
|
||||
* For more information see setParamCurrentValue(ModelParam,float).
|
||||
*
|
||||
* @param type : the parameter to set
|
||||
* @param delta : the delta
|
||||
* @return true if the parameter can be changed, false otherwise (if the parameter is not enabled)
|
||||
* @since 1.02.00
|
||||
*/
|
||||
bool changeParamCurrentValue(ModelParam type,float delta);
|
||||
|
||||
/**
|
||||
* @brief Changes the final value for the given parameter
|
||||
*
|
||||
* The delta is added to the final value of the parameter.<br>
|
||||
* For more information see setParamFinalValue(ModelParam,float).
|
||||
*
|
||||
* @param type : the parameter to set
|
||||
* @param delta : the delta
|
||||
* @return true if the parameter can be changed, false otherwise (if the parameter is not mutable)
|
||||
* @since 1.02.00
|
||||
*/
|
||||
bool changeParamFinalValue(ModelParam type,float delta);
|
||||
|
||||
/**
|
||||
* @brief Sets the life left of the Particle.
|
||||
*
|
||||
* When the Particle's life reaches 0, the Particle is inactivated.
|
||||
*
|
||||
* @param life : the amount of life left of the Particle
|
||||
*/
|
||||
void setLifeLeft(float life);
|
||||
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Gets the position of the Particle
|
||||
* @return the position of this Particle
|
||||
* @since 1.02.00
|
||||
*/
|
||||
Vector3D& position();
|
||||
|
||||
/**
|
||||
* @brief Gets the velocity of the Particle
|
||||
* @return the velocity of this Particle
|
||||
* @since 1.02.00
|
||||
*/
|
||||
Vector3D& velocity();
|
||||
|
||||
/**
|
||||
* @brief Gets the old position of the Particle
|
||||
* @return the old position of this Particle
|
||||
* @since 1.02.00
|
||||
*/
|
||||
Vector3D& oldPosition();
|
||||
|
||||
/**
|
||||
* @brief Gets the position of the Particle
|
||||
*
|
||||
* This is the constant version of position()
|
||||
*
|
||||
* @return the position of this Particle
|
||||
* @since 1.02.00
|
||||
*/
|
||||
const Vector3D& position() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the velocity of the Particle
|
||||
*
|
||||
* This is the constant version of velocity()
|
||||
*
|
||||
* @return the velocity of this Particle
|
||||
* @since 1.02.00
|
||||
*/
|
||||
const Vector3D& velocity() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the old position of the Particle
|
||||
*
|
||||
* This is the constant version of oldPosition()
|
||||
*
|
||||
* @return the old position of this Particle
|
||||
* @since 1.02.00
|
||||
*/
|
||||
const Vector3D& oldPosition() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the current value for the given parameter
|
||||
*
|
||||
* Note that if the the parameter is not enabled in the Particle's Model, the default value for the parameter is returned.
|
||||
*
|
||||
* @param type : the parameter to get the value
|
||||
* @return the current value of the parameter
|
||||
*/
|
||||
float getParamCurrentValue(ModelParam type) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the final value for the given parameter
|
||||
*
|
||||
* Note that if the the parameter is not enabled in the Particle's Model, the default value for the parameter is returned.<br>
|
||||
* If the parameter is enabled but not mutable, the current value is returned.
|
||||
*
|
||||
* @param type : the parameter to get the value
|
||||
* @return the current value of the parameter
|
||||
*/
|
||||
float getParamFinalValue(ModelParam type) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the Model of this Particle
|
||||
* @return A pointer on the Model of this Particle
|
||||
*/
|
||||
Model* getModel() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the group of this Particle
|
||||
* @return A pointer on the Group of this Particle
|
||||
* @since 1.02.00
|
||||
*/
|
||||
Group* getGroup() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the index of this Particle in its Group
|
||||
* @return the index of thi Particle in its Group
|
||||
* @since 1.03.00
|
||||
*/
|
||||
size_t getIndex() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the amount of life left of the Particle
|
||||
*
|
||||
* The life left of the Particle is the time left before the Particle dies.<br>
|
||||
* Note that in case of immortal particles, this value does not evolve.
|
||||
*
|
||||
* @return the amount of life left
|
||||
*/
|
||||
float getLifeLeft() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the age of the Particle
|
||||
*
|
||||
* The age of a Particle starts at zero when it is initialized and evolve at each update.<br>
|
||||
* Note that even immortal particles gets older.
|
||||
*
|
||||
* @return the age of the particle
|
||||
* @since 1.03.00
|
||||
*/
|
||||
float getAge() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the distance of this Particle from the camera.
|
||||
*
|
||||
* Note that the correct distance is only returned if the Group of this Particles has its distance computation enabled.
|
||||
*
|
||||
* @return the distance of this Particle from the camera
|
||||
* @since 1.01.00
|
||||
*/
|
||||
float getDistanceFromCamera() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the square distance of this Particle from the camera.
|
||||
*
|
||||
* Note that the correct distance is only returned if the Group of this Particles has its distance computation enabled.<br>
|
||||
* This method is faster than getDistanceFromCamera() and should be used instead when possible.
|
||||
*
|
||||
* @return the square distance of this Particle from the camera
|
||||
* @since 1.01.00
|
||||
*/
|
||||
float getSqrDistanceFromCamera() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Particle was initialized at its latest update or not
|
||||
*
|
||||
* A call to this method is equivalent to <i>getAge() == 0.0f</i>
|
||||
*
|
||||
* @return true if this Particle was initialized at its latest update, false if not
|
||||
* @since 1.03.00
|
||||
*/
|
||||
bool isNewBorn() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Particle is alive or not
|
||||
*
|
||||
* A call to this method is equivalent to <i>getLifeLeft > 0.0f</i>
|
||||
*
|
||||
* @return true if this Particle is alive, false if it is dead
|
||||
* @since 1.04.00
|
||||
*/
|
||||
bool isAlive() const;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Initializes the Particle
|
||||
*
|
||||
* When a Particle is initialized, all its parameters are reinitialized as well as its life.
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* @brief Kills this Particle
|
||||
*
|
||||
* This method is equivalent to a call to setLifeLeft(float) with life being 0.<br>
|
||||
*
|
||||
* @since 1.01.00
|
||||
*/
|
||||
void kill();
|
||||
|
||||
// As we know the color component are always enabled, we optimizes it a bit for access
|
||||
float getR() const { return currentParams[PARAM_RED]; }
|
||||
float getG() const { return currentParams[PARAM_GREEN]; }
|
||||
float getB() const { return currentParams[PARAM_BLUE]; }
|
||||
|
||||
private :
|
||||
|
||||
struct ParticleData
|
||||
{
|
||||
Vector3D oldPosition;
|
||||
Vector3D position;
|
||||
Vector3D velocity;
|
||||
float age;
|
||||
float life;
|
||||
float sqrDist;
|
||||
};
|
||||
|
||||
Group* group;
|
||||
size_t index;
|
||||
|
||||
ParticleData* data;
|
||||
float* currentParams;
|
||||
float* extendedParams;
|
||||
|
||||
Particle(Group* group,size_t index);
|
||||
|
||||
bool update(float timeDelta);
|
||||
void computeSqrDist();
|
||||
|
||||
void interpolateParameters();
|
||||
};
|
||||
|
||||
|
||||
inline Group* Particle::getGroup() const
|
||||
{
|
||||
return group;
|
||||
}
|
||||
|
||||
inline size_t Particle::getIndex() const
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
inline void Particle::setLifeLeft(float life)
|
||||
{
|
||||
data->life = life;
|
||||
}
|
||||
|
||||
inline Vector3D& Particle::position()
|
||||
{
|
||||
return data->position;
|
||||
}
|
||||
|
||||
inline Vector3D& Particle::velocity()
|
||||
{
|
||||
return data->velocity;
|
||||
}
|
||||
|
||||
inline Vector3D& Particle::oldPosition()
|
||||
{
|
||||
return data->oldPosition;
|
||||
}
|
||||
|
||||
inline const Vector3D& Particle::position() const
|
||||
{
|
||||
return data->position;
|
||||
}
|
||||
|
||||
inline const Vector3D& Particle::velocity() const
|
||||
{
|
||||
return data->velocity;
|
||||
}
|
||||
|
||||
inline const Vector3D& Particle::oldPosition() const
|
||||
{
|
||||
return data->oldPosition;
|
||||
}
|
||||
|
||||
inline float Particle::getLifeLeft() const
|
||||
{
|
||||
return data->life;
|
||||
}
|
||||
|
||||
inline float Particle::getAge() const
|
||||
{
|
||||
return data->age;
|
||||
}
|
||||
|
||||
inline float Particle::getDistanceFromCamera() const
|
||||
{
|
||||
return std::sqrt(data->sqrDist);
|
||||
}
|
||||
|
||||
inline float Particle::getSqrDistanceFromCamera() const
|
||||
{
|
||||
return data->sqrDist;
|
||||
}
|
||||
|
||||
inline bool Particle::isNewBorn() const
|
||||
{
|
||||
return data->age == 0.0f;
|
||||
}
|
||||
|
||||
inline bool Particle::isAlive() const
|
||||
{
|
||||
return data->life > 0.0f;
|
||||
}
|
||||
|
||||
inline void Particle::kill()
|
||||
{
|
||||
data->life = 0.0f;
|
||||
}
|
||||
|
||||
// specialization of the swap for particle
|
||||
template<>
|
||||
inline void Pool<Particle>::swapElements(Particle& a,Particle& b)
|
||||
{
|
||||
swapParticles(a,b);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// Global functions definitions //
|
||||
//////////////////////////////////
|
||||
|
||||
inline bool isFurtherToCamera(const Particle& a, const Particle& b)
|
||||
{
|
||||
return a.getSqrDistanceFromCamera() > b.getSqrDistanceFromCamera();
|
||||
}
|
||||
|
||||
// Swaps particle data. Used internally. Do not use with particles that are not from the same group !
|
||||
extern void swapParticles(Particle& a,Particle& b);
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@@ -1,114 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_REGWRAPPER
|
||||
#define H_SPK_REGWRAPPER
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Registerable.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
/**
|
||||
* @class RegWrapper
|
||||
* @brief A Wrapper class that allows to use any type of object as a Registerable
|
||||
*
|
||||
* It simply encapsulates an object of type defined at compilation time.<br>
|
||||
* It allows to define the behavior of these Group attributes when a copy of the Group occurs.<br>
|
||||
* <br>
|
||||
* The user can use it to define an attribute of a custom Registerable child class that needs to act as a Registerable.<br>
|
||||
* <br>
|
||||
* WARNING : T must obviously not be itself a Registerable.
|
||||
*
|
||||
* @since 1.03.00
|
||||
*/
|
||||
template<class T>
|
||||
class RegWrapper : public Registerable
|
||||
{
|
||||
SPK_IMPLEMENT_REGISTERABLE(RegWrapper<T>)
|
||||
|
||||
public :
|
||||
|
||||
//////////////////
|
||||
// Constructors //
|
||||
//////////////////
|
||||
|
||||
/**
|
||||
* @brief Default constructor of RegWrapper
|
||||
* @param object : the inner object
|
||||
*/
|
||||
RegWrapper<T>(const T& object = T());
|
||||
|
||||
/**
|
||||
* @brief Creates and registers a new RegWrapper
|
||||
* @param object : the inner object
|
||||
* @return A new registered RegWrapper
|
||||
* @since 1.04.00
|
||||
*/
|
||||
static RegWrapper<T>* create(const T& object = T());
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Gets a reference on the inner object
|
||||
* @return a reference on the inner object
|
||||
*/
|
||||
T& get();
|
||||
|
||||
/**
|
||||
* @brief Gets a constant reference on the inner object
|
||||
* @return a constant reference on the inner object
|
||||
*/
|
||||
const T& get() const;
|
||||
|
||||
private :
|
||||
|
||||
T object;
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
inline RegWrapper<T>* RegWrapper<T>::create(const T& object)
|
||||
{
|
||||
RegWrapper<T>* obj = new RegWrapper<T>(object);
|
||||
registerObject(obj);
|
||||
return obj;
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T& RegWrapper<T>::get()
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const T& RegWrapper<T>::get() const
|
||||
{
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,468 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_REGISTERABLE
|
||||
#define H_SPK_REGISTERABLE
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Vector3D.h"
|
||||
|
||||
|
||||
// A macro implementing the clone method for Registerable children
|
||||
// Note that copyChildren and destroyChildren have to be implemented manually if needed
|
||||
#define SPK_IMPLEMENT_REGISTERABLE(ClassName) \
|
||||
\
|
||||
virtual ClassName* clone(bool createBase) const \
|
||||
{ \
|
||||
ClassName* cloneObject = new ClassName(*this); \
|
||||
cloneObject->copyChildren(*this,createBase); \
|
||||
return cloneObject; \
|
||||
} \
|
||||
\
|
||||
public : \
|
||||
virtual std::string getClassName() const {return #ClassName;}
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
/** @brief the ID type of a Registerable */
|
||||
typedef unsigned long SPK_ID;
|
||||
|
||||
/** @brief the ID constant value for unregistered Registerable */
|
||||
extern SPK_PREFIX const SPK_ID NO_ID;
|
||||
|
||||
/** @brief an empty string defining the name of an object with no name */
|
||||
extern SPK_PREFIX const std::string NO_NAME;
|
||||
|
||||
/**
|
||||
* @class Registerable
|
||||
* @brief the abstract base class for SPARK objects
|
||||
*
|
||||
* A Registerable defines a SPARK object that can be managed by the SPKFactory.<br>
|
||||
* <br>
|
||||
* In SPARK, a particle System is defined as a tree of objects. For instance, a System
|
||||
* will contain some Renderer, Emitter and Modifier. Every Emitter and Modifier will
|
||||
* contain a Zone...<br>
|
||||
* All those Registerable are linked by association. A Registerable can be shared to several
|
||||
* Registerable or belong to a single Registerable and die with it (composition).<br>
|
||||
* <br>
|
||||
* The SPKFactory offers a flexible system to define, create and destroy complex association
|
||||
* of Registerable.<br>
|
||||
* <br>
|
||||
* Basically a Registerable has 3 parameters that will define its behavior :
|
||||
* <ul>
|
||||
* <li><b>Registered</b> : a registered Registerable is managed by the SPKFactory to deal with copy and destruction.</li>
|
||||
* <li><b>Shared</b> : a shared Registerable will not be copied when copying its parent. Only its reference will. This allows
|
||||
* for instance to change a parameter for many system with only a call. Note that this is valid only for registered
|
||||
* Registerable copied with the SPKFactory.</li>
|
||||
* <li><b>Destroyable</b> : a destroyable Registerable is a Registerable that is allowed to be destroyed by the SPKFactory when destroying
|
||||
* its parent (if it has no more references on it see below). If not destroyable, the destruction of the Registerable is the user's responsability.
|
||||
* Note that a non destroyable Registerable can still be destroyed by the SPKFactory by a direct call.</li>
|
||||
* </ul>
|
||||
* Moreover, every registered Registerable holds a counter of references that indicates how many registered Registerable hold a reference to it.
|
||||
* A registered Registerable will only be destroyed by the SPKFactory if its number of references is 0 (except for a direct call to its destruction).
|
||||
*
|
||||
* @since 1.03.00
|
||||
*/
|
||||
class SPK_PREFIX Registerable
|
||||
{
|
||||
friend class SPKFactory;
|
||||
|
||||
public :
|
||||
|
||||
//////////////////
|
||||
// Constructors //
|
||||
//////////////////
|
||||
|
||||
/** @brief Default constructor of Registerable */
|
||||
Registerable();
|
||||
|
||||
/**
|
||||
* @brief Copy constructor of Registerable
|
||||
* @param registerable : the Registerable to construct the new Registerable from
|
||||
*/
|
||||
Registerable(const Registerable& registerable);
|
||||
|
||||
////////////////
|
||||
// Destructor //
|
||||
////////////////
|
||||
|
||||
/** @brief Destructor of Registerable */
|
||||
virtual ~Registerable();
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Makes this Registerable shared or not
|
||||
*
|
||||
* By default, a Registerable is not shared
|
||||
*
|
||||
* @param shared : true to make this Registerable shared, false to make it unshared
|
||||
*/
|
||||
void setShared(bool shared);
|
||||
|
||||
/**
|
||||
* @brief Makes this Registerable destroyable or not
|
||||
*
|
||||
* A non destroyable Registerable cannot be destroyed internally.
|
||||
*
|
||||
* @param destroyable : true to make this Registerable destroyable, false to make it undestroyable
|
||||
*/
|
||||
void setDestroyable(bool destroyable);
|
||||
|
||||
/**
|
||||
* @brief Sets the name of this Registerable
|
||||
*
|
||||
* The name is an easy to find registerable in a tree.<br>
|
||||
* See getName() and findByName(const std::string&)
|
||||
*
|
||||
* A constant NO_NAME exists to give no name to the registerable (an empty string)
|
||||
*
|
||||
* @param name : the name of this registerable
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void setName(const std::string& name);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Gets the ID of this Registerable
|
||||
*
|
||||
* If this Registerable is unregistered, NO_ID is returned.<br>
|
||||
* Else an SPK_ID is returned. This ID uniquely identifies the Registerable.
|
||||
*
|
||||
* @return the ID of this Registerable or NO_ID if it is not registered
|
||||
* @since 1.05.04
|
||||
*/
|
||||
SPK_ID getSPKID() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the ID of this Registerable
|
||||
* @return the ID of this Registerable or NO_ID if it is not registered
|
||||
* @deprecated 1.05.04 Use getSPKID instead
|
||||
*/
|
||||
SPK_ID getID() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of references of this Registerable
|
||||
*
|
||||
* The number of references defines the number of times a registered Registerable
|
||||
* is references within all the registered Registerable.<br>
|
||||
* <br>
|
||||
* 0 is always returned for an unregistered Registerable.
|
||||
*
|
||||
* @return the number of references of this Registerable
|
||||
*/
|
||||
unsigned int getNbReferences() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Registerable is registered or not
|
||||
* @return true if this Registerable is registered, false if not
|
||||
*/
|
||||
bool isRegistered() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Registerable is shared or not
|
||||
* @return true if this Registerable is shared, false if not
|
||||
*/
|
||||
bool isShared() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Registerable is destroyable or not
|
||||
* @return true if this Registerable is destroyable, false if not
|
||||
*/
|
||||
bool isDestroyable() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the name of this registerable
|
||||
*
|
||||
* The name is an easy to find registerable in a tree.<br>
|
||||
* See setName(const std::string&) and findByName(const std::string&)
|
||||
*
|
||||
* @return the name of this registerable
|
||||
* @since 1.05.00
|
||||
*/
|
||||
const std::string& getName() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the class of the object
|
||||
*
|
||||
* This method is implemented in non abstract derived class of Registerable with the macro SPK_IMPLEMENT_REGISTERABLE(ClassName).
|
||||
*
|
||||
* @return the name of the class of the object as a std::string
|
||||
*/
|
||||
virtual std::string getClassName() const = 0;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Finds a registerable with its name recursively from this registerable
|
||||
*
|
||||
* If the name is not found, NULL is returned.<br>
|
||||
* If the several objects with the same name exists, only the first one is returned.<br>
|
||||
* <br>
|
||||
* Note that the name of the registerable itself is already tested.
|
||||
*
|
||||
* @param name : the name of the registerable to find
|
||||
* @return : the first registerable with that name within this registerable or NULL if none is found
|
||||
* @since 1.05.00
|
||||
*/
|
||||
virtual Registerable* findByName(const std::string& name);
|
||||
|
||||
protected :
|
||||
|
||||
/**
|
||||
* @brief Registers a child of this Registerable
|
||||
*
|
||||
* This method has to be called in the registerChildren(bool) implementation of a derived class of Registerable.<br>
|
||||
* It is called to allow correct registering and correct reference counting of the children Registerable when registering the Registerable.
|
||||
*
|
||||
* @param child : the child of this Registerable to register
|
||||
* @param registerAll : true to register an unregistered child, false to only increment ref counts of an already registered child
|
||||
* @since 1.04.00
|
||||
*/
|
||||
void registerChild(Registerable* child,bool registerAll);
|
||||
|
||||
/**
|
||||
* @brief Copies a child of this Registerable
|
||||
*
|
||||
* This method has to be called in the copyChildren(const Registerable&,bool) implementation of a derived class of Registerable.<br>
|
||||
* It is called to allow correct copy (of the object or of the reference only) of the children Registerable when copying the Registerable.
|
||||
*
|
||||
* @param child : the child of this Registerable to copy
|
||||
* @param createBase : true if a base is created, false otherwise
|
||||
* @return the children of the copy of this Registerable
|
||||
*/
|
||||
Registerable* copyChild(Registerable* child,bool createBase);
|
||||
|
||||
/**
|
||||
* @brief Destroys a child of this Registerable
|
||||
*
|
||||
* This method has to be called in the destroyChildren(bool) implementation of a derived class of Registerable.<br>
|
||||
* It is called to allows the correct destruction (if not destroyable or references exist) of the children Registerable when destroying the Registerable.
|
||||
*
|
||||
* @param child : the child of this Registerable to destroy
|
||||
* @param keepChildren : true to keep the children (used when destroying all registered Registerable)
|
||||
* @return true if the child was destroyed, false if not
|
||||
*/
|
||||
bool destroyChild(Registerable* child,bool keepChildren);
|
||||
|
||||
/**
|
||||
* @brief Increments the number of references of the child by one
|
||||
*
|
||||
* This method has to be called when adding a child in the implementation of a derived class of Registerable.<br>
|
||||
* It allows to keep the number of references of the child correct.
|
||||
*
|
||||
* @param child : the child of this Registerable to increment references of
|
||||
*/
|
||||
void incrementChildReference(Registerable* child);
|
||||
|
||||
/**
|
||||
* @brief Decrements the number of references of the child by one
|
||||
*
|
||||
* This method has to be called when removing a child in the implementation of a derived class of Registerable.<br>
|
||||
* It allows to keep the number of references of the child correct.
|
||||
*
|
||||
* @param child : the child of this Registerable to decrement references of
|
||||
*/
|
||||
void decrementChildReference(Registerable* child);
|
||||
|
||||
/**
|
||||
* @brief Registers a Registerable in the factory
|
||||
*
|
||||
* This method allows to register an unregistered given object.<br>
|
||||
* If the registerable is already registered nothing happen.<br>
|
||||
* <br>
|
||||
* If registerAll is set to true, all the unregistered children of this Registerable will be registered as well.<br>
|
||||
* Apart from that, all registered children see their reference count increments by one, no matter the value of registerAll.<br>
|
||||
* <br>
|
||||
* Use this method with care as it is very important to never register a object that is allocated on the stack, as the factory
|
||||
* may delete its registered object with a call to delete.
|
||||
*
|
||||
* @param obj : the registerable object to register
|
||||
* @param registerAll : true to register all its unregistered children and chidren of children and so on, false not to
|
||||
* @since 1.04.00
|
||||
*/
|
||||
static void registerObject(Registerable* obj,bool registerAll = false);
|
||||
|
||||
/////////////////////
|
||||
// Virtual methods //
|
||||
/////////////////////
|
||||
|
||||
/**
|
||||
* @brief Registers the children of this Registerable
|
||||
*
|
||||
* This method has to be implemented in derived classes of Registerable which hold pointers or references of Registerable children.<br>
|
||||
* The registerChild(Registerable*,bool) has to be called within it for each child to copy from object.<br>
|
||||
* The registerAll parameter of registerChild is simply the registerAll parameter of registerChildren.
|
||||
*
|
||||
* @param registerAll : true to register unregistered children, false to only increment ref counts of already registered children
|
||||
* @since 1.04.00
|
||||
*/
|
||||
virtual void registerChildren(bool registerAll){};
|
||||
|
||||
/**
|
||||
* @brief Copies the children of object in this Registerable
|
||||
*
|
||||
* This method has to be implemented in derived classes of Registerable which hold pointers or references of Registerable children.<br>
|
||||
* The copyChild(Registerable*,bool) has to be called within it for each child to copy from object.<br>
|
||||
* The createBase parameter of copyChild is simply the createBase parameter of copyChildren.
|
||||
*
|
||||
* @param object : the object to copy the children from
|
||||
* @param createBase : true if a base is created, false otherwise
|
||||
*/
|
||||
virtual void copyChildren(const Registerable& object,bool createBase){};
|
||||
|
||||
/**
|
||||
* @brief Destroys the children of this Registerable
|
||||
*
|
||||
* This method has to be implemented in derived classes of Registerable which hold pointers or references of Registerable children.<br>
|
||||
* The destroyChild(Registerable*,bool) has to be called within it for each child to destroy.<br>
|
||||
* The keepChildren parameter of destroyChild is simply the keepChildren parameter of destroyChildren.
|
||||
*
|
||||
* @param keepChildren : true to keep the children (used when destroying all registered Registerable)
|
||||
*/
|
||||
virtual void destroyChildren(bool keepChildren){};
|
||||
|
||||
private :
|
||||
|
||||
SPK_ID ID;
|
||||
unsigned int nbReferences;
|
||||
|
||||
std::string name;
|
||||
|
||||
bool shared;
|
||||
bool destroyable;
|
||||
|
||||
// Those methods allow specific behavior when registering and unregistering in the SPKFactory
|
||||
virtual void onRegister() {} // Called when a registerable is registered in the SPKFactory
|
||||
virtual void onUnregister() {} // Called when a registerable is unregistered from the SPKFactory
|
||||
|
||||
void incrementReference();
|
||||
void decrementReference();
|
||||
|
||||
// the assignment operator is private
|
||||
Registerable& operator=(const Registerable& registerable);
|
||||
|
||||
/////////////////////////
|
||||
// Pure virtual method //
|
||||
/////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Clones this Registerable
|
||||
*
|
||||
* This method is implemented in non abstract derived class of Registerable with the macro SPK_IMPLEMENT_REGISTERABLE(ClassName).
|
||||
*
|
||||
* @param createBase : true if a base is created, false otherwise
|
||||
* @return the clone of this Registerable
|
||||
*/
|
||||
virtual Registerable* clone(bool createBase) const = 0;
|
||||
};
|
||||
|
||||
|
||||
inline void Registerable::setShared(bool shared)
|
||||
{
|
||||
this->shared = shared;
|
||||
}
|
||||
|
||||
inline void Registerable::setDestroyable(bool destroyable)
|
||||
{
|
||||
this->destroyable = destroyable;
|
||||
}
|
||||
|
||||
inline void Registerable::setName(const std::string& name)
|
||||
{
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
inline SPK_ID Registerable::getSPKID() const
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
inline SPK_ID Registerable::getID() const
|
||||
{
|
||||
return getSPKID();
|
||||
}
|
||||
|
||||
inline unsigned int Registerable::getNbReferences() const
|
||||
{
|
||||
return nbReferences;
|
||||
}
|
||||
|
||||
inline bool Registerable::isRegistered() const
|
||||
{
|
||||
return ID != NO_ID;
|
||||
}
|
||||
|
||||
inline bool Registerable::isShared() const
|
||||
{
|
||||
return shared;
|
||||
}
|
||||
|
||||
inline bool Registerable::isDestroyable() const
|
||||
{
|
||||
return destroyable;
|
||||
}
|
||||
|
||||
inline const std::string& Registerable::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
inline Registerable* Registerable::findByName(const std::string& name)
|
||||
{
|
||||
return getName().compare(name) == 0 ? this : NULL;
|
||||
}
|
||||
|
||||
inline void Registerable::incrementReference()
|
||||
{
|
||||
if (isRegistered())
|
||||
++nbReferences;
|
||||
}
|
||||
|
||||
inline void Registerable::decrementReference()
|
||||
{
|
||||
if ((isRegistered())&&(nbReferences > 0))
|
||||
--nbReferences;
|
||||
}
|
||||
|
||||
inline void Registerable::incrementChildReference(Registerable* child)
|
||||
{
|
||||
if ((isRegistered())&&(child != NULL))
|
||||
child->incrementReference();
|
||||
}
|
||||
|
||||
inline void Registerable::decrementChildReference(Registerable* child)
|
||||
{
|
||||
if ((isRegistered())&&(child != NULL))
|
||||
child->decrementReference();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,220 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_RENDERER
|
||||
#define H_SPK_RENDERER
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Registerable.h"
|
||||
#include "Core/SPK_BufferHandler.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Group;
|
||||
class Particle;
|
||||
|
||||
/**
|
||||
* @enum BlendingMode
|
||||
* @brief Constants defining the available blending modes
|
||||
* @since 1.04.00
|
||||
*/
|
||||
enum BlendingMode
|
||||
{
|
||||
BLENDING_NONE, /**< No blending is applied. The particles will appeared as opaque */
|
||||
BLENDING_ADD, /**< The additive blending is useful to render particles that supposed to emit light (fire, magic spells...) */
|
||||
BLENDING_ALPHA, /**< The alpha blending is useful to render transparent particles */
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum RenderingHint
|
||||
* @brief Constants defining the available rendering hints
|
||||
* @since 1.04.00
|
||||
*/
|
||||
enum RenderingHint
|
||||
{
|
||||
ALPHA_TEST = 1 << 0, /**< The alpha test. Enabling it is useful when rendering fully opaque particles with fully transparent zones (a texture of ball for instance) */
|
||||
DEPTH_TEST = 1 << 1, /**< The depth test. Disabling it is useful when rendering particles with additive blending without having to sort them. Note that disabling the depth test will disable the depth write as well. */
|
||||
DEPTH_WRITE = 1 << 2, /**< The depth write. Disabling it is useful when rendering particles with additive blending without having to sort them. Particles are still culled with the Zbuffer (when behind a wall for instance) */
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Renderer
|
||||
* @brief An abstract class that renders particles
|
||||
*
|
||||
* A renderer is used to represent particle systems.<br>
|
||||
* the representation of a particle system is totally independant to its computation.<br>
|
||||
* <br>
|
||||
* Some renderers (or renderers modes) may need some buffers be attached to the Group of particles they render.<br>
|
||||
* rendering buffers are attached to groups but used by renderers. Their creation can also be given to renderer when needed.<br>
|
||||
* By enabling the buffer creation with the static method enableBuffersCreation(bool), the renderer will create the buffers he needs,
|
||||
* if not already created in the group, before rendering. If buffer creation is disabled, a group that dont have the correct buffers for the renderer, cannot
|
||||
* be renderered, the render method of the renderer will simply exit.<br>
|
||||
* <br>
|
||||
* Note that buffers are linked to a class of renderer, not to a given renderer object.<br>
|
||||
* Moreover buffers have an inner flag that can vary function of the states of the renderer used.
|
||||
*/
|
||||
class SPK_PREFIX Renderer : public Registerable,
|
||||
public BufferHandler
|
||||
{
|
||||
public :
|
||||
|
||||
/////////////////
|
||||
// Constructor //
|
||||
/////////////////
|
||||
|
||||
/** @brief Constructor of Renderer */
|
||||
Renderer();
|
||||
|
||||
////////////////
|
||||
// Destructor //
|
||||
////////////////
|
||||
|
||||
/** @brief Destructor of Renderer */
|
||||
virtual ~Renderer();
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets this Renderer active or not.
|
||||
*
|
||||
* An inactive Renderer will render its parent Group when a call to Group::render() is made.<br>
|
||||
* However it can still be used manually by the user with render(Group&).
|
||||
*
|
||||
* @param active : true to activate this Renderer, false to deactivate it
|
||||
* @since 1.03.00
|
||||
*/
|
||||
void setActive(bool active);
|
||||
|
||||
/**
|
||||
* @brief Sets the blending mode of this renderer
|
||||
*
|
||||
* This is a generic method that allows to set most common blending modes in a generic way.
|
||||
* However renderers can implement method to give more control over the blending mode used.
|
||||
*
|
||||
* @param blendMode : the blending mode to use
|
||||
* @since 1.04.00
|
||||
*/
|
||||
virtual void setBlending(BlendingMode blendMode) = 0;
|
||||
|
||||
/**
|
||||
* @brief Enables or disables a rendering hint
|
||||
*
|
||||
* Note that as stated, these are only hints that may not be taken into account in all rendering APIs
|
||||
*
|
||||
* @param renderingHint : the renderingHint to enable or disable
|
||||
* @param enable : true to enable it, false to disable it
|
||||
* @since 1.04.00
|
||||
*/
|
||||
virtual void enableRenderingHint(RenderingHint renderingHint,bool enable);
|
||||
|
||||
/**
|
||||
* @brief Tells the alpha threshold to use when the ALPHA_TEST is enabled
|
||||
*
|
||||
* The operation performs by the alpha test is <i>greater or equal to threshold</i>
|
||||
*
|
||||
* @param alphaThreshold : the alpha threshold to use for the alpha test
|
||||
* @since 1.04.00
|
||||
*/
|
||||
virtual void setAlphaTestThreshold(float alphaThreshold);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Renderer is active or not
|
||||
* @return true if this Renderer is active, false if is is inactive
|
||||
* @since 1.03.00
|
||||
*/
|
||||
bool isActive() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether a rendering hint is enabled or not
|
||||
* @param renderingHint : the rendering hint
|
||||
* @since 1.04.00
|
||||
*/
|
||||
virtual bool isRenderingHintEnabled(RenderingHint renderingHint) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the alpha threhold used by the alpha test
|
||||
* @return the alpha threhold used by the alpha test
|
||||
* @since 1.04.00
|
||||
*/
|
||||
float getAlphaTestThreshold() const;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Renders a Group of particles
|
||||
* @param group : the Group to render
|
||||
*/
|
||||
virtual void render(const Group& group) = 0;
|
||||
|
||||
private :
|
||||
|
||||
bool active;
|
||||
|
||||
int renderingHintsMask;
|
||||
float alphaThreshold;
|
||||
};
|
||||
|
||||
|
||||
inline void Renderer::setActive(bool active)
|
||||
{
|
||||
this->active = active;
|
||||
}
|
||||
|
||||
inline void Renderer::enableRenderingHint(RenderingHint renderingHint,bool enable)
|
||||
{
|
||||
if (enable)
|
||||
renderingHintsMask |= renderingHint;
|
||||
else
|
||||
renderingHintsMask &= ~renderingHint;
|
||||
}
|
||||
|
||||
inline void Renderer::setAlphaTestThreshold(float alphaThreshold)
|
||||
{
|
||||
this->alphaThreshold = alphaThreshold;
|
||||
}
|
||||
|
||||
inline bool Renderer::isActive() const
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
inline bool Renderer::isRenderingHintEnabled(RenderingHint renderingHint) const
|
||||
{
|
||||
return (renderingHintsMask & renderingHint) != 0;
|
||||
}
|
||||
|
||||
inline float Renderer::getAlphaTestThreshold() const
|
||||
{
|
||||
return alphaThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,457 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_SYSTEM
|
||||
#define H_SPK_SYSTEM
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Registerable.h"
|
||||
#include "Core/SPK_Transformable.h"
|
||||
#include "Core/SPK_Vector3D.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Group;
|
||||
class Vector3D;
|
||||
|
||||
|
||||
/**
|
||||
* @enum StepMode
|
||||
* @brief Enumeration defining how to handle the step time of particle systems
|
||||
* @since 1.05.00
|
||||
*/
|
||||
enum StepMode
|
||||
{
|
||||
STEP_REAL, /**< The step time is the deltatime passed by the user */
|
||||
STEP_CONSTANT, /**< The step time is a constant time therefore 0 to many updates may occur in a call */
|
||||
STEP_ADAPTIVE, /**< The step time is a range between 2 values therefore 0 to many updates may occur in a call */
|
||||
};
|
||||
|
||||
/**
|
||||
* @class System
|
||||
* @brief A whole system of particles
|
||||
*
|
||||
* This class defines a whole system of particles. It contains particle groups.<br>
|
||||
* It offers a way to handle a system very easily.<br>
|
||||
* Basically a particle system is updated by calling update(unsigned int) and renderered with render() at each frame.<br>
|
||||
* <br>
|
||||
* Note that a System is only a helper class to manage many Groups. However it can be omitted and groups can be updated and rendered alone.<br>
|
||||
* <br>
|
||||
* A System is transformable. If the system is transformed, all its sub emitters will be transformed as well. However, its modifiers will not
|
||||
* (modifiers can be described in the world coordinates already). If you wish to transform some of its modifiers as well, you will have to do it aside.
|
||||
*/
|
||||
class SPK_PREFIX System : public Registerable, public Transformable
|
||||
{
|
||||
SPK_IMPLEMENT_REGISTERABLE(System)
|
||||
|
||||
public :
|
||||
|
||||
/////////////////
|
||||
// Constructor //
|
||||
/////////////////
|
||||
|
||||
/** @brief Constructor of System */
|
||||
System();
|
||||
|
||||
/**
|
||||
* @brief Creates and registers a new System
|
||||
* @return A new registered System
|
||||
* @since 1.04.00
|
||||
*/
|
||||
static System* create();
|
||||
|
||||
////////////////
|
||||
// Destructor //
|
||||
////////////////
|
||||
|
||||
virtual ~System() {}
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets the camera position
|
||||
*
|
||||
* Note that the camera position is only useful if a group has to be sorted.<br>
|
||||
* In that case this vector will be used as the camera position to derive the distance between the particle and the camera position.<br>
|
||||
* The camera position has to be updated before an update of the sorted group.
|
||||
*
|
||||
* @param cameraPosition the camera position
|
||||
*/
|
||||
static void setCameraPosition(const Vector3D& cameraPosition);
|
||||
|
||||
/**
|
||||
* @brief Enables or not the clamping on the deltaTime when updating systems
|
||||
*
|
||||
* This allows to limit too big deltaTime which may spoil your particle systems.<br>
|
||||
* Basically if the deltaTime is higher than the clamp value, the clamp calue is used as the deltaTime.<br>
|
||||
* <br>
|
||||
* It allows in real step mode to avoid having too big deltaTimes and in the other 2 modes to avoid having too
|
||||
* many updates that may slow down the application.<br>
|
||||
* <br>
|
||||
* Note that setting the clamp value too low may slow down your systems
|
||||
*
|
||||
* @param useClampStep : true to use a clamp value on the step, false not to
|
||||
* @param clamp : the clamp value
|
||||
* @since 1.05.00
|
||||
*/
|
||||
static void setClampStep(bool useClampStep,float clamp = 1.0f);
|
||||
|
||||
/**
|
||||
* @brief Uses a constant step to update the systems
|
||||
*
|
||||
* This tells the system to be updated with a constant time.<br>
|
||||
* Depending on the deltaTime passed for the update, 0 to many updates can occur.<br>
|
||||
* For example if the delta time is 1.0 and the constant step is 0.1 then 10 updates of time 0.1 will occur.<br>
|
||||
* <br>
|
||||
* This mode is useful when the update must be constant (accurate collisions...) but be aware it can be very computationnaly intensive.
|
||||
*
|
||||
* @param constantStep : the value of the step
|
||||
* @since 1.05.00
|
||||
*/
|
||||
static void useConstantStep(float constantStep);
|
||||
|
||||
/**
|
||||
* @brief Uses an adaptive step to update the systems
|
||||
*
|
||||
* This tells the system to be updated with a time between min and max.<br>
|
||||
* If the deltaTime passed is higher than maxStep or lower than minStep then this mode operates like the constant step mode with
|
||||
* either constant time being maxStep or minStep (respectivally).<br>
|
||||
* If the deltaTime lies between minStep and maxStep then this mode performs like the real step mode.<br>
|
||||
* <br>
|
||||
* This mode is a good alternative between the other two.<br>
|
||||
* Combined with the clamp step, it allows to correctly handle the step time without being to much frame rate dependant.
|
||||
*
|
||||
* @param minStep : the minimal time step
|
||||
* @param maxStep : the maximal time step
|
||||
* @since 1.05.00
|
||||
*/
|
||||
static void useAdaptiveStep(float minStep,float maxStep);
|
||||
|
||||
/**
|
||||
* @brief Uses the real step to update the systems
|
||||
*
|
||||
* This is the basic mode (and the mode per default) to update the systems.<br>
|
||||
* One call to update means one update of time deltaTime.<br>
|
||||
* <br>
|
||||
* This mode is the simpler and the one that allows best performance on low end systems.<br>
|
||||
* However the update may be inaccurate (due to too big deltaTime) and it performs badly with frame rate variation.
|
||||
*
|
||||
* @since 1.05.00
|
||||
*/
|
||||
static void useRealStep();
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the computation of the axis aligned Vector for this System
|
||||
*
|
||||
* Enabling the computation of the AABB for the System only takes the AABB of all AABB of the Groups within the System where AABB computation is enabled.<br>
|
||||
* see Group::enableAABBComputing(bool) for more details.
|
||||
*
|
||||
* @param AABB : true to enable the computing of the AABB of this System, false to disable it
|
||||
*/
|
||||
void enableAABBComputing(bool AABB);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Gets the camera position
|
||||
*
|
||||
* Note that the camera position vector is only read by SPARK. Only the user modifies it.
|
||||
*
|
||||
* @return the camera position
|
||||
*/
|
||||
static const Vector3D& getCameraPosition();
|
||||
|
||||
/**
|
||||
* @brief Gets the current step mode
|
||||
* @return the current step mode
|
||||
*/
|
||||
static StepMode getStepMode();
|
||||
|
||||
/**
|
||||
* @brief Gets the number of active particles in this system
|
||||
*
|
||||
* The number of active particles in the system is the addition of the number of active particles in each group of the system.<br>
|
||||
* Note that the number of active particle of the system is updated after each update of the system.<br>
|
||||
* This means if the user changes manually the number of particles in a group and call this method before an update, the number returned will not be up to date.<br>
|
||||
* To compute and get the real number of active particles in the System, see computeNbParticles().
|
||||
*
|
||||
* @return the number of active particle in the system
|
||||
*/
|
||||
size_t getNbParticles() const;
|
||||
|
||||
/**
|
||||
* @brief Computes the number of active particles in this System and returns it
|
||||
*
|
||||
* Unlike getNbParticles() which returns the last number of particles computed (after a call to update(float) or empty()),
|
||||
* this method recomputes the current number of active particles by parsing all the groups of this System.<br>
|
||||
* In that way, this method must not be used as an accessor but call once when necesseray between 2 updates.<br>
|
||||
* <br>
|
||||
* Note that this method updates the inner number of particles of this System, which means a call to getNbParticles() will
|
||||
* then return the computed number.
|
||||
*
|
||||
* @return the number of active particle in the system
|
||||
* @since 1.02.01
|
||||
*/
|
||||
size_t computeNbParticles();
|
||||
|
||||
/**
|
||||
* @brief Gets the number of groups in the System
|
||||
* @return the number of groups in the System
|
||||
*/
|
||||
size_t getNbGroups() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the vector of the groups (pointers) in this System
|
||||
*
|
||||
* This method allows to modify Group parameters within the System.<br>
|
||||
* Note that for addition and removal, methods <i>addGroup(Group*)</i> and <i>removeGroup(Group*)</i> must exist.<br>
|
||||
*
|
||||
* @return a STL vector containing the groups in the System
|
||||
*/
|
||||
const std::vector<Group*>& getGroups() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the Group at index
|
||||
*
|
||||
* Note that no bound check is performed.
|
||||
*
|
||||
* @param index : the index of the Group to get
|
||||
* @return the Group at index
|
||||
* @since 1.03.00
|
||||
*/
|
||||
Group* getGroup(size_t index);
|
||||
|
||||
/**
|
||||
* @brief Tells whether the computation of the axis aligned bouding box is enabled
|
||||
*
|
||||
* For a description of the computation of the AABB, see enableAABBComputing(bool).
|
||||
*
|
||||
* @return true if the computation of the AABB is enabled, false if it is disabled
|
||||
*/
|
||||
bool isAABBComputingEnabled() const;
|
||||
|
||||
/**
|
||||
* @brief Gets a Vector3D holding the minimum coordinates of the AABB of this System.
|
||||
*
|
||||
* Note that this method is only useful when the AABB computation is enabled (see enableAABBComputing(bool)).
|
||||
*
|
||||
* @return a Vector3D holding the minimum coordinates of the AABB of this System
|
||||
* @since 1.01.00
|
||||
*/
|
||||
const Vector3D& getAABBMin() const;
|
||||
|
||||
/**
|
||||
* @brief Gets a Vector3D holding the maximum coordinates of the AABB of this System.
|
||||
*
|
||||
* Note that this method is only useful when the AABB computation is enabled (see enableAABBComputing(bool)).
|
||||
*
|
||||
* @return a Vector3D holding the maximum coordinates of the AABB of this System
|
||||
* @since 1.01.00
|
||||
*/
|
||||
const Vector3D& getAABBMax() const;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Adds a Group to the System
|
||||
* @param group : a pointer on the Group to add to the System
|
||||
*/
|
||||
void addGroup(Group* group);
|
||||
|
||||
/**
|
||||
* @brief Removes a Group from the System
|
||||
*
|
||||
* If the Group cannot be found, nothing happens.
|
||||
*
|
||||
* @param group : a pointer on the Group to remove from the System
|
||||
*/
|
||||
void removeGroup(Group* group);
|
||||
|
||||
/**
|
||||
* @brief Updates the System of the current time step
|
||||
*
|
||||
* Note that this method updates all groups in the System from first to last.
|
||||
*
|
||||
* @param deltaTime : the time step
|
||||
* @return true if the System is still active (has active groups)
|
||||
*/
|
||||
virtual bool update(float deltaTime);
|
||||
|
||||
/**
|
||||
* @brief Renders particles in the System
|
||||
*
|
||||
* Note that this method renders all groups in the System from first to last.
|
||||
*/
|
||||
virtual void render() const;
|
||||
|
||||
/**
|
||||
* @brief Makes this System grow to the given time
|
||||
*
|
||||
* This method is useful to get a newwly created System to a mature state.<br>
|
||||
* This method only calls update(float) with the step until the total update time reaches the time.
|
||||
*
|
||||
* @param time : the total time of which to update this System
|
||||
* @param step : the time the System is updated at each call to update(float)
|
||||
*
|
||||
* @since 1.01.00
|
||||
*/
|
||||
void grow(float time,float step);
|
||||
|
||||
/**
|
||||
* @brief Empties the System
|
||||
*
|
||||
* This method will make all particles in the System inactive.<br>
|
||||
* However all connections are kept which means groups are still in theSystem.
|
||||
*/
|
||||
void empty();
|
||||
|
||||
/**
|
||||
* @brief Sorts the particles in all the group of this System where the sorting is enabled
|
||||
*
|
||||
* Note that the sorting is also performed during the update.<br>
|
||||
* This method is therefore only useful when the camera position changes several times between 2 updates.<br>
|
||||
* <br>
|
||||
* This methods calls the Group::sortParticles() of each Group in this System.
|
||||
*
|
||||
* @since 1.01.00
|
||||
*/
|
||||
void sortParticles();
|
||||
|
||||
/**
|
||||
* @brief Computes the distances between each Particle in each Group of this System
|
||||
*
|
||||
* Note that the distances computation is also performed during the update.<br>
|
||||
* This method is therefore only useful when the camera position changes several times between 2 updates.<br>
|
||||
* <br>
|
||||
* This methods calls the Group::computeDistances() of each Group in this System.
|
||||
*
|
||||
* @since 1.01.00
|
||||
*/
|
||||
void computeDistances();
|
||||
|
||||
/**
|
||||
* @brief Computes the bounding box of this System and of all groups in the System
|
||||
*
|
||||
* The bounding box of the System is only computed if the System has its bounding box computing enabled.<br>
|
||||
* In the same way, the bounding box of a Group within the System is only computed if the Group has its bounding box computing enabled.<br>
|
||||
* <br>
|
||||
* Note that the computation of bounding boxes is also performed during the update.<br>
|
||||
* This method is therefore only useful when the bounding boxes have to be recomputed between 2 updates.<br>
|
||||
* <br>
|
||||
* This methods calls the Group::computeAABB() of each Group in this System.
|
||||
*
|
||||
* @since 1.01.00
|
||||
*/
|
||||
void computeAABB();
|
||||
|
||||
virtual Registerable* findByName(const std::string& name);
|
||||
|
||||
protected :
|
||||
|
||||
std::vector<Group*> groups;
|
||||
|
||||
virtual void registerChildren(bool registerAll);
|
||||
virtual void copyChildren(const Registerable& object,bool keepChildren);
|
||||
virtual void destroyChildren(bool createBase);
|
||||
|
||||
virtual void propagateUpdateTransform();
|
||||
|
||||
private :
|
||||
|
||||
static Vector3D cameraPosition;
|
||||
|
||||
static StepMode stepMode;
|
||||
static float constantStep;
|
||||
static float minStep;
|
||||
static float maxStep;
|
||||
|
||||
static bool clampStepEnabled;
|
||||
static float clampStep;
|
||||
|
||||
float deltaStep;
|
||||
|
||||
size_t nbParticles;
|
||||
|
||||
bool boundingBoxEnabled;
|
||||
Vector3D AABBMin;
|
||||
Vector3D AABBMax;
|
||||
|
||||
bool innerUpdate(float deltaTime);
|
||||
};
|
||||
|
||||
|
||||
inline System* System::create()
|
||||
{
|
||||
System* obj = new System;
|
||||
registerObject(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
inline void System::enableAABBComputing(bool AABB)
|
||||
{
|
||||
boundingBoxEnabled = AABB;
|
||||
}
|
||||
|
||||
inline size_t System::getNbParticles() const
|
||||
{
|
||||
return nbParticles;
|
||||
}
|
||||
|
||||
inline size_t System::getNbGroups() const
|
||||
{
|
||||
return groups.size();
|
||||
}
|
||||
|
||||
inline const std::vector<Group*>& System::getGroups() const
|
||||
{
|
||||
return groups;
|
||||
}
|
||||
|
||||
inline Group* System::getGroup(size_t index)
|
||||
{
|
||||
return groups[index];
|
||||
}
|
||||
|
||||
inline bool System::isAABBComputingEnabled() const
|
||||
{
|
||||
return boundingBoxEnabled;
|
||||
}
|
||||
|
||||
inline const Vector3D& System::getAABBMin() const
|
||||
{
|
||||
return AABBMin;
|
||||
}
|
||||
|
||||
inline const Vector3D& System::getAABBMax() const
|
||||
{
|
||||
return AABBMax;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,590 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_TRANSFORMABLE
|
||||
#define H_SPK_TRANSFORMABLE
|
||||
|
||||
#include "Core/SPK_Vector3D.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Zone;
|
||||
|
||||
|
||||
/**
|
||||
* @class Transformable
|
||||
* @brief an abstract class that allows matrix transformations
|
||||
*
|
||||
* Every SPARK object that can be transformated thanks to a matrix should derive from this class.<br>
|
||||
* A Transformable stores a matrix and performs operation on object parameters function of its matrix.<br>
|
||||
* <br>
|
||||
* It allows for instance to transform all emitters and zones in a system with a transform matrix.<br>
|
||||
* Particles are still living in the world coordinates (unlike transforming the rendering process).<br>
|
||||
* <br>
|
||||
* Note that SPARK is not a linear algebra library, so this class does not offers lots of matri operations.<br>
|
||||
* It is rather designed to be plugged within an existing engine with its own matrix system.<br>
|
||||
* <br>
|
||||
* SPARK was not designed to offer a complete scene graph. Even if the library can handle matrices stack, it does not
|
||||
* offer lots of possibilities. Once again it was designed to be used with an existing outer scene graph.
|
||||
* <br>
|
||||
* The transforms used are continuous-in-memory homogeneous matrices with vectors being stored with their coordinates contiguous :<br>
|
||||
* <i>[side.x side.y side.z side.w up.x up.y up.z up.w look.x look.y look.z look.w pos.x pos.y pos.z pos.w]</i><br>
|
||||
* (look being -look in right-handed coordinate systems)<br>
|
||||
*
|
||||
* @since 1.03.00
|
||||
*/
|
||||
class SPK_PREFIX Transformable
|
||||
{
|
||||
public :
|
||||
|
||||
///////////////
|
||||
// Constants //
|
||||
///////////////
|
||||
|
||||
/** @brief The number of floats held by a transform */
|
||||
static const size_t TRANSFORM_LENGTH = 16;
|
||||
|
||||
/** @brief The identity matrix */
|
||||
static const float IDENTITY[TRANSFORM_LENGTH];
|
||||
|
||||
/////////////////
|
||||
// Constructor //
|
||||
/////////////////
|
||||
|
||||
/** @brief Constructor of Transformable */
|
||||
Transformable();
|
||||
|
||||
Transformable(const Transformable& transformable);
|
||||
|
||||
////////////////
|
||||
// Destructor //
|
||||
////////////////
|
||||
|
||||
/** @brief Destructor of Transformable */
|
||||
virtual ~Transformable() {}
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets the local transform of this Transformable
|
||||
*
|
||||
* Note that the matrix must contain the following value in that order :<br>
|
||||
* <i>[side.x side.y side.z side.w up.x up.y up.z up.w look.x look.y look.z look.w pos.x pos.y pos.z pos.w]</i><br>
|
||||
* (look being -look in right-handed coordinate systems)<br>
|
||||
* <br>
|
||||
* The matrix being row or column major is just a convention which is not important.<br>
|
||||
* The only thing that matters is that vectors coordinates are contiguous in memory.<br>
|
||||
* If not, see setTransformNC(const float*)
|
||||
*
|
||||
* @param transform : the transform to copy its content from
|
||||
*/
|
||||
void setTransform(const float* transform);
|
||||
|
||||
/**
|
||||
* @brief Sets the local transfom of this Transformable from a "non contiguous vector coordinates" matrix
|
||||
*
|
||||
* Note that the matrix must contain the following value in that order :<br>
|
||||
* <i>[side.x up.x look.x pos.x side.x up.x look.x pos.x side.x up.x look.x pos.x side.w up.w look.w pos.w]</i><br>
|
||||
* (look being -look in right-handed coordinate systems)<br>
|
||||
* <br>
|
||||
* Note the inner transform is stored with vector coordinates being contiguous in memory.<br>
|
||||
* See setTransform(const float*)
|
||||
*
|
||||
* @param transform : the transform to copy its content from
|
||||
*/
|
||||
void setTransformNC(const float* transform);
|
||||
|
||||
/**
|
||||
* @brief Sets the position of the local transform
|
||||
*
|
||||
* The orientation is left untouched.<br>
|
||||
* <br>
|
||||
* Note that this methods sets the local transform.
|
||||
* To compute the world transform and propagate it, updateTransform(const Transformable*) must be called afterwards.
|
||||
*
|
||||
* @param pos : the position of the local transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void setTransformPosition(const Vector3D& pos);
|
||||
|
||||
/**
|
||||
* @brief Sets the orientation of the local transform in a right-handed system
|
||||
*
|
||||
* The position is left untouched.<br>
|
||||
* <br>
|
||||
* Note that this methods sets the local transform.
|
||||
* To compute the world transform and propagate it, updateTransform(const Transformable*) must be called afterwards.
|
||||
*
|
||||
* @param look : the look vector of the transformable
|
||||
* @param up : the up vector of the transformable
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void setTransformOrientationRH(Vector3D look,Vector3D up);
|
||||
|
||||
/**
|
||||
* @brief Sets the orientation of the local transform in a left-handed system
|
||||
*
|
||||
* The position is left untouched.<br>
|
||||
* <br>
|
||||
* Note that this methods sets the local transform.
|
||||
* To compute the world transform and propagate it, updateTransform(const Transformable*) must be called afterwards.
|
||||
*
|
||||
* @param look : the look vector of the transformable
|
||||
* @param up : the up vector of the transformable
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void setTransformOrientationLH(Vector3D look,Vector3D up);
|
||||
|
||||
/**
|
||||
* @brief Sets the orientation of the local transform
|
||||
*
|
||||
* This method allows to set the orientation around an arbitrary axis.<br>
|
||||
* The position is left untouched.<br>
|
||||
* <br>
|
||||
* Note that this methods sets the local transform.
|
||||
* To compute the world transform and propagate it, updateTransform(const Transformable*) must be called afterwards.
|
||||
*
|
||||
* @param axis : the axis of rotation
|
||||
* @param angle : the angle of rotation around the axis
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void setTransformOrientation(Vector3D axis,float angle);
|
||||
|
||||
/**
|
||||
* @brief Sets the orientation of the local transform
|
||||
*
|
||||
* This method allows to set the orientation around an the x axis.<br>
|
||||
* The position is left untouched.<br>
|
||||
* <br>
|
||||
* Note that this methods sets the local transform.
|
||||
* To compute the world transform and propagate it, updateTransform(const Transformable*) must be called afterwards.
|
||||
*
|
||||
* @param angle : the angle of rotation around the x axis
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void setTransformOrientationX(float angle);
|
||||
|
||||
/**
|
||||
* @brief Sets the orientation of the local transform
|
||||
*
|
||||
* This method allows to set the orientation around an the y axis.<br>
|
||||
* The position is left untouched.<br>
|
||||
* <br>
|
||||
* Note that this methods sets the local transform.
|
||||
* To compute the world transform and propagate it, updateTransform(const Transformable*) must be called afterwards.
|
||||
*
|
||||
* @param angle : the angle of rotation around the y axis
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void setTransformOrientationY(float angle);
|
||||
|
||||
/**
|
||||
* @brief Sets the orientation of the local transform
|
||||
*
|
||||
* This method allows to set the orientation around an the z axis.<br>
|
||||
* The position is left untouched.<br>
|
||||
* <br>
|
||||
* Note that this methods sets the local transform.
|
||||
* To compute the world transform and propagate it, updateTransform(const Transformable*) must be called afterwards.
|
||||
*
|
||||
* @param angle : the angle of rotation around the z axis
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void setTransformOrientationZ(float angle);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Gets the local transform of this Transformable
|
||||
* @return a pointer to the local transform of this Transformable
|
||||
*/
|
||||
const float* getLocalTransform() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the world transform of this Transformable
|
||||
* @return a pointer to the world transform of this Transformable
|
||||
*/
|
||||
const float* getWorldTransform() const;
|
||||
|
||||
/**
|
||||
* @brief Tells whether the local transform is the identity or not
|
||||
* @return true if the local transform is identity, false if not
|
||||
*/
|
||||
bool isLocalIdentity() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the position of the local transform
|
||||
* @return the position of the local transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getLocalTransformPos() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the side vector of the local transform
|
||||
* @return the side vector of the local transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getLocalTransformSide() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the up vector of the local transform
|
||||
* @return the up vector of the local transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getLocalTransformUp() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the look vector of the local transform in a right-handed system
|
||||
* @return the look vector of the local transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getLocalTransformLookRH() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the look vector of the local transform in a left-handed system
|
||||
* @return the look vector of the local transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getLocalTransformLookLH() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the position of the world transform
|
||||
* @return the position of the world transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getWorldTransformPos() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the side vector of the world transform
|
||||
* @return the side vector of the world transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getWorldTransformSide() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the up vector of the world transform
|
||||
* @return the up vector of the world transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getWorldTransformUp() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the look vector of the world transform in a right-handed system
|
||||
* @return the look vector of the world transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getWorldTransformLookRH() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the look vector of the world transform in a left-handed system
|
||||
* @return the look vector of the world transform
|
||||
* @since 1.05.00
|
||||
*/
|
||||
Vector3D getWorldTransformLookLH() const;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief lookAt method for a right-handed system
|
||||
*
|
||||
* The vectors are normalized internally.<br>
|
||||
* <br>
|
||||
* Note that this methods sets the local transform.
|
||||
* To compute the world transform and propagate it, updateTransform(const Transformable*) must be called afterwards.
|
||||
*
|
||||
* @param target : the point the transformable is looking at
|
||||
* @param up : the up vector of the transformable
|
||||
* @param pos : the position of the transformable
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void lookAtRH(const Vector3D& target,Vector3D up,const Vector3D& pos);
|
||||
|
||||
/**
|
||||
* @brief lookAt method for a left-handed system
|
||||
*
|
||||
* The vectors are normalized internally.<br>
|
||||
* <br>
|
||||
* Note that this methods sets the local transform.
|
||||
* To compute the world transform and propagate it, updateTransform(const Transformable*) must be called afterwards.
|
||||
*
|
||||
* @param target : the point the transformable is looking at
|
||||
* @param up : the up vector of the transformable
|
||||
* @param pos : the position of the transformable
|
||||
* @since 1.05.00
|
||||
*/
|
||||
void lookAtLH(const Vector3D& target,Vector3D up,const Vector3D& pos);
|
||||
|
||||
/**
|
||||
* @brief Updates the world transform of this Transformable
|
||||
*
|
||||
* The parent transform and the local transform is used to derive the world transform.<br>
|
||||
* If parent is NULL, the local transform is simply copied to the world transform.<br>
|
||||
* <br>
|
||||
* Note that this method only updates the transform if needed
|
||||
*
|
||||
* @param parent : the parent node of this Transformable or NULL
|
||||
*/
|
||||
void updateTransform(const Transformable* parent = NULL);
|
||||
|
||||
/** @brief Resets the transform to identity */
|
||||
void resetTransform();
|
||||
|
||||
protected :
|
||||
|
||||
/**
|
||||
* @brief A helper method to transform a position from local to world coordinates
|
||||
* @param tPos : the resulting transformed position
|
||||
* @param pos : the position in local coordinates
|
||||
*/
|
||||
void transformPos(Vector3D& tPos,const Vector3D& pos);
|
||||
|
||||
/**
|
||||
* @brief A helper method to transform a direction from local to world coordinates
|
||||
* @param tDir : the resulting transformed direction
|
||||
* @param dir : the direction in local coordinates
|
||||
*/
|
||||
void transformDir(Vector3D& tDir,const Vector3D& dir);
|
||||
|
||||
/**
|
||||
* @brief Tells whether this Transformable needs update or not
|
||||
* @return true if it needs update, false if not
|
||||
*/
|
||||
bool isUpdateNotified() const;
|
||||
|
||||
/**
|
||||
* @brief Notifies the Transformable for a update need
|
||||
*
|
||||
* This method has to be called when modifying a parameter that impose the transform's recomputation.
|
||||
*/
|
||||
void notifyForUpdate();
|
||||
|
||||
/**
|
||||
* @brief Gets the latest parent of this Transformable
|
||||
* @return the latest parent of this Transformable or NULL
|
||||
*/
|
||||
const Transformable* getParentTransform() const;
|
||||
|
||||
/**
|
||||
* @brief Updates all the parameters in the world coordinates
|
||||
*
|
||||
* This method can be overriden in derived classes of Transformable (By default it does nothing).<br>
|
||||
* It is this method task to compute all parameters of the class that are dependent of the world transform.
|
||||
*/
|
||||
virtual void innerUpdateTransform() {}
|
||||
|
||||
/**
|
||||
* @brief Propagates the update of the transform to transformable children of this transformable
|
||||
*
|
||||
* This method can be overriden in derived classes of Transformable (By default it does nothing).<br>
|
||||
* It is this method task to call the updateTransform method of transformable children of this transformable.
|
||||
*
|
||||
* @since 1.05.00
|
||||
*/
|
||||
virtual void propagateUpdateTransform() {}
|
||||
|
||||
private :
|
||||
|
||||
float local[TRANSFORM_LENGTH];
|
||||
float world[TRANSFORM_LENGTH];
|
||||
|
||||
unsigned long int currentUpdate;
|
||||
unsigned long int lastUpdate;
|
||||
unsigned long int lastParentUpdate;
|
||||
bool localIdentity;
|
||||
|
||||
const Transformable* parent;
|
||||
|
||||
static void multiply(
|
||||
float* dest,
|
||||
const float* src0,
|
||||
const float* src1);
|
||||
|
||||
static void multiply(
|
||||
Vector3D& dest,
|
||||
const Vector3D& v,
|
||||
const float* m);
|
||||
|
||||
static void rotate(
|
||||
Vector3D& dest,
|
||||
const Vector3D& v,
|
||||
const float* m);
|
||||
};
|
||||
|
||||
|
||||
inline void Transformable::setTransform(const float* transform)
|
||||
{
|
||||
std::memcpy(local,transform,sizeof(float) * TRANSFORM_LENGTH);
|
||||
localIdentity = false;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
inline const float* Transformable::getLocalTransform() const
|
||||
{
|
||||
return local;
|
||||
}
|
||||
|
||||
inline const float* Transformable::getWorldTransform() const
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
inline bool Transformable::isLocalIdentity() const
|
||||
{
|
||||
return localIdentity;
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getLocalTransformPos() const
|
||||
{
|
||||
return Vector3D(local[12],local[13],local[14]);
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getLocalTransformSide() const
|
||||
{
|
||||
return Vector3D(local[0],local[1],local[2]);
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getLocalTransformUp() const
|
||||
{
|
||||
return Vector3D(local[4],local[5],local[6]);
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getLocalTransformLookRH() const
|
||||
{
|
||||
return Vector3D(-local[8],-local[9],-local[10]);
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getLocalTransformLookLH() const
|
||||
{
|
||||
return Vector3D(local[8],local[9],local[10]);
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getWorldTransformPos() const
|
||||
{
|
||||
return Vector3D(world[12],world[13],world[14]);
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getWorldTransformSide() const
|
||||
{
|
||||
return Vector3D(world[0],world[1],world[2]);
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getWorldTransformUp() const
|
||||
{
|
||||
return Vector3D(world[4],world[5],world[6]);
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getWorldTransformLookRH() const
|
||||
{
|
||||
return Vector3D(-world[8],-world[9],-world[10]);
|
||||
}
|
||||
|
||||
inline Vector3D Transformable::getWorldTransformLookLH() const
|
||||
{
|
||||
return Vector3D(world[8],world[9],world[10]);
|
||||
}
|
||||
|
||||
inline void Transformable::lookAtRH(const Vector3D& target,Vector3D up,const Vector3D& pos)
|
||||
{
|
||||
setTransformOrientationRH(target - pos,up);
|
||||
setTransformPosition(pos);
|
||||
}
|
||||
|
||||
inline void Transformable::lookAtLH(const Vector3D& target,Vector3D up,const Vector3D& pos)
|
||||
{
|
||||
setTransformOrientationLH(target - pos,up);
|
||||
setTransformPosition(pos);
|
||||
}
|
||||
|
||||
inline void Transformable::resetTransform()
|
||||
{
|
||||
setTransform(IDENTITY);
|
||||
localIdentity = true;
|
||||
}
|
||||
|
||||
inline bool Transformable::isUpdateNotified() const
|
||||
{
|
||||
return lastUpdate != currentUpdate;
|
||||
}
|
||||
|
||||
inline void Transformable::notifyForUpdate()
|
||||
{
|
||||
++currentUpdate;
|
||||
}
|
||||
|
||||
inline const Transformable* Transformable::getParentTransform() const
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
inline void Transformable::multiply(
|
||||
float* dest,
|
||||
const float* src0,
|
||||
const float* src1)
|
||||
{
|
||||
// naive matrix multiplication approach
|
||||
// warning : no self assignment !
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < 4; ++j)
|
||||
{
|
||||
dest[(i << 2) + j] = 0.0f;
|
||||
for (size_t k = 0; k < 4; ++k)
|
||||
dest[(i << 2) + j] += src0[(k << 2) + j] * src1[(i << 2) + k];
|
||||
//++dest;
|
||||
}
|
||||
//++dest;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Transformable::multiply(
|
||||
Vector3D& dest,
|
||||
const Vector3D& v,
|
||||
const float* m)
|
||||
{
|
||||
// warning : no self assignment !
|
||||
// w coord of vectors is implicitely 1
|
||||
dest.x = v.x * m[0] + v.y * m[4] + v.z * m[8] + m[12];
|
||||
dest.y = v.x * m[1] + v.y * m[5] + v.z * m[9] + m[13];
|
||||
dest.z = v.x * m[2] + v.y * m[6] + v.z * m[10] + m[14];
|
||||
}
|
||||
|
||||
inline void Transformable::rotate(
|
||||
Vector3D& dest,
|
||||
const Vector3D& v,
|
||||
const float* m)
|
||||
{
|
||||
// warning : no self assignment !
|
||||
// w coord of vectors is implicitely 1
|
||||
dest.x = v.x * m[0] + v.y * m[4] + v.z * m[8];
|
||||
dest.y = v.x * m[1] + v.y * m[5] + v.z * m[9];
|
||||
dest.z = v.x * m[2] + v.y * m[6] + v.z * m[10];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,570 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_VECTOR3D
|
||||
#define H_SPK_VECTOR3D
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
/**
|
||||
* @class Vector3D
|
||||
* @brief A triplet of coordinates in 3D
|
||||
*
|
||||
* This class offers a set of methods to manipulate 3D points/vectors.<br>
|
||||
* To make the use of 3D points/vectors easier and more intuitive, some operators are overloaded.<br>
|
||||
* Vector3D are the basic primitive used in SPARK to define 3D points/vectors.<br>
|
||||
* <br>
|
||||
* Note that Vector3D coordinates are accessible directly without any setters or getters.
|
||||
*/
|
||||
class SPK_PREFIX Vector3D
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////
|
||||
// Parameters //
|
||||
////////////////
|
||||
|
||||
float x; /**< @brief x coordinate of the vector */
|
||||
float y; /**< @brief y coordinate of the vector */
|
||||
float z; /**< @brief z coordinate of the vector */
|
||||
|
||||
/////////////////
|
||||
// Constructor //
|
||||
/////////////////
|
||||
|
||||
/**
|
||||
* @brief Constructor for the Vector3D
|
||||
* @param x : x coordinate
|
||||
* @param y : y coordinate
|
||||
* @param z : z coordinate
|
||||
*/
|
||||
Vector3D(float x = 0.0f,float y = 0.0f,float z = 0.0f);
|
||||
|
||||
///////////////
|
||||
// Operators //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Adds a Vector3D
|
||||
*
|
||||
* This method performs these operations :<br><i>
|
||||
* x += v.x<br>
|
||||
* y += v.y<br>
|
||||
* z += v.z</i>
|
||||
*
|
||||
* @param v : the Vector3D to add
|
||||
* @return the result Vector3D
|
||||
*/
|
||||
Vector3D& operator+=(const Vector3D& v);
|
||||
|
||||
/**
|
||||
* @brief Substracts a Vector3D
|
||||
*
|
||||
* This method performs these operations :<br><i>
|
||||
* x -= v.x<br>
|
||||
* y -= v.y<br>
|
||||
* z -= v.z</i>
|
||||
*
|
||||
* @param v : the Vector3D to substract
|
||||
* @return the result Vector3D
|
||||
*/
|
||||
Vector3D& operator-=(const Vector3D& v);
|
||||
|
||||
/**
|
||||
* @brief Adds a floating number
|
||||
*
|
||||
* This method performs these operations :<br><i>
|
||||
* x += f<br>
|
||||
* y += f<br>
|
||||
* z += f</i>
|
||||
*
|
||||
* @param f : the number to add
|
||||
* @return the result Vector3D
|
||||
*/
|
||||
Vector3D& operator+=(float f);
|
||||
|
||||
/**
|
||||
* @brief Substracts a floating number
|
||||
*
|
||||
* This method performs these operations :<br><i>
|
||||
* x -= f<br>
|
||||
* y -= f<br>
|
||||
* z -= f</i>
|
||||
*
|
||||
* @param f : the number to substract
|
||||
* @return the result Vector3D
|
||||
*/
|
||||
Vector3D& operator-=(float f);
|
||||
|
||||
/**
|
||||
* @brief Multiplies by a floating number
|
||||
*
|
||||
* This method performs these operations :<br><i>
|
||||
* x *= f<br>
|
||||
* y *= f<br>
|
||||
* z *= f</i>
|
||||
*
|
||||
* @param f : the number to multiply the Vector3D by
|
||||
* @return the result Vector3D
|
||||
*/
|
||||
Vector3D& operator*=(float f);
|
||||
|
||||
/**
|
||||
* @brief Divides by a floating number
|
||||
*
|
||||
* This method performs these operations :<br><i>
|
||||
* x /= f<br>
|
||||
* y /= f<br>
|
||||
* z /= f</i>
|
||||
*
|
||||
* @param f : the number to divide the Vector3D by
|
||||
* @return the result Vector3D
|
||||
*/
|
||||
Vector3D& operator/=(float f);
|
||||
|
||||
/**
|
||||
* @brief Unary - operator of Vector3D
|
||||
*
|
||||
* This method performs that operation :<br><i>
|
||||
* return Vector3D(-x,-y,-z)</i>
|
||||
*
|
||||
* return a Vector3D which is the reverse of this Vector3D
|
||||
*/
|
||||
Vector3D operator-() const;
|
||||
|
||||
/**
|
||||
* @brief Accesses the Vector3D coordinates in an container like fashion
|
||||
*
|
||||
* <ul>
|
||||
* <li>index 0 is X</li>
|
||||
* <li>index 1 is Y</li>
|
||||
* <li>index 2 is Z</li>
|
||||
* </ul>
|
||||
* Note that no check for out of bounds index is performed
|
||||
*
|
||||
* @param index : the index of the coordinate to get (from 0 to 2)
|
||||
* @return : the coordinate value at index
|
||||
* @since 1.03.00
|
||||
*/
|
||||
float& operator[](size_t index);
|
||||
|
||||
/**
|
||||
* @brief Accesses the Vector3D coordinates in an container like fashion
|
||||
*
|
||||
* This is the constant version of operator[](size_t)
|
||||
*
|
||||
* @param index : the index of the coordinate to get (from 0 to 2)
|
||||
* @return : the coordinate value at index
|
||||
* @since 1.03.00
|
||||
*/
|
||||
const float& operator[](size_t index) const;
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets the values of the Vector3D
|
||||
* @param x : x coordinate
|
||||
* @param y : y coordinate
|
||||
* @param z : z coordinate
|
||||
*/
|
||||
void set(float x,float y,float z = 0.0f);
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Gets the square norm of the Vector3D
|
||||
*
|
||||
* the square norm is defined as <i>x * x + y * y + z * z</i>.
|
||||
* This method is faster than getNorm() and should be used when possible.
|
||||
*
|
||||
* @return the square norm of the Vector3D
|
||||
*/
|
||||
float getSqrNorm() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the norm of the Vector3D
|
||||
*
|
||||
* the norm is defined as <i>sqrt(x * x + y * y + z * z)</i>.
|
||||
*
|
||||
* @return the norm of the Vector3D
|
||||
*/
|
||||
float getNorm() const;
|
||||
|
||||
/**
|
||||
* @brief Normalizes the Vector3D
|
||||
*
|
||||
* This method performs these operations :<br><i>
|
||||
* x /= |v|<br>
|
||||
* y /= |v|<br>
|
||||
* z /= |v|<br></i>
|
||||
* Note that if the norm is equal to 0, nothing happens and false is returned.
|
||||
*
|
||||
* @return true if this Vector3D can be normalized, false otherwise
|
||||
*/
|
||||
bool normalize();
|
||||
|
||||
/**
|
||||
* @brief Reverts the Vector3D
|
||||
*
|
||||
* This method performs these operations :<br><i>
|
||||
* x = -x<br>
|
||||
* y = -y<br>
|
||||
* z = -z</i>
|
||||
*/
|
||||
void revert();
|
||||
|
||||
/**
|
||||
* @brief Sets this Vector3D to its absolute values
|
||||
*
|
||||
* This method performs these operations :<br><i>
|
||||
* x = abs(x)<br>
|
||||
* y = abs(y)<br>
|
||||
* z = abs(z)</i>
|
||||
*
|
||||
* @since 1.02.00
|
||||
*/
|
||||
void abs();
|
||||
|
||||
/**
|
||||
* @brief Computes the cross product between v and the vector3D and store the result in the vector3D
|
||||
* @param v : the vector3D used to compute the cross product (*this x v)
|
||||
*/
|
||||
void crossProduct(const Vector3D& v);
|
||||
};
|
||||
|
||||
////////////////////////
|
||||
// External operators //
|
||||
////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Adds two Vector3D
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = v0.x + v1.x<br>
|
||||
* result.y = v0.y + v1.y<br>
|
||||
* result.z = v0.z + v1.z</i>
|
||||
*
|
||||
* @param v0 : the first vector3D
|
||||
* @param v1 : the second vector3D
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator+(const Vector3D& v0,const Vector3D& v1);
|
||||
|
||||
/**
|
||||
* @brief Substracts two Vector3D
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = v0.x - v1.x<br>
|
||||
* result.y = v0.y - v1.y<br>
|
||||
* result.z = v0.z - v1.z</i>
|
||||
*
|
||||
* @param v0 : the first vector3D
|
||||
* @param v1 : the second vector3D
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator-(const Vector3D& v0,const Vector3D& v1);
|
||||
|
||||
/**
|
||||
* @brief Adds a Vector3D and a float
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = v.x + f<br>
|
||||
* result.y = v.y + f<br>
|
||||
* result.z = v.z + f</i>
|
||||
*
|
||||
* @param v : the vector3D
|
||||
* @param f : the floating number
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator+(const Vector3D& v,float f);
|
||||
|
||||
/**
|
||||
* @brief Adds a float and a Vector3D
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = f + v.x<br>
|
||||
* result.y = f + v.y<br>
|
||||
* result.z = f + v.z</i>
|
||||
*
|
||||
* @param f : the floating number
|
||||
* @param v : the vector3D
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator+(float f,const Vector3D& v);
|
||||
|
||||
/**
|
||||
* @brief Substracts a float to a Vector3D
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = v.x - f<br>
|
||||
* result.y = v.y - f<br>
|
||||
* result.z = v.z - f</i>
|
||||
*
|
||||
* @param v : the vector3D
|
||||
* @param f : the floating number
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator-(const Vector3D& v,float f);
|
||||
|
||||
/**
|
||||
* @brief Substracts a Vector3D to a float
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = f - v.x<br>
|
||||
* result.y = f - v.y<br>
|
||||
* result.z = f - v.z</i>
|
||||
*
|
||||
* @param f : the floating number
|
||||
* @param v : the vector3D
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator-(float f,const Vector3D& v);
|
||||
|
||||
/**
|
||||
* @brief Multiplies a Vector3D by a float
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = v.x * f<br>
|
||||
* result.y = v.y * f<br>
|
||||
* result.z = v.z * f</i>
|
||||
*
|
||||
* @param v : the vector3D
|
||||
* @param f : the floating number
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator*(const Vector3D& v,float f);
|
||||
|
||||
/**
|
||||
* @brief Multiplies a float by a Vector3D
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = f * v.x<br>
|
||||
* result.y = f * v.y<br>
|
||||
* result.z = f * v.z</i>
|
||||
*
|
||||
* @param f : the floating number
|
||||
* @param v : the vector3D
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator*(float f,const Vector3D& v);
|
||||
|
||||
/**
|
||||
* @brief Divides a Vector3D by a float
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = v.x / f<br>
|
||||
* result.y = v.y / f<br>
|
||||
* result.z = v.z / f</i>
|
||||
*
|
||||
* @param v : the vector3D
|
||||
* @param f : the floating number
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator/(const Vector3D& v,float f);
|
||||
|
||||
/**
|
||||
* @brief Divides a float by a Vector3D
|
||||
*
|
||||
* This function performs these operations :<br><i>
|
||||
* result.x = f / v.x<br>
|
||||
* result.y = f / v.y<br>
|
||||
* result.z = f / v.z</i>
|
||||
*
|
||||
* @param f : the floating number
|
||||
* @param v : the vector3D
|
||||
* @return the result vector3D
|
||||
*/
|
||||
Vector3D operator/(float f,const Vector3D& v);
|
||||
|
||||
/**
|
||||
* @brief Tests whether 2 Vector3D are equal
|
||||
* @param v0 : the first Vector3D to compare
|
||||
* @param v1 : the second Vector3D to compare
|
||||
* @return true if the Vector3D are equal, false if not
|
||||
* @since 1.01.01
|
||||
*/
|
||||
bool operator==(const Vector3D& v0,const Vector3D& v1);
|
||||
|
||||
/**
|
||||
* @brief Tests whether 2 Vector3D are different
|
||||
* @param v0 : the first Vector3D to compare
|
||||
* @param v1 : the second Vector3D to compare
|
||||
* @return true if the Vector3D are different, false if not
|
||||
* @since 1.01.01
|
||||
*/
|
||||
bool operator!=(const Vector3D& v0,const Vector3D& v1);
|
||||
|
||||
/**
|
||||
* @brief Writes a Vector3D on an output stream
|
||||
*
|
||||
* The Vector3D is written that way : <i>(x,y,z)</i>
|
||||
*
|
||||
* @param s : the output stream where to write
|
||||
* @param v : the Vector3D to write to the output stream
|
||||
* @return the output stream
|
||||
* @since 1.01.01
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& s,const Vector3D& v);
|
||||
|
||||
////////////////////////
|
||||
// External functions //
|
||||
////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Returns the square distance between two Vector3D
|
||||
*
|
||||
* This method is faster than getDist(const Vector3D&,const Vector3D&) and should be used when possible.
|
||||
*
|
||||
* @param v0 : the first Vector3D
|
||||
* @param v1 : the second Vector3D
|
||||
* @return the square distance between the two Vector3D
|
||||
*/
|
||||
extern SPK_PREFIX float getSqrDist(const Vector3D& v0,const Vector3D& v1);
|
||||
|
||||
/**
|
||||
* @brief Returns the distance between two Vector3D
|
||||
* @param v0 : the first Vector3D
|
||||
* @param v1 : the second Vector3D
|
||||
* @return the distance between the two Vector3D
|
||||
*/
|
||||
extern SPK_PREFIX float getDist(const Vector3D& v0,const Vector3D& v1);
|
||||
|
||||
/**
|
||||
* @brief Returns the dot product between two Vector3D
|
||||
* @param v0 : the first Vector3D
|
||||
* @param v1 : the second Vector3D
|
||||
* @return the dot product (v0 . v1)
|
||||
*/
|
||||
float dotProduct(const Vector3D& v0,const Vector3D& v1);
|
||||
|
||||
/**
|
||||
* @brief Returns the cross product between two Vector3D
|
||||
* @param v0 : the first Vector3D
|
||||
* @param v1 : the second Vector3D
|
||||
* @return the cross product (v0 x v1)
|
||||
*/
|
||||
extern SPK_PREFIX Vector3D crossProduct(const Vector3D& v0,const Vector3D& v1);
|
||||
|
||||
/**
|
||||
* @brief Computes the cross product between two Vector3D and stores the result in the Vector3D result
|
||||
* @param v0 : the first Vector3D
|
||||
* @param v1 : the second Vector3D
|
||||
* @param result : the Vector3D where to store the cross product (v0 x v1)
|
||||
*/
|
||||
extern SPK_PREFIX void crossProduct(const Vector3D& v0,const Vector3D& v1,Vector3D& result);
|
||||
|
||||
|
||||
inline float Vector3D::getSqrNorm() const
|
||||
{
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
inline float Vector3D::getNorm() const
|
||||
{
|
||||
return std::sqrt(getSqrNorm());
|
||||
}
|
||||
|
||||
inline Vector3D Vector3D::operator-() const
|
||||
{
|
||||
return Vector3D(-x,-y,-z);
|
||||
}
|
||||
|
||||
inline float dotProduct(const Vector3D& v0,const Vector3D& v1)
|
||||
{
|
||||
return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
|
||||
}
|
||||
|
||||
inline Vector3D operator+(const Vector3D& v0,const Vector3D& v1)
|
||||
{
|
||||
return Vector3D(v0.x + v1.x,v0.y + v1.y,v0.z + v1.z);
|
||||
}
|
||||
|
||||
inline Vector3D operator-(const Vector3D& v0,const Vector3D& v1)
|
||||
{
|
||||
return Vector3D(v0.x - v1.x,v0.y - v1.y,v0.z - v1.z);
|
||||
}
|
||||
|
||||
inline Vector3D operator+(const Vector3D& v,float f)
|
||||
{
|
||||
return Vector3D(v.x + f,v.y + f,v.z + f);
|
||||
}
|
||||
|
||||
inline Vector3D operator+(float f,const Vector3D& v)
|
||||
{
|
||||
return Vector3D(v.x + f,v.y + f,v.z + f);
|
||||
}
|
||||
|
||||
inline Vector3D operator-(const Vector3D& v,float f)
|
||||
{
|
||||
return Vector3D(v.x - f,v.y - f,v.z - f);
|
||||
}
|
||||
|
||||
inline Vector3D operator-(float f,const Vector3D& v)
|
||||
{
|
||||
return Vector3D(v.x - f,v.y - f,v.z - f);
|
||||
}
|
||||
|
||||
inline Vector3D operator*(const Vector3D& v,float f)
|
||||
{
|
||||
return Vector3D(v.x * f,v.y * f,v.z * f);
|
||||
}
|
||||
|
||||
inline Vector3D operator*(float f,const Vector3D& v)
|
||||
{
|
||||
return Vector3D(v.x * f,v.y * f,v.z * f);
|
||||
}
|
||||
|
||||
inline Vector3D operator/(const Vector3D& v,float f)
|
||||
{
|
||||
float mul = 1.0f / f;
|
||||
return Vector3D(v.x * mul,v.y * mul,v.z * mul);
|
||||
}
|
||||
|
||||
inline Vector3D operator/(float f,const Vector3D& v)
|
||||
{
|
||||
return Vector3D(f / v.x,f / v.y,f / v.z);
|
||||
}
|
||||
|
||||
inline bool operator==(const Vector3D& v0,const Vector3D& v1)
|
||||
{
|
||||
return (v0.x == v1.x)&&(v0.y == v1.y)&&(v0.z == v1.z);
|
||||
}
|
||||
|
||||
inline bool operator!=(const Vector3D& v0,const Vector3D& v1)
|
||||
{
|
||||
return (v0.x != v1.x)||(v0.y != v1.y)||(v0.z != v1.z);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s,const Vector3D& v)
|
||||
{
|
||||
return s << '(' << v.x << ',' << v.y << ',' << v.z << ')';
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,197 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_ZONE
|
||||
#define H_SPK_ZONE
|
||||
|
||||
#include "Core/SPK_DEF.h"
|
||||
#include "Core/SPK_Registerable.h"
|
||||
#include "Core/SPK_Transformable.h"
|
||||
#include "Core/SPK_Vector3D.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
class Particle;
|
||||
|
||||
/**
|
||||
* @class Zone
|
||||
* @brief An abstract class that defines a zone in space
|
||||
*
|
||||
* A Zone is used in SPARK to :
|
||||
* <ul>
|
||||
* <li>define the area of an Emitter</li>
|
||||
* <li>define the area of a Modifier</li>
|
||||
* </ul>
|
||||
*/
|
||||
class SPK_PREFIX Zone : public Registerable, public Transformable
|
||||
{
|
||||
public :
|
||||
|
||||
/////////////////
|
||||
// Constructor //
|
||||
/////////////////
|
||||
|
||||
/**
|
||||
* @brief Default constructor for Zone
|
||||
* @param position : the position of the Zone
|
||||
*/
|
||||
Zone(const Vector3D& position = Vector3D());
|
||||
|
||||
////////////////
|
||||
// Destructor //
|
||||
////////////////
|
||||
|
||||
/** @brief Destructor of Zone */
|
||||
virtual ~Zone() {}
|
||||
|
||||
////////////
|
||||
// Setter //
|
||||
////////////
|
||||
|
||||
/**
|
||||
* @brief Sets the position of this Zone
|
||||
* @param v : the position of this Zone
|
||||
*/
|
||||
virtual void setPosition(const Vector3D& v);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Gets the position of this Zone
|
||||
* @return the position of this Zone
|
||||
*/
|
||||
const Vector3D& getPosition() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the transformed position of this Zone
|
||||
* @return the transformed position of this Zone
|
||||
* @since 1.03.00
|
||||
*/
|
||||
const Vector3D& getTransformedPosition() const;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @brief Randomly generates a position inside this Zone for a given Particle
|
||||
* @param particle : the Particle whose position will be generated
|
||||
* @param full : true to generate a position in the whole volume of this Zone, false to generate a position only at borders
|
||||
*/
|
||||
virtual void generatePosition(Particle& particle,bool full) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Checks whether a point is within the Zone
|
||||
* @param point : the point to check
|
||||
* @return true if the point is within the Zone, false otherwise
|
||||
*/
|
||||
virtual bool contains(const Vector3D& point) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Checks whether a line intersects the Zone
|
||||
*
|
||||
* The intersection is computed only if the Vector3D* intersection is not NULL.<br>
|
||||
* The normal is computed if the Vector3D* normal AND intersection are not NULL.
|
||||
*
|
||||
* @param v0 : start of the line
|
||||
* @param v1 : end of the line
|
||||
* @param intersection : the Vector3D where the intersection will be stored, NULL not to compute the intersection
|
||||
* @param normal : the Vector3D where the normal will be stored, NULL not to compute the normal
|
||||
* @return true if the line intersects with the Zone, false otherwise
|
||||
*/
|
||||
virtual bool intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Moves a point at the border of the Zone
|
||||
* @param point : the point that will be moved to the border of the Zone
|
||||
* @param inside : true to move the point inside the Zone of APPROXIMATION_VALUE, false to move it outside of APPROXIMATION_VALUE
|
||||
*/
|
||||
virtual void moveAtBorder(Vector3D& point,bool inside) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Computes the normal for the point
|
||||
* @param point : the point from where the normal is computed
|
||||
* @return the normal vector
|
||||
* @since 1.02.00
|
||||
*/
|
||||
virtual Vector3D computeNormal(const Vector3D& point) const = 0;
|
||||
|
||||
protected :
|
||||
|
||||
/** @brief Value used for approximation */
|
||||
static const float APPROXIMATION_VALUE;
|
||||
|
||||
/**
|
||||
* @brief A helper static method to normalize a Vector3D
|
||||
*
|
||||
* If the Vector3D is NULL, a random normal Vector3D is set.<br>
|
||||
* The randomness is guaranteed to be uniformely distributed.
|
||||
*
|
||||
* @param v : the Vector3D to normalize or randomize if not normalizable
|
||||
* @since 1.03.00
|
||||
*/
|
||||
static void normalizeOrRandomize(Vector3D& v);
|
||||
|
||||
virtual void innerUpdateTransform();
|
||||
|
||||
private :
|
||||
|
||||
Vector3D position;
|
||||
Vector3D tPosition; // transformed position
|
||||
};
|
||||
|
||||
|
||||
inline void Zone::setPosition(const Vector3D& v)
|
||||
{
|
||||
position = tPosition = v;
|
||||
notifyForUpdate();
|
||||
}
|
||||
|
||||
inline const Vector3D& Zone::getPosition() const
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
inline const Vector3D& Zone::getTransformedPosition() const
|
||||
{
|
||||
return tPosition;
|
||||
}
|
||||
|
||||
inline void Zone::normalizeOrRandomize(Vector3D& v)
|
||||
{
|
||||
while(!v.normalize())
|
||||
{
|
||||
do v = Vector3D(random(-1.0f,1.0f),random(-1.0f,1.0f),random(-1.0f,1.0f));
|
||||
while (v.getSqrNorm() > 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Zone::innerUpdateTransform()
|
||||
{
|
||||
transformPos(tPosition,position);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,146 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_NORMALEMITTER
|
||||
#define H_SPK_NORMALEMITTER
|
||||
|
||||
#include "Core/SPK_Emitter.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
/**
|
||||
* @class NormalEmitter
|
||||
* @brief An Emitter that emits particles following a Zone normals
|
||||
*
|
||||
* The Zone used to derive the direction of emission can either be the Emitter Zone
|
||||
* or another Zone that can be set with setNormalZone(Zone*).<br>
|
||||
* If the normal zone is NULL the emitter Zone is used.
|
||||
*
|
||||
* @since 1.02.00
|
||||
*/
|
||||
class SPK_PREFIX NormalEmitter : public Emitter
|
||||
{
|
||||
SPK_IMPLEMENT_REGISTERABLE(NormalEmitter)
|
||||
|
||||
public :
|
||||
|
||||
//////////////////
|
||||
// Constructors //
|
||||
//////////////////
|
||||
|
||||
/**
|
||||
* @brief Constructor of NormalEmitter
|
||||
* @param normalZone : the Zone used to compute normals (NULL to used the Emitter Zone)
|
||||
* @param inverted : true to invert the normals, false otherwise
|
||||
*/
|
||||
NormalEmitter(Zone* normalZone = NULL,bool inverted = false);
|
||||
|
||||
/**
|
||||
* @brief Creates and registers a new NormalEmitter
|
||||
* @param normalZone : the Zone used to compute normals (NULL to used the Emitter Zone)
|
||||
* @param inverted : true to invert the normals, false otherwise
|
||||
* @return A new registered NormalEmitter
|
||||
* @since 1.04.00
|
||||
*/
|
||||
static NormalEmitter* create(Zone* normalZone = NULL,bool inverted = false);
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets whether normals are inverted or not
|
||||
* @param inverted true to use inverted normals, false not to
|
||||
*/
|
||||
void setInverted(bool inverted);
|
||||
|
||||
/**
|
||||
* @brief the Zone used to compute normals
|
||||
*
|
||||
* Note that if the normal zone is NULL, the Emitter Zone is used.
|
||||
*
|
||||
* @param zone : the Zone used to compute normals (NULL to used the Emitter Zone)
|
||||
*/
|
||||
void setNormalZone(Zone* zone);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Tells whether normals are inverted for this NormalEmitter
|
||||
* @return true if normals are inverted, false if not
|
||||
*/
|
||||
bool isInverted() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the normal Zone of this NormalEmitter
|
||||
* @return the normal Zone of this NormalEmitter
|
||||
*/
|
||||
Zone* getNormalZone() const;
|
||||
|
||||
///////////////
|
||||
// Interface //
|
||||
///////////////
|
||||
|
||||
virtual Registerable* findByName(const std::string& name);
|
||||
|
||||
protected :
|
||||
|
||||
virtual void registerChildren(bool registerAll);
|
||||
virtual void copyChildren(const Registerable& object,bool createBase);
|
||||
virtual void destroyChildren(bool keepChildren);
|
||||
|
||||
private :
|
||||
|
||||
bool inverted;
|
||||
Zone* normalZone;
|
||||
|
||||
virtual void generateVelocity(Particle& particle,float speed) const;
|
||||
};
|
||||
|
||||
|
||||
inline NormalEmitter* NormalEmitter::create(Zone* normalZone,bool inverted)
|
||||
{
|
||||
NormalEmitter* obj = new NormalEmitter(normalZone,inverted);
|
||||
registerObject(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
inline void NormalEmitter::setInverted(bool inverted)
|
||||
{
|
||||
this->inverted = inverted;
|
||||
}
|
||||
|
||||
inline bool NormalEmitter::isInverted() const
|
||||
{
|
||||
return inverted;
|
||||
}
|
||||
|
||||
inline Zone* NormalEmitter::getNormalZone() const
|
||||
{
|
||||
return normalZone;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,63 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_RANDOMEMITTER
|
||||
#define H_SPK_RANDOMEMITTER
|
||||
|
||||
#include "Core/SPK_Emitter.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
/**
|
||||
* @class RandomEmitter
|
||||
* @brief An Emitter that emits in a random direction
|
||||
* @since 1.02.00
|
||||
*/
|
||||
class SPK_PREFIX RandomEmitter : public Emitter
|
||||
{
|
||||
SPK_IMPLEMENT_REGISTERABLE(RandomEmitter)
|
||||
|
||||
public :
|
||||
|
||||
/**
|
||||
* @brief Creates and registers a new RandomEmitter
|
||||
* @return A new registered RandomEmitter
|
||||
* @since 1.04.00
|
||||
*/
|
||||
static RandomEmitter* create();
|
||||
|
||||
private :
|
||||
|
||||
virtual void generateVelocity(Particle& particle,float speed) const;
|
||||
};
|
||||
|
||||
|
||||
inline RandomEmitter* RandomEmitter::create()
|
||||
{
|
||||
RandomEmitter* obj = new RandomEmitter;
|
||||
registerObject(obj);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,183 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// SPARK particle engine //
|
||||
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||||
// //
|
||||
// This software is provided 'as-is', without any express or implied //
|
||||
// warranty. In no event will the authors be held liable for any damages //
|
||||
// arising from the use of this software. //
|
||||
// //
|
||||
// Permission is granted to anyone to use this software for any purpose, //
|
||||
// including commercial applications, and to alter it and redistribute it //
|
||||
// freely, subject to the following restrictions: //
|
||||
// //
|
||||
// 1. The origin of this software must not be misrepresented; you must not //
|
||||
// claim that you wrote the original software. If you use this software //
|
||||
// in a product, an acknowledgment in the product documentation would be //
|
||||
// appreciated but is not required. //
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||||
// misrepresented as being the original software. //
|
||||
// 3. This notice may not be removed or altered from any source distribution. //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef H_SPK_SPHERICEMITTER
|
||||
#define H_SPK_SPHERICEMITTER
|
||||
|
||||
#include "Core/SPK_Emitter.h"
|
||||
|
||||
|
||||
namespace SPK
|
||||
{
|
||||
/**
|
||||
* @class SphericEmitter
|
||||
* @brief An Emitter that emits particles in a portion of sphere
|
||||
*
|
||||
* This Emitter can emit particles in a spheric way.
|
||||
* To do that 2 angles and a direction Vector3D can be parametered :
|
||||
* <ul>
|
||||
* <li>The direction Vector3D defines the direction of the emitter.</li>
|
||||
* <li>The angles defines the area in between which wil be emitted the particles velocities.</li>
|
||||
* </ul>
|
||||
* Here are a few examples :
|
||||
* <ul>
|
||||
* <li><i>0 and 2 * PI</i> will define a complete sphere ie equivalent to a RandomEmitter</li>
|
||||
* <li><i>0 and 0</i> will define a Emitter equivalent to a StraightEmitter</li>
|
||||
* <li><i>PI and PI</i> will define a disk</li>
|
||||
* <li><i>PI / 2 and PI / 2</i> will define a Cone of angle PI / 2</li>
|
||||
* <li>...</li>
|
||||
* </ul>
|
||||
*/
|
||||
class SPK_PREFIX SphericEmitter : public Emitter
|
||||
{
|
||||
SPK_IMPLEMENT_REGISTERABLE(SphericEmitter)
|
||||
|
||||
public :
|
||||
|
||||
/////////////////
|
||||
// Constructor //
|
||||
/////////////////
|
||||
|
||||
/**
|
||||
* @brief Constructor of SphericEmitter
|
||||
* @param direction : the direction of the SphericEmitter
|
||||
* @param angleA : the first angle in radians of the SphericEmitter
|
||||
* @param angleB : the second angle in radians of the SphericEmitter
|
||||
*/
|
||||
SphericEmitter(const Vector3D& direction = Vector3D(0.0f,0.0f,-1.0f),float angleA = 0.0f,float angleB = 0.0f);
|
||||
|
||||
/**
|
||||
* @brief Creates and registers a new SphericEmitter
|
||||
* @param direction : the direction of the SphericEmitter
|
||||
* @param angleA : the first angle in radians of the SphericEmitter
|
||||
* @param angleB : the second angle in radians of the SphericEmitter
|
||||
* @since 1.04.00
|
||||
*/
|
||||
static SphericEmitter* create(const Vector3D& direction = Vector3D(0.0f,0.0f,-1.0f),float angleA = 0.0f,float angleB = 0.0f);
|
||||
|
||||
/////////////
|
||||
// Setters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Sets the direction of this SphericEmitter
|
||||
*
|
||||
* Note that it is not necessary to provide a normalized Vector3D.
|
||||
* This Vector3D only indicates a direction, its norm does not matter.
|
||||
*
|
||||
* @param direction : the direction of this SphericEmitter
|
||||
*/
|
||||
void setDirection(const Vector3D& direction);
|
||||
|
||||
/**
|
||||
* @brief Sets the angles of this SphericEmitter
|
||||
*
|
||||
* Note that angles are clamped between 0 and 2 * PI
|
||||
* AngleA does not have to be inferior to angleB, it has no importance as angles are sorted within the method.
|
||||
*
|
||||
* @param angleA : the first angle in radians of this SphericEmitter
|
||||
* @param angleB : the second angle in radians of this SphericEmitter
|
||||
*/
|
||||
void setAngles(float angleA,float angleB);
|
||||
|
||||
/////////////
|
||||
// Getters //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Gets the direction of this SphericEmitter
|
||||
* @return the direction of this SphericEmitter
|
||||
*/
|
||||
const Vector3D& getDirection() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the direction of this SphericEmitter
|
||||
* @return the direction of this SphericEmitter
|
||||
*/
|
||||
const Vector3D& getTransformedDirection() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the minimum angle of this SphericEmitter
|
||||
* @return the minimum angle of this SphericEmitter
|
||||
*/
|
||||
float getAngleMin() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the maximum angle of this SphericEmitter
|
||||
* @return the maximum angle of this SphericEmitter
|
||||
*/
|
||||
float getAngleMax() const;
|
||||
|
||||
protected :
|
||||
|
||||
virtual void innerUpdateTransform();
|
||||
|
||||
private :
|
||||
|
||||
static const float PI;
|
||||
|
||||
Vector3D direction;
|
||||
Vector3D tDirection; // transformed direction
|
||||
|
||||
float angleMin;
|
||||
float angleMax;
|
||||
|
||||
float cosAngleMin;
|
||||
float cosAngleMax;
|
||||
|
||||
float matrix[9];
|
||||
|
||||
void computeMatrix();
|
||||
|
||||
virtual void generateVelocity(Particle& particle,float speed) const;
|
||||
};
|
||||
|
||||
|
||||
inline SphericEmitter* SphericEmitter::create(const Vector3D& direction,float angleA,float angleB)
|
||||
{
|
||||
SphericEmitter* obj = new SphericEmitter(direction,angleA,angleB);
|
||||
registerObject(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
inline const Vector3D& SphericEmitter::getDirection() const
|
||||
{
|
||||
return direction;
|
||||
}
|
||||
|
||||
inline const Vector3D& SphericEmitter::getTransformedDirection() const
|
||||
{
|
||||
return tDirection;
|
||||
}
|
||||
|
||||
inline float SphericEmitter::getAngleMin() const
|
||||
{
|
||||
return angleMin;
|
||||
}
|
||||
|
||||
inline float SphericEmitter::getAngleMax() const
|
||||
{
|
||||
return angleMax;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user