diff --git a/Core/Contents/CMakeLists.txt b/Core/Contents/CMakeLists.txt index 1b13a78c9..caa69b82c 100644 --- a/Core/Contents/CMakeLists.txt +++ b/Core/Contents/CMakeLists.txt @@ -19,7 +19,7 @@ SET(polycore_SRCS Source/PolyEventHandler.cpp Source/PolyFixedShader.cpp Source/PolyFont.cpp - Source/PolyFontGlyphSheet.cpp + Source/PolyFontGlyphSheet.cpp Source/PolyFontManager.cpp Source/PolyGLCubemap.cpp Source/PolyGLRenderer.cpp @@ -40,6 +40,8 @@ SET(polycore_SRCS Source/PolyObject.cpp Source/PolyParticleEmitter.cpp Source/PolyPerlin.cpp + Source/PolyPlugin.cpp + Source/PolyPluginManager.cpp Source/PolyQuaternion.cpp Source/PolyQuaternionCurve.cpp Source/PolyRectangle.cpp @@ -62,8 +64,8 @@ SET(polycore_SRCS Source/PolySound.cpp Source/PolySoundManager.cpp Source/PolyString.cpp - Source/PolyTextMesh.cpp - Source/PolyTexture.cpp + Source/PolyTextMesh.cpp + Source/PolyTexture.cpp Source/PolyThreaded.cpp Source/PolyTimer.cpp Source/PolyTimerManager.cpp @@ -105,7 +107,7 @@ SET(polycore_HDRS Include/PolyEventHandler.h Include/PolyFixedShader.h Include/PolyFont.h - Include/PolyFontGlyphSheet.h + Include/PolyFontGlyphSheet.h Include/PolyFontManager.h Include/PolyGLCubemap.h Include/PolyGLHeaders.h @@ -129,6 +131,8 @@ SET(polycore_HDRS Include/PolyObject.h Include/PolyParticleEmitter.h Include/PolyPerlin.h + Include/PolyPlugin.h + Include/PolyPluginManager.h Include/PolyQuaternionCurve.h Include/PolyQuaternion.h Include/PolyRectangle.h diff --git a/Core/Contents/Include/PolyCoreServices.h b/Core/Contents/Include/PolyCoreServices.h index b79f0f8f4..b21a6585e 100755 --- a/Core/Contents/Include/PolyCoreServices.h +++ b/Core/Contents/Include/PolyCoreServices.h @@ -38,10 +38,11 @@ namespace Polycode { class TweenManager; class ResourceManager; class SoundManager; + class PluginManager; class Core; class CoreMutex; class Logger; - + /** * Global services singleton. CoreServices instantiates and provides global Singleton access to all of the main manager classes in Polycode as well as the Renderer and Config classes. */ @@ -141,6 +142,13 @@ namespace Polycode { */ FontManager *getFontManager(); + /** + * Returns the plugin manager. The plugin manager is responsible for loading and managing plugins. + * @return Plugin Manager + * @see PluginManager + */ + PluginManager *getPluginManager(); + /** * Returns the logger. It can log messages and broadcast them to listeners. */ @@ -181,6 +189,7 @@ namespace Polycode { ResourceManager *resourceManager; SoundManager *soundManager; FontManager *fontManager; + PluginManager *pluginManager; Renderer *renderer; }; diff --git a/Core/Contents/Include/PolyEntity.h b/Core/Contents/Include/PolyEntity.h index 28e1fe2a2..5d13e0e44 100755 --- a/Core/Contents/Include/PolyEntity.h +++ b/Core/Contents/Include/PolyEntity.h @@ -30,11 +30,13 @@ #include "PolyRectangle.h" #include "PolyRay.h" #include "PolyEventDispatcher.h" +#include "PolyPlugin.h" #include namespace Polycode { class Renderer; + class ResourcePool; class _PolyExport MouseEventResult { public: @@ -42,10 +44,23 @@ namespace Polycode { bool blocked; }; - class _PolyExport EntityProp { - public: - String propName; - String propValue; + class _PolyExport EntityProp : public PolyBase { public: + EntityProp(const String& name, const unsigned int& type = EntityProp::PROP_STRING); + + int type; + String name; + + String stringVal; + Number numberVal; + int intVal; + bool boolVal; + //std::vector arrayVal; + + static const unsigned int PROP_NUMBER = 0; + static const unsigned int PROP_INT = 1; + static const unsigned int PROP_BOOL = 2; + static const unsigned int PROP_STRING = 3; + static const unsigned int PROP_ARRAY = 4; }; class _PolyExport AABB { @@ -718,19 +733,81 @@ namespace Polycode { std::vector getEntitiesByLayerID(unsigned char layerID, bool recursive) const; /** - * Returns custom string dictionary property of the entity based on the property name. + * Returns int property of the entity based on the property name. * @param Property name to look up. - * @return String property for specified property name or "null" if this property doesn't exist. + * @return int property for specified property name or false if this property doesn't exist. */ - String getEntityProp(const String& propName); - - /** - * Sets the entity property for a specified property name in the entity's custom property dictionary. + int getEntityPropIntByName (const String& propName) const; + + /** + * Returns Number property of the entity based on the property name. + * @param Property name to look up. + * @return Number property for specified property name or 0 if this property doesn't exist. + */ + Number getEntityPropNumberByName (const String& propName) const; + + /** + * Returns Bool property of the entity based on the property name. + * @param Property name to look up. + * @return Bool property for specified property name or -1 if this property doesn't exist. + */ + bool getEntityPropBoolByName (const String& propName) const; + + /** + * Returns String property of the entity based on the property name. + * @param Property name to look up. + * @return String property for specified property name or "null" if this property doesn't exist. + */ + String getEntityPropStringByName (const String& propName) const; + + /** + * Returns vector of EntityProp property of the entity based on the property name. + * @param Property name to look up. + * @return vector of EntityProp property for specified property name - is empty if this property doesn't exist. + */ + //std::vector getEntityPropArrayByName(const String& propName) const; + + /** + * Sets the entity property for a specified property name. * @param propName Property name to set. - * @param propValue Value to set for the specified property name. + * @param propVal String to set for the specified property name. */ - void setEntityProp(const String& propName, const String& propValue); + void setEntityProp(const String& propName, const String& propVal); + + /** + * Sets the entity property for a specified property name. + * @param propName Property name to set. + * @param propVal int to set for the specified property name. + */ + void setEntityProp(const String& propName, const int& propVal); + + /** + * Sets the entity property for a specified property name. + * @param propName Property name to set. + * @param propVal Number to set for the specified property name. + */ + void setEntityProp(const String& propName, const Number& propVal); + + /** + * Sets the entity property for a specified property name. + * @param propName Property name to set. + * @param propVal bool to set for the specified property name. + */ + void setEntityProp(const String& propName, const bool& propVal); + /** + * Sets the entity property for a specified property name. + * @param propName Property name to set. + * @param propVal vector of EntityProp* to set for the specified property name. + */ + //void setEntityProp(const String& propName, std::vector propVal); + + void setEntityProp(EntityProp* prop); + + bool isRequiredPlugin(const String& pluginName) const; + void addPluginByName(const String& name, ResourcePool *resourcePool = NULL); + void removePluginByName(const String& name); + /** * If set to true, the y position of the entity matrix will be multiplied by -1.0, inverting its Y-axis coordinate system. */ @@ -895,8 +972,8 @@ namespace Polycode { */ unsigned char layerID; - std::vector entityProps; - + std::vector entityProps; + std::vector requiredPlugins; protected: diff --git a/Core/Contents/Include/PolyPlugin.h b/Core/Contents/Include/PolyPlugin.h new file mode 100644 index 000000000..640b53dbc --- /dev/null +++ b/Core/Contents/Include/PolyPlugin.h @@ -0,0 +1,95 @@ +/* +Copyright (C) 2014 by Joachim Meyer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once +#include "PolyGlobals.h" +#include "PolyString.h" +#include "PolyResource.h" + +namespace Polycode { + class ObjectEntry; + + class _PolyExport Prop : public PolyBase { + public: + Prop(const String& name, const int type = Prop::PROP_STRING); + Prop(ObjectEntry *entry); + ~Prop(); + + Prop *loadPropFromEntry(ObjectEntry* entry); + + int type; + String name; + int value; + + std::vector children; + + static const int PROP_VECTOR3 = 0; + static const int PROP_VECTOR2 = 1; + static const int PROP_SLIDER = 2; + static const int PROP_BUTTON = 3; + static const int PROP_NUMBER = 4; + static const int PROP_TARGET_BINDING = 5; + static const int PROP_RENDER_TARGET = 6; + static const int PROP_SHADER_PASS = 7; + static const int PROP_REMOVABLE_STRING = 8; + static const int PROP_LAYER = 9; + static const int PROP_CUSTOM = 10; + static const int PROP_STRING = 11; + static const int PROP_COLOR = 12; + static const int PROP_COMBO = 13; + static const int PROP_BOOL = 14; + static const int PROP_SOUND = 15; + static const int PROP_BEZIER_RGBA_CURVE = 16; + static const int PROP_BEZIER_CURVE = 17; + static const int PROP_MATERIAL = 18; + static const int PROP_MATERIAL_PREVIEW = 19; + static const int PROP_TEXTURE = 20; + static const int PROP_SCENE_SPRITE = 21; + static const int PROP_SCENE_ENTITY_INSTANCE = 22; }; + + class _PolyExport Plugin : public Resource { + public: + Plugin(const String& name); + Plugin(ObjectEntry *entry); + ~Plugin(); + + Plugin* loadPluginFromEntry(ObjectEntry *entry); + + void setProp(Prop* prop); + + void removeProp(Prop* prop); + void removeProp(const String& propName); + + std::vector getProps() const; + unsigned int getNumProps() const; + + unsigned int pluginType; + + static const unsigned int PLUGIN_ENTITY = 0; + + String ext; + String author; + + protected: + std::vector props; + }; +} \ No newline at end of file diff --git a/Core/Contents/Include/PolyPluginManager.h b/Core/Contents/Include/PolyPluginManager.h new file mode 100644 index 000000000..a7463d803 --- /dev/null +++ b/Core/Contents/Include/PolyPluginManager.h @@ -0,0 +1,47 @@ +/* +Copyright (C) 2014 by Joachim Meyer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once +#include "PolyGlobals.h" +#include "PolyPlugin.h" + +namespace Polycode { + + class ResourcePool; + class String; + + class PluginManager : public PolyBase { + public: + PluginManager(); + ~PluginManager(); + + std::vector loadPluginsFromFile(ResourcePool* pool, const String &fileName); + void loadPluginLibraryIntoPool(ResourcePool *pool, const String &pluginFile); + + void addPlugin(Plugin* plugin); + + protected: + Number version; + std::vector plugins; + }; + +} \ No newline at end of file diff --git a/Core/Contents/Include/PolyResource.h b/Core/Contents/Include/PolyResource.h index 69596fa59..08f4d2782 100755 --- a/Core/Contents/Include/PolyResource.h +++ b/Core/Contents/Include/PolyResource.h @@ -59,7 +59,8 @@ namespace Polycode { static const int RESOURCE_CUBEMAP = 6; static const int RESOURCE_SPRITE = 7; static const int RESOURCE_ENTITY_INSTANCE = 8; - + static const int RESOURCE_PLUGIN = 9; + bool reloadOnFileModify; static bool defaultReloadOnFileModify; @@ -69,12 +70,8 @@ namespace Polycode { //@} protected: - - int type; String resourcePath; String name; - - }; } diff --git a/Core/Contents/Include/PolyResourceManager.h b/Core/Contents/Include/PolyResourceManager.h index 0fb5b6e4c..509658444 100755 --- a/Core/Contents/Include/PolyResourceManager.h +++ b/Core/Contents/Include/PolyResourceManager.h @@ -106,6 +106,7 @@ namespace Polycode { void parseShadersIntoPool(ResourcePool *pool, const String& dirPath, bool recursive); void parseProgramsIntoPool(ResourcePool *pool, const String& dirPath, bool recursive); void parseCubemapsIntoPool(ResourcePool *pool, const String& dirPath, bool recursive); + void parsePluginsIntoPool(ResourcePool *pool, const String& dirPath, bool recursive); void parseOtherIntoPool(ResourcePool *pool, const String& dirPath, bool recursive); ResourcePool *getGlobalPool(); diff --git a/Core/Contents/Include/PolySceneEntityInstance.h b/Core/Contents/Include/PolySceneEntityInstance.h index bb4873a0c..4e3423166 100644 --- a/Core/Contents/Include/PolySceneEntityInstance.h +++ b/Core/Contents/Include/PolySceneEntityInstance.h @@ -57,6 +57,7 @@ class SceneEntityInstance : public Entity { void clearInstance(); void parseObjectIntoCurve(ObjectEntry *entry, BezierCurve *curve); + std::vector parseObjectEntryIntoProps(ObjectEntry *propsEntry, const String& baseName); Entity *loadObjectEntryIntoEntity(ObjectEntry *entry, Entity *targetEntity = NULL, int entityFileVersion = 1); bool loadFromFile(const String& fileName); void applySceneMesh(ObjectEntry *entry, SceneMesh *sceneMesh); @@ -78,7 +79,7 @@ class SceneEntityInstance : public Entity { SceneEntityInstanceLayer *createNewLayer(String name); - + String getFileName() const; bool cloneUsingReload; diff --git a/Core/Contents/Source/PolyCoreServices.cpp b/Core/Contents/Source/PolyCoreServices.cpp index 42620f145..7bec527d2 100755 --- a/Core/Contents/Source/PolyCoreServices.cpp +++ b/Core/Contents/Source/PolyCoreServices.cpp @@ -35,6 +35,7 @@ #include "PolyTimerManager.h" #include "PolyTweenManager.h" #include "PolySoundManager.h" +#include "PolyPluginManager.h" using namespace Polycode; @@ -95,6 +96,10 @@ FontManager *CoreServices::getFontManager() { return fontManager; } +PluginManager *CoreServices::getPluginManager(){ + return pluginManager; +} + Config *CoreServices::getConfig() { return config; } @@ -131,6 +136,7 @@ CoreServices::CoreServices() : EventDispatcher() { tweenManager = new TweenManager(); soundManager = new SoundManager(); fontManager = new FontManager(); + pluginManager = new PluginManager(); } CoreServices::~CoreServices() { diff --git a/Core/Contents/Source/PolyEntity.cpp b/Core/Contents/Source/PolyEntity.cpp index b88f6ad3e..a7c302248 100755 --- a/Core/Contents/Source/PolyEntity.cpp +++ b/Core/Contents/Source/PolyEntity.cpp @@ -23,6 +23,7 @@ #include "PolyRenderer.h" #include "PolyCoreServices.h" #include "PolyInputEvent.h" +#include "PolyResourceManager.h" using namespace Polycode; @@ -804,28 +805,125 @@ void Entity::rebuildRotation() { rotationQuat.fromAxes(rotation.x, rotation.y, rotation.z); } -void Entity::setEntityProp(const String& propName, const String& propValue) { +void Entity::setEntityProp(const String& propName, const String& propVal) { - for(int i=0; i < entityProps.size(); i++) { - if(entityProps[i].propName == propName) { - entityProps[i].propValue = propValue; + for (int i = 0; i < entityProps.size(); i++) { + if (entityProps[i]->name == propName) { + entityProps[i]->stringVal = propVal; + entityProps[i]->type = EntityProp::PROP_STRING; return; } - } + } + + + EntityProp* entityProp = new EntityProp(propName, EntityProp::PROP_STRING); + entityProp->stringVal = propVal; + entityProps.push_back(entityProp); +} + +void Entity::setEntityProp(const String& propName, const int& propVal) { + + for (int i = 0; i < entityProps.size(); i++) { + if (entityProps[i]->name == propName) { + entityProps[i]->intVal = propVal; + entityProps[i]->type = EntityProp::PROP_INT; + return; + } + } + + EntityProp* entityProp = new EntityProp(propName, EntityProp::PROP_INT); + entityProp->intVal = propVal; + entityProps.push_back(entityProp); +} + +void Entity::setEntityProp(const String& propName, const Number& propVal) { + + for (int i = 0; i < entityProps.size(); i++) { + if (entityProps[i]->name == propName) { + entityProps[i]->numberVal = propVal; + entityProps[i]->type = EntityProp::PROP_NUMBER; + return; + } + } + + EntityProp* entityProp = new EntityProp(propName, EntityProp::PROP_NUMBER); + entityProp->numberVal = propVal; + entityProps.push_back(entityProp); +} + +void Entity::setEntityProp(const String& propName, const bool& propVal) { + + for (int i = 0; i < entityProps.size(); i++) { + if (entityProps[i]->name == propName) { + entityProps[i]->boolVal = propVal; + entityProps[i]->type = EntityProp::PROP_BOOL; + return; + } + } - EntityProp entityProp; - entityProp.propName = propName; - entityProp.propValue = propValue; + EntityProp* entityProp = new EntityProp(propName, EntityProp::PROP_BOOL); + entityProp->boolVal = propVal; entityProps.push_back(entityProp); } -String Entity::getEntityProp(const String& propName) { - for(int i=0; i < entityProps.size(); i++) { - if(entityProps[i].propName == propName) { - return entityProps[i].propValue; +void Entity::setEntityProp(EntityProp* prop){ + for (int i = 0; i < entityProps.size(); i++) { + if (entityProps[i]->name == prop->name) { + entityProps[i] = prop; + return; + } + } + + entityProps.push_back(prop); +} + +int Entity::getEntityPropIntByName(const String& propName) const { + for (int i = 0; i < entityProps.size(); i++) { + if (entityProps[i]->name == propName && entityProps[i]->type == EntityProp::PROP_INT) { + return entityProps[i]->intVal; + } else if (entityProps[i]->name == propName && entityProps[i]->type == EntityProp::PROP_NUMBER){ + return entityProps[i]->numberVal; + } + } + return 0; +} + +Number Entity::getEntityPropNumberByName(const String& propName) const { + for (int i = 0; i < entityProps.size(); i++) { + if (entityProps[i]->name == propName && entityProps[i]->type == EntityProp::PROP_INT) { + return entityProps[i]->intVal; + } else if (entityProps[i]->name == propName && entityProps[i]->type == EntityProp::PROP_NUMBER){ + return entityProps[i]->numberVal; } } - return "null"; + return Number(NULL); +} + +bool Entity::getEntityPropBoolByName(const String& propName) const { + for (int i = 0; i < entityProps.size(); i++) { + if (entityProps[i]->name == propName && entityProps[i]->type == EntityProp::PROP_BOOL) { + return entityProps[i]->boolVal; + } + } + return -1; +} + +String Entity::getEntityPropStringByName(const String& propName) const { + for (int i = 0; i < entityProps.size(); i++) { + if (entityProps[i]->name == propName && entityProps[i]->type == EntityProp::PROP_STRING) { + return entityProps[i]->stringVal; + } + } + return String("null"); +} + +bool Entity::isRequiredPlugin(const String& pluginName) const { + for (int i = 0; i < requiredPlugins.size(); i++) { + if (requiredPlugins[i]->getResourceName() == pluginName){ + return true; + } + } + return false; } Vector3 Entity::getCombinedPosition() const { @@ -1250,3 +1348,42 @@ MouseEventResult Entity::onMouseWheelDown(const Ray &ray, int timestamp) { } return ret; } + +EntityProp::EntityProp(const String& name, const unsigned int& type) { + this->name = name; + this->type = type; +} + +void Entity::addPluginByName(const String& pluginName, ResourcePool *resourcePool) { + Plugin *plugin; + + if (resourcePool) { + plugin = (Plugin*)resourcePool->getResource(Resource::RESOURCE_PLUGIN, pluginName); + } else { + plugin = (Plugin*)Services()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_PLUGIN, pluginName); + } + + if (plugin){ + + for (int i = 0; i < requiredPlugins.size(); i++) { + if (requiredPlugins[i]->getResourceName() == plugin->getResourceName()) { + requiredPlugins[i] = plugin; + return; + } + } + + requiredPlugins.push_back(plugin); + for (int p = 0; p < plugin->getNumProps(); p++){ + setEntityProp(plugin->getResourceName() + plugin->getProps()[p]->name, 0); + } + } +} + +void Entity::removePluginByName(const String& pluginName) { + for (int i = 0; i < requiredPlugins.size(); i++) { + if (requiredPlugins[i]->getResourceName() == pluginName) { + requiredPlugins.erase(requiredPlugins.begin() + i); + return; + } + } +} \ No newline at end of file diff --git a/Core/Contents/Source/PolyPlugin.cpp b/Core/Contents/Source/PolyPlugin.cpp new file mode 100644 index 000000000..8357a80f7 --- /dev/null +++ b/Core/Contents/Source/PolyPlugin.cpp @@ -0,0 +1,147 @@ +/* +Copyright (C) 2014 by Joachim Meyer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "PolyPlugin.h" +#include "PolyObject.h" +#include "PolyCoreServices.h" +#include "PolyPluginManager.h" +#include "PolyResourceManager.h" +#include "PolyLogger.h" + +using namespace Polycode; + +Plugin::Plugin(const String& name) : Resource(Resource::RESOURCE_PLUGIN) { + if (!Services()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_PLUGIN, name)) { + setResourceName(""); + ext = ""; + pluginType = 0; + type = Resource::RESOURCE_PLUGIN; + } +} + +Plugin::Plugin(ObjectEntry *entry) : Resource(Resource::RESOURCE_PLUGIN) { + loadPluginFromEntry(entry); +} + +Plugin::~Plugin() {} + +Plugin* Plugin::loadPluginFromEntry(ObjectEntry* entry){ + if ((*entry)["name"]) + this->setResourceName((*entry)["name"]->stringVal); + + if ((*entry)["author"]) + this->author = (*entry)["author"]->stringVal; + + if ((*entry)["fileext"]) + this->ext = (*entry)["fileext"]->stringVal; + + if ((*entry)["type"]) + this->pluginType = (*entry)["type"]->intVal; + + if ((*entry)["sheet"]){ + ObjectEntry* sheetEntry = (*entry)["sheet"]; + if ((*sheetEntry)["props"]){ + ObjectEntry* props = (*sheetEntry)["props"]; + if (props) { + for (int k = 0; k < props->children.size(); k++) { + ObjectEntry* propEntry = props->children[k]; + if (!propEntry || propEntry->name != "prop") + continue; + Prop *prop = new Prop(propEntry); + this->setProp(prop); + } + } + } + } + Logger::log("Adding plugin: [%s]\n", this->getResourceName().c_str()); + return this; +} + +unsigned int Plugin::getNumProps() const { + return props.size(); +} + +void Plugin::setProp(Prop *prop) { + for (int i = 0; i < props.size(); i++) { + if (props[i]->name == prop->name) { + props[i] = prop; + return; + } + } + + props.push_back(prop); +} + +void Plugin::removeProp(Prop *propToRemove) { + for (int i = 0; iname == propName) { + delete props[i]; + props.erase(props.begin() + i); + return; + } + } +} + +std::vector Plugin::getProps() const { + return props; +} + +Prop::Prop(const String& name, const int type){ + this->type = type; + this->name = name; +} + +Prop::Prop(ObjectEntry *entry) { + loadPropFromEntry(entry); +} + +Prop::~Prop(){} + +Prop* Prop::loadPropFromEntry(ObjectEntry* entry){ + if (!entry->readInt("type", &this->type)) + return NULL; + + if (!(*entry)["name"]) + return NULL; + this->name = (*entry)["name"]->stringVal; + + if (type == Prop::PROP_COMBO || type == Prop::PROP_SLIDER){ + for (int i = 0; i < entry->children.size(); i++) { if (entry->children[i]->name == "prop") { + Prop* newProp = new Prop((*entry->children[i])["name"]->stringVal, Prop::PROP_COMBO); + newProp->value = (*entry->children[i])["value"]->intVal; + children.push_back(newProp); + } + } + + return this; + } +} \ No newline at end of file diff --git a/Core/Contents/Source/PolyPluginManager.cpp b/Core/Contents/Source/PolyPluginManager.cpp new file mode 100644 index 000000000..42c3b08b8 --- /dev/null +++ b/Core/Contents/Source/PolyPluginManager.cpp @@ -0,0 +1,68 @@ +/* +Copyright (C) 2014 by Joachim Meyer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "PolyPluginManager.h" +#include "PolyPlugin.h" +#include "PolyObject.h" +#include "PolyLogger.h" +#include "PolyResourceManager.h" + +using namespace Polycode; + +PluginManager::PluginManager() { + version = 1.0; +} + +PluginManager::~PluginManager(){} + +std::vector PluginManager::loadPluginsFromFile(ResourcePool *pool, const String &fileName){ + std::vector retPlugins; + Object pluginFile; + if (!pluginFile.loadFromBinary(fileName)) + if (!pluginFile.loadFromXML(fileName)) + return retPlugins; + + version = 1.0; + + for (int i = 0; i < pluginFile.root.children.size(); i++){ + ObjectEntry* pluginEntry = pluginFile.root.children[i]; + if (!pluginEntry || pluginEntry->name != "plugin") + continue; + + Plugin *plugin = new Plugin(pluginEntry); + if (plugin){ + pool->addResource(plugin); + retPlugins.push_back(plugin); + } + } + return retPlugins; +} + +void PluginManager::loadPluginLibraryIntoPool(ResourcePool *pool, const String &pluginFile) { + Logger::log("LOADING [%s] into pool [%s]\n", pluginFile.c_str(), pool->getName().c_str()); + + loadPluginsFromFile(pool, pluginFile); +} + +void PluginManager::addPlugin(Plugin* plugin) { + plugins.push_back(plugin); +} \ No newline at end of file diff --git a/Core/Contents/Source/PolyResourceManager.cpp b/Core/Contents/Source/PolyResourceManager.cpp index 813254819..0ce67ce7f 100755 --- a/Core/Contents/Source/PolyResourceManager.cpp +++ b/Core/Contents/Source/PolyResourceManager.cpp @@ -30,6 +30,8 @@ #include "PolyMaterial.h" #include "PolyShader.h" #include "PolyTexture.h" +#include "PolyPluginManager.h" +#include "PolyPlugin.h" #include "OSBasics.h" #include "physfs.h" @@ -121,6 +123,7 @@ void ResourceManager::addDirResource(const String& dirPath, bool recursive) { parseShadersIntoPool(globalPool, dirPath, recursive); parseCubemapsIntoPool(globalPool, dirPath, recursive); parseMaterialsIntoPool(globalPool, dirPath, recursive); + parsePluginsIntoPool(globalPool, dirPath, recursive); parseOtherIntoPool(globalPool, dirPath, recursive); } @@ -312,6 +315,25 @@ void ResourceManager::parseCubemapsIntoPool(ResourcePool *pool, const String& di } } + +void ResourceManager::parsePluginsIntoPool(ResourcePool *pool, const String& dirPath, bool recursive) { + vector resourceDir; + resourceDir = OSBasics::parseFolder(dirPath, false); + + for (int i = 0; i < resourceDir.size(); i++) { + if (resourceDir[i].type == OSFileEntry::TYPE_FILE) { + if (resourceDir[i].extension == "plugin") { + PluginManager *pluginManager = CoreServices::getInstance()->getPluginManager(); + std::vector plugins = pluginManager->loadPluginsFromFile(Services()->getResourceManager()->getGlobalPool(), resourceDir[i].fullPath); + } + } else { + if (recursive) + parsePluginsIntoPool(pool, dirPath + "/" + resourceDir[i].name, true); + } + } +} + + void ResourceManager::handleEvent(Event *event) { if(event->getEventCode() == Event::RESOURCE_CHANGE_EVENT) { dispatchEvent(new Event(), Event::CHANGE_EVENT); diff --git a/Core/Contents/Source/PolySceneEntityInstance.cpp b/Core/Contents/Source/PolySceneEntityInstance.cpp index f17048921..be02dc9c6 100644 --- a/Core/Contents/Source/PolySceneEntityInstance.cpp +++ b/Core/Contents/Source/PolySceneEntityInstance.cpp @@ -273,6 +273,40 @@ void SceneEntityInstance::parseObjectIntoCurve(ObjectEntry *entry, BezierCurve * } +std::vector SceneEntityInstance::parseObjectEntryIntoProps(ObjectEntry *propsEntry, const String& baseName) { + Entity *retEntity = new Entity(); + std::vector entProps; + for (int i = 0; i < propsEntry->children.size(); i++) { + ObjectEntry *prop = ((*propsEntry))[i]; + if (prop->name=="prop") { + switch ((*prop)["type"]->intVal) { + case EntityProp::PROP_STRING: + retEntity->setEntityProp(baseName + (*prop)["name"]->stringVal, (*prop)["value"]->stringVal); + break; + case EntityProp::PROP_ARRAY: + entProps = parseObjectEntryIntoProps(prop, baseName + (*prop)["name"]->stringVal); + for (int i = 0; i < entProps.size(); i++){ + retEntity->setEntityProp(entProps[i]); + } + break; + case EntityProp::PROP_BOOL: + retEntity->setEntityProp(baseName + (*prop)["name"]->stringVal, (*prop)["value"]->boolVal); + break; + case EntityProp::PROP_INT: + retEntity->setEntityProp(baseName + (*prop)["name"]->stringVal, (*prop)["value"]->intVal); + break; + case EntityProp::PROP_NUMBER: + retEntity->setEntityProp(baseName + (*prop)["name"]->stringVal, (*prop)["value"]->NumberVal); + break; + default: + retEntity->setEntityProp(baseName + (*prop)["name"]->stringVal, (*prop)["value"]->stringVal); + break; + } + } + } + return retEntity->entityProps; +} + Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entity *targetEntity, int entityFileVersion) { Entity *entity = NULL; @@ -498,7 +532,6 @@ Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entit entity->color.b = (*entry)["cB"]->NumberVal; entity->color.a = (*entry)["cA"]->NumberVal; - if(!targetEntity) { entity->blendingMode = (*entry)["blendMode"]->intVal; @@ -529,16 +562,39 @@ Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entit } } - ObjectEntry *props = (*entry)["props"]; - if(props) { - for(int i=0; i < props->length; i++) { - ObjectEntry *prop = ((*props))[i]; - if(prop) { - entity->setEntityProp((*prop)["name"]->stringVal, (*prop)["value"]->stringVal); + if (entityFileVersion <= 2){ + ObjectEntry *props = (*entry)["props"]; + if (props) { + for (int i = 0; i < props->length; i++) { + ObjectEntry *prop = ((*props))[i]; + if (prop) { + entity->setEntityProp((*prop)["name"]->stringVal, (*prop)["value"]->stringVal); + } + } + } + } else { + ObjectEntry *plugins = (*entry)["plugins"]; + if (plugins){ + for (int p = 0; p < plugins->children.size(); p++) { + ObjectEntry *plugin = plugins->children[p]; + if (plugin){ + if (plugin->name == "plugin") { + String pluginName = (*plugin)["name"]->stringVal; + entity->addPluginByName(pluginName); + + ObjectEntry *props = (*plugin)["props"]; + if (props){ + std::vector entProps = parseObjectEntryIntoProps(props, pluginName); + for (int i = 0; i < entProps.size(); i++){ + entity->setEntityProp(entProps[i]); + } + } + } + } } } } - + ObjectEntry *children = (*entry)["children"]; if(children) { @@ -704,6 +760,7 @@ bool SceneEntityInstance::loadFromFile(const String& fileName) { } } } + } ObjectEntry *root = loadObject.root["root"]; @@ -725,3 +782,12 @@ bool SceneEntityInstance::loadFromFile(const String& fileName) { return true; } + + + + + + + + + diff --git a/Core/Contents/Source/PolyWinCore.cpp b/Core/Contents/Source/PolyWinCore.cpp index 4f06a0a35..a52c3eac5 100644 --- a/Core/Contents/Source/PolyWinCore.cpp +++ b/Core/Contents/Source/PolyWinCore.cpp @@ -1137,7 +1137,7 @@ std::vector Win32Core::openFilePicker(std::vector ext ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir=NULL; - if(allowMultiple) { + if(!allowMultiple) { ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_EXPLORER; } else { ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_ALLOWMULTISELECT|OFN_EXPLORER; @@ -1147,7 +1147,23 @@ std::vector Win32Core::openFilePicker(std::vector ext if(GetOpenFileName(&ofn)) { if(allowMultiple) { - + String dir = fBuffer; + size_t pos = dir.length(), last = 0; + while (true){ + if (fBuffer[pos + 1] == NULL){ + if (retVec.size() == 0){ + retVec.push_back(dir); + } + break; + } else { + String fileName; + for (last = pos + 1; fBuffer[pos + 1] != NULL; pos++){ + fileName.append(fBuffer[pos + 1]); + } + retVec.push_back(dir + "/" + fileName); + pos++; + } + } } else { retVec.push_back(String(fBuffer)); } diff --git a/IDE/Build/Windows2013/Polycode.rc b/IDE/Build/Windows2013/Polycode.rc index d73e4349e..a629c414f 100644 Binary files a/IDE/Build/Windows2013/Polycode.rc and b/IDE/Build/Windows2013/Polycode.rc differ diff --git a/IDE/Build/Windows2013/Polycode.sln b/IDE/Build/Windows2013/Polycode.sln index 02b3dad1f..a07f85ac4 100644 --- a/IDE/Build/Windows2013/Polycode.sln +++ b/IDE/Build/Windows2013/Polycode.sln @@ -1,8 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.21005.1 -MinimumVisualStudioVersion = 10.0.40219.1 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30501.0MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Polycode", "Polycode.vcxproj", "{D6C2171B-9167-4FB6-851A-DC1CEDCFC43D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0D5CDD59-CFF6-4143-8D1D-A92BBAB86060}" @@ -18,8 +17,8 @@ Global Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D6C2171B-9167-4FB6-851A-DC1CEDCFC43D}.Debug|Win32.ActiveCfg = Debug|x64 - {D6C2171B-9167-4FB6-851A-DC1CEDCFC43D}.Debug|Win32.Build.0 = Debug|x64 + {D6C2171B-9167-4FB6-851A-DC1CEDCFC43D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D6C2171B-9167-4FB6-851A-DC1CEDCFC43D}.Debug|Win32.Build.0 = Debug|Win32 {D6C2171B-9167-4FB6-851A-DC1CEDCFC43D}.Debug|x64.ActiveCfg = Debug|x64 {D6C2171B-9167-4FB6-851A-DC1CEDCFC43D}.Debug|x64.Build.0 = Debug|x64 {D6C2171B-9167-4FB6-851A-DC1CEDCFC43D}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/IDE/Build/Windows2013/Polycode.vcxproj b/IDE/Build/Windows2013/Polycode.vcxproj index 503c67b32..1dc8017ee 100644 --- a/IDE/Build/Windows2013/Polycode.vcxproj +++ b/IDE/Build/Windows2013/Polycode.vcxproj @@ -38,6 +38,7 @@ + @@ -76,6 +77,7 @@ + diff --git a/IDE/Build/Windows2013/Polycode.vcxproj.filters b/IDE/Build/Windows2013/Polycode.vcxproj.filters index dde3779ad..a77e0ee3e 100644 --- a/IDE/Build/Windows2013/Polycode.vcxproj.filters +++ b/IDE/Build/Windows2013/Polycode.vcxproj.filters @@ -114,6 +114,9 @@ Source + + Source + @@ -222,6 +225,9 @@ Include + + Include + diff --git a/IDE/Build/Windows2013/resource.h b/IDE/Build/Windows2013/resource.h index de8ce9694..e1e0b7a7f 100644 Binary files a/IDE/Build/Windows2013/resource.h and b/IDE/Build/Windows2013/resource.h differ diff --git a/IDE/Build/WindowsShared/PolycodeWinIDEView.cpp b/IDE/Build/WindowsShared/PolycodeWinIDEView.cpp index c6f06ab8e..3504734a8 100644 --- a/IDE/Build/WindowsShared/PolycodeWinIDEView.cpp +++ b/IDE/Build/WindowsShared/PolycodeWinIDEView.cpp @@ -70,6 +70,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case ID_FILE_OPEN_PROJECT: globalApp->openProject(); break; + case ID_FILE_OPEN_FILE: + globalApp->openFilePicker(); + break; case ID_FILE_CLOSE_FILE: globalApp->closeFile(); break; diff --git a/IDE/Contents/Include/EntityEditorPropertyView.h b/IDE/Contents/Include/EntityEditorPropertyView.h index 8d969a953..c8104edcc 100644 --- a/IDE/Contents/Include/EntityEditorPropertyView.h +++ b/IDE/Contents/Include/EntityEditorPropertyView.h @@ -60,7 +60,8 @@ class EntityEditorPropertyView : public UIElement { SoundSheet *soundSheet; SceneCurveSheet *curveSheet; CameraSheet *cameraSheet; - EntityPropSheet *propSheet; + PluginsSheet *pluginsSheet; + std::vector propSheets; SceneMeshSheet *sceneMeshSheet; ShaderTexturesSheet *shaderTexturesSheet; diff --git a/IDE/Contents/Include/PolycodeEditor.h b/IDE/Contents/Include/PolycodeEditor.h index c02b6fac8..8261c03a5 100644 --- a/IDE/Contents/Include/PolycodeEditor.h +++ b/IDE/Contents/Include/PolycodeEditor.h @@ -127,7 +127,9 @@ class PolycodeEditorFactory { bool canHandleExtension(String extension); + std::vector getExtensions(); + protected: - std::vector extensions; + std::vector extensions; }; diff --git a/IDE/Contents/Include/PolycodeEditorManager.h b/IDE/Contents/Include/PolycodeEditorManager.h index 5854b1d52..f93ec3794 100644 --- a/IDE/Contents/Include/PolycodeEditorManager.h +++ b/IDE/Contents/Include/PolycodeEditorManager.h @@ -38,6 +38,8 @@ class PolycodeEditorManager : public EventDispatcher { void registerEditorFactory(PolycodeEditorFactory *editorFactory); PolycodeEditorFactory *getEditorFactoryForExtension(String extension); + + std::vector getExtensionsWithEditor(); void handleEvent(Event *event); diff --git a/IDE/Contents/Include/PolycodeEntityEditor.h b/IDE/Contents/Include/PolycodeEntityEditor.h index de212bcae..8c5ca9a35 100644 --- a/IDE/Contents/Include/PolycodeEntityEditor.h +++ b/IDE/Contents/Include/PolycodeEntityEditor.h @@ -383,7 +383,8 @@ class PolycodeEntityEditor : public PolycodeEditor { void saveFile(); void saveCurveToObject(ObjectEntry *entry, BezierCurve *curve); void saveShaderOptionsToEntry(ObjectEntry *entry, Material *material, ShaderBinding *binding); - + void savePropsToEntry(ObjectEntry *entry, std::vector props, const String& baseName); + void saveEntityToObjectEntry(Entity *entity, ObjectEntry *entry); void doAction(String actionName, PolycodeEditorActionData *data); diff --git a/IDE/Contents/Include/PolycodeIDEApp.h b/IDE/Contents/Include/PolycodeIDEApp.h index e90347d44..6dae452e9 100644 --- a/IDE/Contents/Include/PolycodeIDEApp.h +++ b/IDE/Contents/Include/PolycodeIDEApp.h @@ -42,6 +42,7 @@ #include "PolycodeSpriteEditor.h" #include "PolycodeMeshEditor.h" #include "PolycodeEntityEditor.h" +#include "PolycodePluginEditor.h" #include "PolycodeToolLauncher.h" @@ -68,6 +69,7 @@ class PolycodeIDEApp : public EventDispatcher { void openFileInProject(PolycodeProject *project, String filePath); void openFile(OSFileEntry file); + void openFilePicker(); void stopProject(); diff --git a/IDE/Contents/Include/PolycodePluginEditor.h b/IDE/Contents/Include/PolycodePluginEditor.h new file mode 100644 index 000000000..cdfcfcdfd --- /dev/null +++ b/IDE/Contents/Include/PolycodePluginEditor.h @@ -0,0 +1,144 @@ +/* +Copyright (C) 2014 by Joachim Meyer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once +#include "PolycodeEditor.h" +#include +#include "PolycodeUI.h" +#include "PolycodeProps.h" +#include "PolyPlugin.h" + +namespace Polycode { + + class PluginBrowserData { + public: + PluginBrowserData() { + plugin = NULL; + } + Plugin *plugin; + }; + + class PluginBrowser : public UIElement { + public: + PluginBrowser(); + ~PluginBrowser(); + + void Resize(Number width, Number height); + + UITree *addPlugin(Plugin* plugin); + + void removeSelected(); + + void handleEvent(Event *event); + + PluginBrowserData *selectedData; + + UIImageButton *newPluginButton; + + UIImageButton *removeButton; + + UITree *selectedNode; + + protected: + + UIRect *headerBg; + UITree *pluginNode; + + UITreeContainer *treeContainer; + }; + + class PluginEditorPane : public UIElement { + public: + PluginEditorPane(ResourcePool* resourcePool); + ~PluginEditorPane(); + + void setPlugin(Plugin *plugin); + void handleEvent(Event *event); + + PropProp* getPropByName(); + void setProp(const String& name, PropProp* prop); + std::vector getProps(); + int getNumProps(); + + void Resize(Number width, Number height); + + Plugin *currentPlugin; + protected: + ResourcePool *resourcePool; + bool changingPlugin; + UIRect *headerBg; + PropList *propList; + PropSheet *propsSheet; + + StringProp* nameProp; + StringProp* author; + + StringProp* newPropName; + ButtonProp* addPropButton; + + int padding; + }; + + class PluginMainWindow : public UIElement { + public: + PluginMainWindow(ResourcePool *resourcePool); + ~PluginMainWindow(); + + void Resize(Number width, Number height); + + PluginEditorPane *pluginPane; + + UIColorPicker *colorPicker; + }; + + class PolycodePluginEditor : public PolycodeEditor { + public: + PolycodePluginEditor(); + ~PolycodePluginEditor(); + + bool openFile(OSFileEntry filePath); + void Resize(int x, int y); + + void saveFile(); + void savePluginToObjectEntry(Plugin *plugin, ObjectEntry *entry); + + void handleEvent(Event *event); + + protected: + ResourcePool *resourcePool; + OSFileEntry filePath; + + PluginBrowser *pluginBrowser; + UIHSizer *mainSizer; + + PluginMainWindow *mainWindow; + //std::vector plugins; + + UITree *selectedPluginNode; + }; + + class PolycodePluginEditorFactory : public PolycodeEditorFactory { + public: + PolycodePluginEditorFactory() : PolycodeEditorFactory() { extensions.push_back("plugin"); } + PolycodeEditor *createEditor() { return new PolycodePluginEditor(); } + }; +} \ No newline at end of file diff --git a/IDE/Contents/Include/PolycodeProps.h b/IDE/Contents/Include/PolycodeProps.h index f75a538ec..a6d8c932a 100644 --- a/IDE/Contents/Include/PolycodeProps.h +++ b/IDE/Contents/Include/PolycodeProps.h @@ -36,20 +36,48 @@ class PolycodeEditorPropActionData; class PropProp : public UIElement { public: - PropProp(String caption, String type); + PropProp(String caption, int type); ~PropProp(); virtual void setPropData(PolycodeEditorPropActionData* data) {} virtual void setPropWidth(Number width) {} void setPropName(String newName); - - String propType; + String getPropName(); + + int propType; UILabel *label; Entity *propContents; bool suppressChangeEvent; bool settingFromData; + + static const int PROP_VECTOR3 = 0; + static const int PROP_VECTOR2 = 1; + static const int PROP_SLIDER = 2; + static const int PROP_BUTTON = 3; + static const int PROP_NUMBER = 4; + static const int PROP_TARGET_BINDING = 5; + static const int PROP_RENDER_TARGET = 6; + static const int PROP_SHADER_PASS = 7; + static const int PROP_REMOVABLE_STRING = 8; + static const int PROP_LAYER = 9; + static const int PROP_CUSTOM = 10; + static const int PROP_STRING = 11; + static const int PROP_COLOR = 12; + static const int PROP_COMBO = 13; + static const int PROP_BOOL = 14; + static const int PROP_SOUND = 15; + static const int PROP_BEZIER_RGBA_CURVE = 16; + static const int PROP_BEZIER_CURVE = 17; + static const int PROP_MATERIAL = 18; + static const int PROP_MATERIAL_PREVIEW = 19; + static const int PROP_TEXTURE = 20; + static const int PROP_SCENE_SPRITE = 21; + static const int PROP_SCENE_ENTITY_INSTANCE = 22; + static const int PROP_EDIT = 23; + static const int PROP_COMBO_EDIT = 24; + static const int PROP_SLIDER_EDIT = 25; }; class Vector3Prop : public PropProp { @@ -77,7 +105,6 @@ class Vector3Prop : public PropProp { }; - class Vector2Prop : public PropProp { public: Vector2Prop(String caption); @@ -130,7 +157,6 @@ class ButtonProp : public PropProp { UIButton *button; }; - class NumberProp : public PropProp { public: NumberProp(String caption); @@ -220,7 +246,6 @@ class RemovableStringProp : public PropProp { UIImageButton *removeButton; }; - class LayerProp : public PropProp { public: LayerProp(SceneEntityInstance *instance, SceneEntityInstanceLayer *layer); @@ -260,7 +285,7 @@ class CustomProp : public PropProp { UITextInput *keyEntry; UITextInput *valueEntry; - UIImageButton *removeButton; + //UIImageButton *removeButton; }; class StringProp : public PropProp { @@ -471,6 +496,76 @@ class SceneEntityInstanceProp : public PropProp { }; +class SliderEditProp : public PropProp { +public: + SliderEditProp(SliderProp* newSlider); + ~SliderEditProp(); + void handleEvent(Event *event); + + void set(SliderProp *newCombo); + SliderProp *get(); + + StringProp *minProp; + StringProp *maxProp; + + SliderProp *lastSlider; + SliderProp *currentSlider; +}; + +class ComboPropEditProp : public PropProp { +public: + ComboPropEditProp(ComboProp* newCombo); + ~ComboPropEditProp(); + void handleEvent(Event *event); + + void set(ComboProp *newCombo); + ComboProp *get(); + + void layoutProps(); + + UILabel *nameLabel; + UIButton *addItemButton; + UITextInput *newItemName; + + std::vector items; + std::vector datas; + + ComboProp *lastCombo; + ComboProp *currentCombo; +}; + +class PropEditProp : public PropProp { +public: + PropEditProp(PropProp* newProp); + ~PropEditProp(); + void handleEvent(Event *event); + + void set(PropProp *newProp); + PropProp *get(); + + int updatePadding(); + + int getPropType(); + + PropProp *currentProp; + ComboPropEditProp *comboEditProp; + SliderEditProp *sliderEditProp; + + UITextInput *nameInput; + UIComboBox *typeChooser; + + UILabel *nameLabel; + UIMultilineLabel *typeLabel; + + UIImageButton *delButton; + + int lastValue; + int currentValue; + + String lastName; + String currentName; +}; + class PropSheet : public UIElement { public: PropSheet(String caption, String type); @@ -486,6 +581,8 @@ class PropSheet : public UIElement { void addProp(PropProp *prop); void setTopPadding(Number padding); + + void removeProp(PropProp *prop); String caption; String type; @@ -557,6 +654,8 @@ class EntitySheet : public PropSheet { void setEntityInstance(SceneEntityInstance *instance); + std::vector pluginsProp; + protected: Entity *entity; @@ -567,6 +666,20 @@ class EntitySheet : public PropSheet { ColorProp *colorProp; ComboProp *blendingProp; Vector3Prop *bBoxProp; + +}; + +class PluginsSheet : public PropSheet { +public: + PluginsSheet(); + ~PluginsSheet(); + + void handleEvent(Event *event); + void setEntity(Entity *entity); + + std::vector pluginsProp; + + Entity *entity; }; class ShaderPassesSheet : public PropSheet { @@ -777,19 +890,22 @@ class MaterialPropSheet : public PropSheet { class EntityPropSheet : public PropSheet { public: - EntityPropSheet(); - void handleEvent(Event *event); + EntityPropSheet(Plugin* plugin); + void Update(); void refreshProps(); + void reloadSheetFromEntry(ObjectEntry *sheetEntry); void applyPropActionData(PolycodeEditorPropActionData *data); void setEntity(Entity *entity); - - ButtonProp *addButtonProp; + void handleEvent(Event *event); Entity *entity; + String plugin; + int lastNumProps; int removeIndex; + }; class SceneLabelSheet : public PropSheet { @@ -837,7 +953,7 @@ class SceneSpriteSheet : public PropSheet { void setSprite(SceneSprite *sprite); void setEntityInstance(SceneEntityInstance *instance); - + SceneSprite *sprite; SceneSpriteProp *spriteProp; @@ -845,7 +961,6 @@ class SceneSpriteSheet : public PropSheet { ComboProp *defaultStateProp; }; - class CameraSheet : public PropSheet { public: CameraSheet(); @@ -870,7 +985,6 @@ class CameraSheet : public PropSheet { Camera *camera; }; - class SceneEntityInstanceSheet : public PropSheet { public: SceneEntityInstanceSheet(); @@ -939,6 +1053,13 @@ class LinkedMaterialsSheet : public PropSheet { }; +class CustomSheet : public PropSheet { +public: + +//private: +// std::vector props; +}; + class PropList : public UIElement { public: PropList(String caption="PROPERTIES"); diff --git a/IDE/Contents/Resources/FileTemplates/General/Plugin.plugin b/IDE/Contents/Resources/FileTemplates/General/Plugin.plugin new file mode 100644 index 000000000..8b27dc254 --- /dev/null +++ b/IDE/Contents/Resources/FileTemplates/General/Plugin.plugin @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/IDE/Contents/Resources/Images/materialEditor/new_plugin.png b/IDE/Contents/Resources/Images/materialEditor/new_plugin.png new file mode 100644 index 000000000..8b2677211 Binary files /dev/null and b/IDE/Contents/Resources/Images/materialEditor/new_plugin.png differ diff --git a/IDE/Contents/Resources/Images/materialEditor/plugin_icon.png b/IDE/Contents/Resources/Images/materialEditor/plugin_icon.png new file mode 100644 index 000000000..f2c270fe1 Binary files /dev/null and b/IDE/Contents/Resources/Images/materialEditor/plugin_icon.png differ diff --git a/IDE/Contents/Resources/Images/pluginEditor/new_plugin.png b/IDE/Contents/Resources/Images/pluginEditor/new_plugin.png new file mode 100644 index 000000000..8b2677211 Binary files /dev/null and b/IDE/Contents/Resources/Images/pluginEditor/new_plugin.png differ diff --git a/IDE/Contents/Resources/Images/pluginEditor/plugin_icon.png b/IDE/Contents/Resources/Images/pluginEditor/plugin_icon.png new file mode 100644 index 000000000..f2c270fe1 Binary files /dev/null and b/IDE/Contents/Resources/Images/pluginEditor/plugin_icon.png differ diff --git a/IDE/Contents/Resources/Plugins/PhysicsModul.plugin b/IDE/Contents/Resources/Plugins/PhysicsModul.plugin new file mode 100644 index 000000000..f0c2232d0 --- /dev/null +++ b/IDE/Contents/Resources/Plugins/PhysicsModul.plugin @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/Contents/Source/EntityEditorPropertyView.cpp b/IDE/Contents/Source/EntityEditorPropertyView.cpp index 817ac2170..67fa5891d 100644 --- a/IDE/Contents/Source/EntityEditorPropertyView.cpp +++ b/IDE/Contents/Source/EntityEditorPropertyView.cpp @@ -86,11 +86,18 @@ EntityEditorPropertyView::EntityEditorPropertyView() : UIElement() { entitySheet = new EntitySheet(); entityProps->addPropSheet(entitySheet); entitySheet->addEventListener(this, PropEvent::EVENT_PROP_CHANGE); - - propSheet = new EntityPropSheet(); - entityProps->addPropSheet(propSheet); - propSheet->addEventListener(this, PropEvent::EVENT_PROP_CHANGE); - + + pluginsSheet = new PluginsSheet(); + entityProps->addPropSheet(pluginsSheet); + pluginsSheet->addEventListener(this, PropEvent::EVENT_PROP_CHANGE); + + std::vector plugins = Services()->getResourceManager()->getGlobalPool()->getResources(Resource::RESOURCE_PLUGIN); + for (int p = 0; p < plugins.size(); p++) { + EntityPropSheet *propSheet = new EntityPropSheet(dynamic_cast(plugins[p])); + entityProps->addPropSheet(propSheet); + propSheet->addEventListener(this, PropEvent::EVENT_PROP_CHANGE); + propSheets.push_back(propSheet); + } } void EntityEditorPropertyView::setEntityInstance(SceneEntityInstance *instance) { @@ -109,6 +116,13 @@ void EntityEditorPropertyView::handleEvent(Event *event) { PropEvent *propEvent = (PropEvent*) event; + if (event->getDispatcher() == pluginsSheet){ + for (int p = 0; p < propSheets.size(); p++){ + propSheets[p]->setEntity(this->targetEntity); + } + + } + PropEvent *newPropEvent = new PropEvent(propEvent->prop, propEvent->sheet, propEvent->beforeData, propEvent->afterData); dispatchEvent(newPropEvent, PropEvent::EVENT_PROP_CHANGE); } else { @@ -182,7 +196,12 @@ void EntityEditorPropertyView::setEntity(Entity *entity) { particleSheet->setParticleEmitter(emitter); entitySheet->setEntity(entity); - propSheet->setEntity(entity); + + pluginsSheet->setEntity(entity); + + for (int p = 0; p < propSheets.size(); p++) { + propSheets[p]->setEntity(entity); + } transformSheet->setEntity(entity); Resize(getWidth(), getHeight()); diff --git a/IDE/Contents/Source/PolycodeEditor.cpp b/IDE/Contents/Source/PolycodeEditor.cpp index 37e33b679..4afe3f086 100644 --- a/IDE/Contents/Source/PolycodeEditor.cpp +++ b/IDE/Contents/Source/PolycodeEditor.cpp @@ -42,6 +42,10 @@ bool PolycodeEditorFactory::canHandleExtension(String extension) { return false; } +std::vector PolycodeEditorFactory::getExtensions(){ + return extensions; +} + void PolycodeEditor::setFilePath(String newPath) { filePath = newPath; } diff --git a/IDE/Contents/Source/PolycodeEditorManager.cpp b/IDE/Contents/Source/PolycodeEditorManager.cpp index bddfc7241..066f9d197 100644 --- a/IDE/Contents/Source/PolycodeEditorManager.cpp +++ b/IDE/Contents/Source/PolycodeEditorManager.cpp @@ -45,6 +45,17 @@ PolycodeEditorFactory *PolycodeEditorManager::getEditorFactoryForExtension(Strin return NULL; } +std::vector PolycodeEditorManager::getExtensionsWithEditor(){ + std::vector extensions; + for (int i = 0; i < editorFactories.size(); i++) { + PolycodeEditorFactory *factory = editorFactories[i]; + for (int e = 0; e < factory->getExtensions().size(); e++){ + extensions.push_back(CoreFileExtension(factory->getExtensions()[e], factory->getExtensions()[e])); + } + } + return extensions; +} + PolycodeEditor *PolycodeEditorManager::createEditorForExtension(String extension) { for(int i=0;i < editorFactories.size(); i++) { PolycodeEditorFactory *factory = editorFactories[i]; diff --git a/IDE/Contents/Source/PolycodeEntityEditor.cpp b/IDE/Contents/Source/PolycodeEntityEditor.cpp index 4a2795cfa..14f49d19a 100644 --- a/IDE/Contents/Source/PolycodeEntityEditor.cpp +++ b/IDE/Contents/Source/PolycodeEntityEditor.cpp @@ -1329,9 +1329,9 @@ void EntityEditorMainView::deleteSelected(bool doAction) { selectedEntities[i]->setOwnsChildrenRecursive(true); for(int j=0; j < icons.size(); j++) { if(icons[j]->getUserData() == selectedEntities[i]) { - delete icons[j]; - icons[j]->getParentEntity()->removeChild(icons[j]); - icons.erase(icons.begin()+j); + icons[j]->getParentEntity()->removeChild(icons[j]); + delete icons[j]; + icons.erase(icons.begin()+j); break; } } @@ -2139,16 +2139,18 @@ void PolycodeEntityEditor::saveEntityToObjectEntry(Entity *entity, ObjectEntry * } entry->addChild("tags", tagString); - - if(entity->entityProps.size() > 0) { - ObjectEntry *props = entry->addChild("props"); - for(int i=0; i < entity->entityProps.size(); i++) { - ObjectEntry *prop = props->addChild("prop"); - prop->addChild("name", entity->entityProps[i].propName); - prop->addChild("value", entity->entityProps[i].propValue); - } - } - + if (entity->requiredPlugins.size() > 0) { + ObjectEntry *pluginsEntry = entry->addChild("plugins"); + for (int p = 0; p < entity->requiredPlugins.size(); p++) { + ObjectEntry* plugin = pluginsEntry->addChild("plugin"); + plugin->addChild("name", entity->requiredPlugins[p]->getResourceName()); + if (entity->entityProps.size() > 0) { + ObjectEntry *props = plugin->addChild("props"); + savePropsToEntry(props, entity->entityProps, entity->requiredPlugins[p]->getResourceName()); + } + } + } + if(dynamic_cast(entity) && entity != mainView->getObjectRoot()) { if(!(*(entry))["type"]) { entry->addChild("type", "SceneEntityInstance"); @@ -2502,12 +2504,11 @@ void PolycodeEntityEditor::saveFile() { } saveObject.root.name = "entity"; - saveObject.root.addChild("version", 2); + saveObject.root.addChild("version", 3); ObjectEntry *children = saveObject.root.addChild("root"); saveEntityToObjectEntry(mainView->getObjectRoot(), children); - - + saveObject.saveToXML(filePath); setHasChanges(false); } @@ -2518,3 +2519,28 @@ void PolycodeEntityEditor::Resize(int x, int y) { PolycodeEditor::Resize(x,y); } +void PolycodeEntityEditor::savePropsToEntry(ObjectEntry *entry, std::vector props, const String& baseName) { + for (int i = 0; i < props.size(); i++) { + if (props[i]->name.find(baseName) == 0){ + ObjectEntry *prop = entry->addChild("prop"); + prop->addChild("name", props[i]->name.replace(baseName, "")); + prop->addChild("type", props[i]->type); + switch (props[i]->type) { + case EntityProp::PROP_STRING: + prop->addChild("value", props[i]->stringVal); + break; + case EntityProp::PROP_BOOL: prop->addChild("value", props[i]->boolVal); + break; + case EntityProp::PROP_INT: + prop->addChild("value", props[i]->intVal); + break; + case EntityProp::PROP_NUMBER: + prop->addChild("value", props[i]->numberVal); + break; + default: + prop->addChild("value", props[i]->stringVal); + break; + } + } + } +} diff --git a/IDE/Contents/Source/PolycodeIDEApp.cpp b/IDE/Contents/Source/PolycodeIDEApp.cpp index c57cff82f..bb71f6ec8 100644 --- a/IDE/Contents/Source/PolycodeIDEApp.cpp +++ b/IDE/Contents/Source/PolycodeIDEApp.cpp @@ -72,7 +72,8 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() { CoreServices::getInstance()->getResourceManager()->addArchive("Physics3D.pak"); CoreServices::getInstance()->getResourceManager()->addArchive("UI.pak"); - CoreServices::getInstance()->getResourceManager()->addDirResource("Materials"); + CoreServices::getInstance()->getResourceManager()->addDirResource("Materials"); + CoreServices::getInstance()->getResourceManager()->addDirResource("Plugins"); CoreServices::getInstance()->getFontManager()->registerFont("section", "Fonts/RobotoCondensed-Bold.ttf"); @@ -175,7 +176,8 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() { editorManager->registerEditorFactory(new PolycodeSpriteEditorFactory()); editorManager->registerEditorFactory(new PolycodeMeshEditorFactory()); editorManager->registerEditorFactory(new PolycodeEntityEditorFactory()); - + editorManager->registerEditorFactory(new PolycodePluginEditorFactory()); + screen->addChild(globalMenu); frame->console->applyTheme(); @@ -187,6 +189,7 @@ PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() { fileEntry->addItem("New File", "new_file", KEY_n); fileEntry->addItem("New Project", "new_project", KEY_LSHIFT, KEY_n); fileEntry->addItem("New Folder", "new_folder", KEY_LSHIFT, KEY_f); + fileEntry->addItem("Open File", "open_file", KEY_o); fileEntry->addItem("Open Project", "open_project", KEY_LSHIFT, KEY_o); fileEntry->addItem("Close Project", "close_project", KEY_LSHIFT, KEY_w); fileEntry->addItem("Close File", "close_file", KEY_w); @@ -703,6 +706,25 @@ void PolycodeIDEApp::openFile(OSFileEntry file) { } } +void PolycodeIDEApp::openFilePicker() { + std::vector extensions = editorManager->getExtensionsWithEditor(); + #ifdef USE_POLYCODEUI_FILE_DIALOGS + std::vector exts; + for(int e = 0; e < extensions.size(); e++){ + exts.push_back((extensions[e].extension)); + } + frame->showFileBrowser(CoreServices::getInstance()->getCore()->getUserHomeDirectory(), false, exts, false); + frame->fileDialog->addEventListener(this, UIEvent::OK_EVENT); + frame->fileDialog->action = "openFile"; +#else + extensions.insert(extensions.begin(), CoreFileExtension("All Types", "*")); + std::vector filePaths = core->openFilePicker(extensions, true); + for (int f = 0; f < filePaths.size(); f++){ + openFile(OSFileEntry(filePaths[f], OSFileEntry::TYPE_FILE)); + } +#endif +} + void PolycodeIDEApp::handleEvent(Event *event) { if(event->getDispatcher() == frame->assetImporterWindow) { @@ -758,6 +780,8 @@ void PolycodeIDEApp::handleEvent(Event *event) { frame->assetImporterWindow->setSourceFileAndTargetFolder(path, projectManager->activeFolder, projectManager->activeFolder.replace(projectManager->getActiveProject()->getRootFolder(), "")); frame->showModal(frame->assetImporterWindow); frame->assetImporterWindow->addEventListener(this, UIEvent::OK_EVENT); + } else if(frame->fileDialog->action == "openFile") { + openFile(OSFileEntry(path, OSFileEntry::TYPE_FILE)); } } } @@ -772,7 +796,9 @@ void PolycodeIDEApp::handleEvent(Event *event) { newProject(); } else if(action == "new_folder") { newGroup(); - } else if(action == "open_project") { + } else if (action == "open_file") { + openFilePicker(); + } else if (action == "open_project") { openProject(); } else if(action == "close_project") { closeProject(); diff --git a/IDE/Contents/Source/PolycodeMaterialEditor.cpp b/IDE/Contents/Source/PolycodeMaterialEditor.cpp index 107a9c96b..ff1dbbcba 100644 --- a/IDE/Contents/Source/PolycodeMaterialEditor.cpp +++ b/IDE/Contents/Source/PolycodeMaterialEditor.cpp @@ -826,7 +826,7 @@ void MaterialPreviewBox::handleEvent(Event *event) { } } -MaterialPreviewProp::MaterialPreviewProp() : PropProp("", "") { +MaterialPreviewProp::MaterialPreviewProp() : PropProp("", PropProp::PROP_MATERIAL_PREVIEW) { previewBox = new MaterialPreviewBox(); propContents->addChild(previewBox); setHeight(300); diff --git a/IDE/Contents/Source/PolycodePluginEditor.cpp b/IDE/Contents/Source/PolycodePluginEditor.cpp new file mode 100644 index 000000000..0b542a0ef --- /dev/null +++ b/IDE/Contents/Source/PolycodePluginEditor.cpp @@ -0,0 +1,490 @@ +/* +Copyright (C) 2014 by Joachim Meyer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "PolycodePluginEditor.h" +#include "PolyPluginManager.h" + +using namespace Polycode; + +PluginBrowser::PluginBrowser() : UIElement() { + treeContainer = new UITreeContainer("boxIcon.png", L"Polycode Plugins", 200, 555); + treeContainer->getRootNode()->toggleCollapsed(); + treeContainer->getRootNode()->addEventListener(this, UITreeEvent::SELECTED_EVENT); + treeContainer->addEventListener(this, InputEvent::EVENT_MOUSEDOWN); + + pluginNode = treeContainer->getRootNode()->addTreeChild("pluginEditor/plugin_icon.png", "Plugins", NULL); + + addChild(treeContainer); + selectedData = NULL; + + headerBg = new UIRect(10, 10); + addChild(headerBg); + headerBg->setAnchorPoint(-1.0, -1.0, 0.0); + headerBg->color.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiHeaderBgColor")); + + newPluginButton = new UIImageButton("pluginEditor/new_plugin.png", 1.0, 22, 22); + addChild(newPluginButton); + newPluginButton->setPosition(5, 4); + + removeButton = new UIImageButton("main/remove_icon.png", 1.0, 12, 12); + addChild(removeButton); + removeButton->setPosition(0, 4); + + selectedNode = NULL; +} + +PluginBrowser::~PluginBrowser() {} + +void PluginBrowser::removeSelected() { + selectedNode->getParent()->removeTreeChild(selectedNode); +} + +void PluginBrowser::handleEvent(Event *event) { + + if (event->getDispatcher() == treeContainer->getRootNode()) { + if (event->getEventCode() == UITreeEvent::SELECTED_EVENT) { + selectedNode = treeContainer->getRootNode()->getSelectedNode(); + PluginBrowserData *data = (PluginBrowserData *)selectedNode->getUserData(); + selectedData = data; + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + } + Entity::handleEvent(event); +} + + +UITree *PluginBrowser::addPlugin(Plugin *plugin) { + PluginBrowserData *data = new PluginBrowserData(); + data->plugin = plugin; + return pluginNode->addTreeChild("pluginEditor/plugin_icon.png", plugin->getResourceName(), (void*)data); +} + +void PluginBrowser::Resize(Number width, Number height) { + treeContainer->Resize(width, height - 30); + treeContainer->setPosition(0, 30); + headerBg->Resize(width, 30); + removeButton->setPosition(width - 24, 8); +} + + +PluginEditorPane::PluginEditorPane(ResourcePool *resourcePool) : UIElement() { + + this->resourcePool = resourcePool; + changingPlugin = false; + currentPlugin = NULL; + + headerBg = new UIRect(10, 10); + addChild(headerBg); + headerBg->setAnchorPoint(-1.0, -1.0, 0.0); + headerBg->color.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiHeaderBgColor")); + + propList = new PropList("PLUGIN EDITOR"); + addChild(propList); + propList->setPosition(0, 0); + + PropSheet *baseProps = new PropSheet("PLUGIN SETTINGS", ""); + propList->addPropSheet(baseProps); + + nameProp = new StringProp("Name:"); + baseProps->addProp(nameProp); + nameProp->addEventListener(this, Event::CHANGE_EVENT); + + author = new StringProp("Author:"); + baseProps->addProp(author); + author->addEventListener(this, Event::CHANGE_EVENT); + + addPropButton = new ButtonProp("New Prop"); + baseProps->addProp(addPropButton); + addPropButton->getButton()->addEventListener(this, UIEvent::CLICK_EVENT); + + baseProps->propHeight = 220; + + propsSheet = new PropSheet("PROPS", ""); + propList->addPropSheet(propsSheet); + + propList->updateProps(); + propList->Resize(propList->getWidth(), propList->getHeight()); + + enabled = false; +} + +PluginEditorPane::~PluginEditorPane() {} + +void PluginEditorPane::handleEvent(Event *event) { + if (!changingPlugin) { + + if (event->getDispatcher() == nameProp) { + currentPlugin->setResourceName(nameProp->get()); + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + + if (event->getDispatcher() == author) { + currentPlugin->author = author->get(); + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + + int maxPadding = 0; + for (int p = 0; p < propsSheet->props.size(); p++){ + if (event->getEventCode() == Event::CHANGE_EVENT && event->getDispatcher() == propsSheet->props[p]) { + currentPlugin->getProps()[p]->name = propsSheet->props[p]->getPropName(); + currentPlugin->getProps()[p]->type = ((PropEditProp*)propsSheet->props[p])->getPropType(); + if (currentPlugin->getProps()[p]->type == Prop::PROP_COMBO){ + currentPlugin->getProps()[p]->children.clear(); + for (int c = 0; c < ((PropEditProp*)propsSheet->props[p])->comboEditProp->currentCombo->comboEntry->getNumItems(); c++){ + Prop* newProp = new Prop(((PropEditProp*)propsSheet->props[p])->comboEditProp->currentCombo->comboEntry->getItemAtIndex(c)->label, Prop::PROP_COMBO); + newProp->value = (int)((PropEditProp*)propsSheet->props[p])->comboEditProp->currentCombo->comboEntry->getItemAtIndex(c)->data; + currentPlugin->getProps()[p]->children.push_back(newProp); + } + } else if (currentPlugin->getProps()[p]->type == Prop::PROP_SLIDER){ + currentPlugin->getProps()[p]->children.clear(); + Prop* newProp = new Prop("min", Prop::PROP_SLIDER); + newProp->value = ((PropEditProp*)propsSheet->props[p])->sliderEditProp->currentSlider->slider->getStart(); + currentPlugin->getProps()[p]->children.push_back(newProp); + newProp = new Prop("max", Prop::PROP_SLIDER); + newProp->value = ((PropEditProp*)propsSheet->props[p])->sliderEditProp->currentSlider->slider->getEnd(); + currentPlugin->getProps()[p]->children.push_back(newProp); + } + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + + if (((PropEditProp*)propsSheet->props[p])->updatePadding() > maxPadding){ + maxPadding = ((PropEditProp*)propsSheet->props[p])->updatePadding(); + } + + if (event->getEventCode() == Event::REMOVE_EVENT && event->getDispatcher() == propsSheet->props[p]){ + currentPlugin->removeProp(propsSheet->props[p]->getPropName()); + propsSheet->removeProp(propsSheet->props[p]); + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + } + + padding = maxPadding + 20; + + if (padding < (propList->getWidth() - 370)){ + for (int p = 0; p < propsSheet->props.size(); p++){ + propsSheet->props[p]->propContents->setPositionX(padding); + } + } + + if (event->getDispatcher() == addPropButton->getButton()) { + PropEditProp *newProp = new PropEditProp(new PropProp("", 0)); + propsSheet->addProp(newProp); + currentPlugin->setProp(new Prop("", 0)); + newProp->addEventListener(this, Event::CHANGE_EVENT); + newProp->addEventListener(this, Event::REMOVE_EVENT); + newProp->propContents->setPositionX(padding); + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + + if (event->getEventCode() == Event::CHANGE_EVENT){ + propList->Resize(propList->getWidth(), propList->getHeight()); + } + } +} + +void PluginEditorPane::setPlugin(Plugin *plugin) { + for (int p = propsSheet->props.size(); p > 0; p--){ + propsSheet->removeProp(propsSheet->props[p - 1]); + } + changingPlugin = true; + + currentPlugin = plugin; + + nameProp->set(plugin->getResourceName()); + author->set(plugin->author); + + for (int p = 0; p < plugin->getProps().size(); p++) { + Prop* propEntry = plugin->getProps()[p]; + if (propEntry->type == PropProp::PROP_COMBO){ + ComboProp *newComboProp = new ComboProp(propEntry->name); + for (int c = 0; c < propEntry->children.size(); c++){ + Prop *comboEntry = propEntry->children[c]; + newComboProp->comboEntry->addComboItem(comboEntry->name, (void*)comboEntry->value); + } + setProp(newComboProp->getPropName(), newComboProp); + } else if (propEntry->type == PropProp::PROP_SLIDER) { + SliderProp *newSliderProp = new SliderProp(propEntry->name, 0, 0); + Number min, max; + for (int s = 0; s < propEntry->children.size(); s++){ + Prop *sliderEntry = propEntry->children[s]; + if (sliderEntry->name == "min"){ + min = sliderEntry->value; + } else if (sliderEntry->name == "max"){ + max = sliderEntry->value; + } + } + newSliderProp->slider->setStartEnd(min, max); + setProp(newSliderProp->getPropName(), newSliderProp); + } else { + setProp(propEntry->name, new PropProp(propEntry->name, propEntry->type)); + } + } + + + for (int p = 0; p < propsSheet->props.size(); p++){ + propsSheet->props[p]->propContents->setPositionX(padding); + } + propList->Resize(propList->getWidth(), propList->getHeight()); + + enabled = true; + + changingPlugin = false; +} + +void PluginEditorPane::Resize(Number width, Number height) { + headerBg->Resize(width, 30); + propList->Resize(width, height); + propList->updateProps(); + +} + +std::vector PluginEditorPane::getProps() { + return propsSheet->props; +} + +void PluginEditorPane::setProp(const String& name, PropProp* prop){ + for (int i = 0; i < propsSheet->props.size(); i++) { + if (propsSheet->props[i]->getPropName() == name) { + PropEditProp *newProp = new PropEditProp(prop); + propsSheet->props[i] = newProp; + if (((PropEditProp*)newProp)->updatePadding() > (padding - 20)) + padding = ((PropEditProp*)newProp)->updatePadding() + 20; + newProp->addEventListener(this, Event::CHANGE_EVENT); + newProp->addEventListener(this, Event::REMOVE_EVENT); + currentPlugin->getProps()[i]->name = name; + currentPlugin->getProps()[i]->type = prop->propType; + if (currentPlugin->getProps()[i]->type == Prop::PROP_COMBO){ + currentPlugin->getProps()[i]->children.clear(); + for (int c = 0; c < ((ComboProp*)prop)->comboEntry->getNumItems(); c++){ + Prop* newProp = new Prop(((ComboProp*)prop)->comboEntry->getItemAtIndex(c)->label, Prop::PROP_COMBO); + newProp->value = (int)((ComboProp*)prop)->comboEntry->getItemAtIndex(c)->data; + currentPlugin->getProps()[i]->children.push_back(newProp); + } + } else if (currentPlugin->getProps()[i]->type == Prop::PROP_SLIDER){ + currentPlugin->getProps()[i]->children.clear(); + Prop* newProp = new Prop("min", Prop::PROP_SLIDER); + newProp->value = ((SliderProp*)prop)->slider->getStart(); + currentPlugin->getProps()[i]->children.push_back(newProp); + newProp = new Prop("max", Prop::PROP_SLIDER); + newProp->value = ((SliderProp*)prop)->slider->getEnd(); + currentPlugin->getProps()[i]->children.push_back(newProp); + } + return; + } + } + + PropEditProp *newProp = new PropEditProp(prop); + if (((PropEditProp*)newProp)->updatePadding() > (padding - 20)) + padding = ((PropEditProp*)newProp)->updatePadding() + 20; + propsSheet->addProp(newProp); + newProp->addEventListener(this, Event::CHANGE_EVENT); + newProp->addEventListener(this, Event::REMOVE_EVENT); + Prop* pProp = new Prop(name, prop->propType); + if (prop->propType == Prop::PROP_COMBO){ + for (int c = 0; c < ((ComboProp*)prop)->comboEntry->getNumItems(); c++){ + Prop* comboProp = new Prop(((ComboProp*)prop)->comboEntry->getItemAtIndex(c)->label, Prop::PROP_COMBO); + comboProp->value = (int)((ComboProp*)prop)->comboEntry->getItemAtIndex(c)->data; + pProp->children.push_back(comboProp); + } + } else if (prop->propType == Prop::PROP_SLIDER){ + Prop* sliderProp = new Prop("min", Prop::PROP_SLIDER); + sliderProp->value = ((SliderProp*)prop)->slider->getStart(); + pProp->children.push_back(sliderProp); + sliderProp = new Prop("max", Prop::PROP_SLIDER); + sliderProp->value = ((SliderProp*)prop)->slider->getEnd(); + pProp->children.push_back(sliderProp); + } + currentPlugin->setProp(pProp); +} + +PluginMainWindow::PluginMainWindow(ResourcePool *resourcePool) : UIElement() { + + pluginPane = new PluginEditorPane(resourcePool); + + ownsChildren = true; + + addChild(pluginPane); +} + +PluginMainWindow::~PluginMainWindow() {} + +void PluginMainWindow::Resize(Number width, Number height) { + Vector2 pos = getScreenPositionForMainCamera(); + scissorBox.setRect(pos.x, pos.y, width, height); + pluginPane->Resize(width, height); +} + +PolycodePluginEditor::PolycodePluginEditor() : PolycodeEditor(true) { + selectedPluginNode = NULL; +} + +PolycodePluginEditor::~PolycodePluginEditor() { + delete resourcePool; + + mainWindow->setOwnsChildrenRecursive(true); + delete mainWindow; + delete mainSizer; + delete pluginBrowser; +} + +bool PolycodePluginEditor::openFile(OSFileEntry filePath) { + this->filePath = filePath; + + mainSizer = new UIHSizer(100, 100, 200, false); + addChild(mainSizer); + + pluginBrowser = new PluginBrowser(); + mainSizer->addRightChild(pluginBrowser); + + pluginBrowser->addEventListener(this, Event::CHANGE_EVENT); + + String resourceName = filePath.fullPath.replace(parentProject->getRootFolder() + "/", ""); + + resourcePool = CoreServices::getInstance()->getResourceManager()->getResourcePoolByName(resourceName); + + if (!resourcePool) { + resourcePool = new ResourcePool(resourceName, CoreServices::getInstance()->getResourceManager()->getGlobalPool()); + resourcePool->reloadResourcesOnModify = true; + resourcePool->deleteOnUnsubscribe = true; + CoreServices::getInstance()->getPluginManager()->loadPluginLibraryIntoPool(resourcePool, filePath.fullPath); + CoreServices::getInstance()->getResourceManager()->addResourcePool(resourcePool); + } + + CoreServices::getInstance()->getResourceManager()->subscribeToResourcePool(resourcePool); + + mainWindow = new PluginMainWindow(resourcePool); + mainSizer->addLeftChild(mainWindow); + + for (int i = 0; i < resourcePool->getResources(Resource::RESOURCE_PLUGIN).size(); i++) { + Plugin *plugin = (Plugin*)resourcePool->getResources(Resource::RESOURCE_PLUGIN)[i]; + pluginBrowser->addPlugin(plugin); + } + + mainWindow->pluginPane->addEventListener(this, Event::CHANGE_EVENT); + + pluginBrowser->newPluginButton->addEventListener(this, UIEvent::CLICK_EVENT); + pluginBrowser->removeButton->addEventListener(this, UIEvent::CLICK_EVENT); + + mainWindow->pluginPane->addEventListener(this, Event::CHANGE_EVENT); + + PolycodeEditor::openFile(filePath); + return true; +} + +void PolycodePluginEditor::saveFile() { + Object saveFile; + saveFile.root.name = "plugins"; + saveFile.root.addChild("version", 1); + for (int p = 0; p < resourcePool->getResources(Resource::RESOURCE_PLUGIN).size(); p++) { + ObjectEntry* pluginEntry = saveFile.root.addChild("plugin"); + savePluginToObjectEntry((Plugin*)resourcePool->getResources(Resource::RESOURCE_PLUGIN)[p], pluginEntry); + } + saveFile.saveToXML(filePath.fullPath); + setHasChanges(false); +} + +void PolycodePluginEditor::savePluginToObjectEntry(Plugin* plugin, ObjectEntry* entry) { + entry->addChild("name", plugin->getResourceName()); + entry->addChild("author", plugin->author); + entry->addChild("fileext", plugin->ext); + entry->addChild("type", (int)plugin->pluginType); + + ObjectEntry* sheetEntry = entry->addChild("sheet"); + ObjectEntry* propsEntry = sheetEntry->addChild("props"); + std::vector props = plugin->getProps(); + for (int i = 0; i < props.size(); i++) { + ObjectEntry* propEntry = propsEntry->addChild("prop"); + propEntry->addChild("type", props[i]->type); + propEntry->addChild("name", props[i]->name); + if (props[i]->type == PropProp::PROP_COMBO){ + for (int c = 0; c < props[i]->children.size(); c++){ + ObjectEntry *comboEntry = propEntry->addChild("prop"); + comboEntry->addChild("name", props[i]->children[c]->name); + comboEntry->addChild("value", props[i]->children[c]->value); + } + } else if (props[i]->type == PropProp::PROP_SLIDER){ + for (int s = 0; s < props[i]->children.size(); s++){ + if (props[i]->children[s]->name == "min"){ + ObjectEntry* min = propEntry->addChild("prop"); + min->addChild("name", props[i]->children[s]->name); + min->addChild("value", props[i]->children[s]->value); + } else if (props[i]->children[s]->name == "max"){ + ObjectEntry* max = propEntry->addChild("prop"); + max->addChild("name", props[i]->children[s]->name); + max->addChild("value", props[i]->children[s]->value); + } + } + } + } +} + +void PolycodePluginEditor::handleEvent(Event *event) { + + if (event->getDispatcher() == mainWindow->pluginPane && event->getEventType() == "" && event->getEventCode() == Event::CHANGE_EVENT) { + if (selectedPluginNode && mainWindow->pluginPane->currentPlugin) { + selectedPluginNode->setLabelText(mainWindow->pluginPane->currentPlugin->getResourceName()); + } + setHasChanges(true); + } + + if (event->getDispatcher() == pluginBrowser->newPluginButton && event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::CLICK_EVENT) { + Plugin *newPlugin = new Plugin("New Plugin"); + pluginBrowser->addPlugin(newPlugin)->setSelected(); + resourcePool->addResource(newPlugin); + setHasChanges(true); + } + + if (event->getDispatcher() == pluginBrowser->removeButton && event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::CLICK_EVENT) { + + mainWindow->pluginPane->enabled = false; + + if (pluginBrowser->selectedData->plugin) { + for (int i = 0; i < resourcePool->getResources(Resource::RESOURCE_PLUGIN).size(); i++) { + if ((Plugin*)resourcePool->getResources(Resource::RESOURCE_PLUGIN)[i] == pluginBrowser->selectedData->plugin) { + resourcePool->removeResource(resourcePool->getResource(Resource::RESOURCE_PLUGIN, pluginBrowser->selectedData->plugin->getResourceName())); + pluginBrowser->removeSelected(); + break; + } + } + } + setHasChanges(true); + } + + if (event->getDispatcher() == pluginBrowser) { + if (event->getEventType() == "" && event->getEventCode() == Event::CHANGE_EVENT) { + if (pluginBrowser->selectedData) { + mainWindow->pluginPane->enabled = false; + + if (pluginBrowser->selectedData->plugin) { + selectedPluginNode = pluginBrowser->selectedNode; + mainWindow->pluginPane->setPlugin(pluginBrowser->selectedData->plugin); + } + + } + } + } +} + +void PolycodePluginEditor::Resize(int x, int y) { + mainSizer->Resize(((Number)x), ((Number)y)); + PolycodeEditor::Resize(((Number)x), ((Number)y)); +} diff --git a/IDE/Contents/Source/PolycodeProps.cpp b/IDE/Contents/Source/PolycodeProps.cpp index 097df0a6f..3b1b519cd 100644 --- a/IDE/Contents/Source/PolycodeProps.cpp +++ b/IDE/Contents/Source/PolycodeProps.cpp @@ -23,6 +23,7 @@ #include "PolycodeProps.h" #include "PolycodeFrame.h" #include "PolyCubemap.h" +#include "PolyUIComboBox.h" extern UIColorPicker *globalColorPicker; extern PolycodeFrame *globalFrame; @@ -324,6 +325,18 @@ void PropSheet::addProp(PropProp *prop) { Resize(getWidth(), getHeight()); } +void PropSheet::removeProp(PropProp *prop) { + contents->removeChild(prop); + prop->removeAllHandlers(); + + for (int p = 0; p < props.size(); p++){ + if (props[p] == prop){ + props.erase(props.begin() + p); + } + } + + Resize(getWidth(), getHeight()); +} void PropSheet::applyPropActionData(PolycodeEditorPropActionData *data) { data->prop->setPropData(data); @@ -333,7 +346,11 @@ void PropProp::setPropName(String newName) { label->setText(newName); } -PropProp::PropProp(String caption, String type) : UIElement() { +String PropProp::getPropName() { + return label->getText(); +} + +PropProp::PropProp(String caption, int type) : UIElement() { suppressChangeEvent = false; propType = type; @@ -353,7 +370,7 @@ PropProp::~PropProp() { } -ButtonProp::ButtonProp(const String &caption) : PropProp("", "ButtonProp") { +ButtonProp::ButtonProp(const String &caption) : PropProp("", PropProp::PROP_BUTTON) { button = new UIButton(caption, 100); addChild(button); setHeight(25); @@ -372,7 +389,7 @@ void ButtonProp::setPropWidth(Number width) { } -Vector3Prop::Vector3Prop(String caption) : PropProp(caption, "Vector3") { +Vector3Prop::Vector3Prop(String caption) : PropProp(caption, PropProp::PROP_VECTOR3) { xInput = NULL; yInput = NULL; @@ -463,7 +480,7 @@ Vector3Prop::~Vector3Prop() { } -Vector2Prop::Vector2Prop(String caption) : PropProp(caption, "Vector2") { +Vector2Prop::Vector2Prop(String caption) : PropProp(caption, PropProp::PROP_VECTOR2) { labelX = new UILabel("X:", 11); labelX->color.a = 1.0; @@ -545,7 +562,7 @@ Vector2Prop::~Vector2Prop() { } -RemovableStringProp::RemovableStringProp(const String &caption) : PropProp("", "RemovableStringProp") { +RemovableStringProp::RemovableStringProp(const String &caption) : PropProp("", PropProp::PROP_REMOVABLE_STRING){ label = new UILabel(caption, 12); addChild(label); @@ -573,7 +590,7 @@ void RemovableStringProp::handleEvent(Event *event) { } } -LayerProp::LayerProp(SceneEntityInstance *instance, SceneEntityInstanceLayer *layer) : PropProp("", "Layer") { +LayerProp::LayerProp(SceneEntityInstance *instance, SceneEntityInstanceLayer *layer) : PropProp("", PropProp::PROP_LAYER) { layerID = 0; bgRect = new UIRect(1.0, 1.0); @@ -697,23 +714,18 @@ void LayerProp::setPropWidth(Number width) { removeLayerButton->setPosition(width-PROP_PADDING-propContents->getPosition().x-20, 5.0); } -CustomProp::CustomProp(String key, String value) : PropProp("", "Custom") { - keyEntry = new UITextInput(false, 120, 12); +CustomProp::CustomProp(String key, String value) : PropProp("", PropProp::PROP_CUSTOM) { + keyEntry = new UITextInput(false, 130, 12); keyEntry->setText(key); keyEntry->addEventListener(this, UIEvent::CHANGE_EVENT); propContents->addChild(keyEntry); - keyEntry->setPosition(-90, 0); + keyEntry->setPosition(-110, 0); - valueEntry = new UITextInput(false, 120, 12); + valueEntry = new UITextInput(false, 140, 12); valueEntry->setText(value); valueEntry->addEventListener(this, UIEvent::CHANGE_EVENT); propContents->addChild(valueEntry); - valueEntry->setPosition(45, 0); - - removeButton = new UIImageButton("main/remove_icon.png", 1.0, 12, 12); - removeButton->addEventListener(this, UIEvent::CLICK_EVENT); - propContents->addChild(removeButton); - removeButton->setPosition(-110, 6); + valueEntry->setPosition(55, 0); setHeight(25); @@ -729,7 +741,6 @@ void CustomProp::setPropWidth(Number width) { CustomProp::~CustomProp() { keyEntry->removeAllHandlersForListener(this); valueEntry->removeAllHandlersForListener(this); - removeButton->removeAllHandlersForListener(this); } void CustomProp::handleEvent(Event *event) { @@ -740,9 +751,6 @@ void CustomProp::handleEvent(Event *event) { dispatchEvent(new Event(), Event::CHANGE_EVENT); } - if(event->getDispatcher() == removeButton) { - dispatchEvent(new Event(), Event::CANCEL_EVENT); - } } } @@ -758,7 +766,7 @@ String CustomProp::getKey() { } -StringProp::StringProp(String caption) : PropProp(caption, "String") { +StringProp::StringProp(String caption) : PropProp(caption, PropProp::PROP_STRING) { stringEntry = new UITextInput(false, 150, 12); stringEntry->addEventListener(this, UIEvent::CHANGE_EVENT); @@ -807,7 +815,7 @@ StringProp::~StringProp() { } -SliderProp::SliderProp(String caption, Number min, Number max) : PropProp(caption, "Slider") { +SliderProp::SliderProp(String caption, Number min, Number max) : PropProp(caption, PropProp::PROP_SLIDER) { slider = new UIHSlider(min, max, 100); slider->addEventListener(this, UIEvent::CHANGE_EVENT); @@ -866,7 +874,7 @@ SliderProp::~SliderProp() { } -NumberProp::NumberProp(String caption) : PropProp(caption, "Number") { +NumberProp::NumberProp(String caption) : PropProp(caption, PropProp::PROP_NUMBER) { numberEntry = new UITextInput(false, 50, 20); numberEntry->addEventListener(this, UIEvent::CHANGE_EVENT); @@ -918,7 +926,7 @@ NumberProp::~NumberProp() { } -ColorProp::ColorProp(String caption) : PropProp(caption, "Color") { +ColorProp::ColorProp(String caption) : PropProp(caption, PropProp::PROP_COLOR) { colorEntry = new UIColorBox(globalColorPicker, Color(), 45, 25); colorEntry->addEventListener(this, UIEvent::CHANGE_EVENT); @@ -965,7 +973,7 @@ ColorProp::~ColorProp() { } -ComboProp::ComboProp(String caption) : PropProp(caption, "Combo") { +ComboProp::ComboProp(String caption) : PropProp(caption, PropProp::PROP_COMBO) { comboEntry = new UIComboBox(globalMenu, 150); comboEntry->addEventListener(this, UIEvent::CHANGE_EVENT); propContents->addChild(comboEntry); @@ -1010,7 +1018,7 @@ ComboProp::~ComboProp() { } -BoolProp::BoolProp(String caption) : PropProp(caption, "Bool") { +BoolProp::BoolProp(String caption) : PropProp(caption, PropProp::PROP_BOOL) { checkEntry = new UICheckBox("", false); checkEntry->addEventListener(this, UIEvent::CHANGE_EVENT); @@ -1052,7 +1060,7 @@ BoolProp::~BoolProp() { } -SoundProp::SoundProp(String caption) : PropProp(caption, "Sound"){ +SoundProp::SoundProp(String caption) : PropProp(caption, PropProp::PROP_SOUND) { soundFile = new UILabel("", 11); soundFile->setPosition(0, 5); @@ -1135,7 +1143,7 @@ String SoundProp::get() { return ""; } -BezierRGBACurveProp::BezierRGBACurveProp(String caption) : PropProp(caption, "BezierRGBA") { +BezierRGBACurveProp::BezierRGBACurveProp(String caption) : PropProp(caption, PropProp::PROP_BEZIER_RGBA_CURVE) { changeButton = new UIButton("Edit", 120); @@ -1162,13 +1170,13 @@ void BezierRGBACurveProp::handleEvent(Event *event) { globalFrame->curveEditor->addCurve("Red", curveR, Color(1.0, 0.0, 0.0, 1.0)); globalFrame->curveEditor->addCurve("Green", curveG, Color(0.0, 1.0, 0.0, 1.0)); globalFrame->curveEditor->addCurve("Blue", curveB, Color(0.0, 0.0, 1.0, 1.0)); - globalFrame->curveEditor->addCurve("Alpha", curveA, Color(1.0, 1.0, 1.0, 1.0)); + globalFrame->curveEditor->addCurve("Alpha", curveA, Color(1.0, 1.0, 1.0, 1.0)); globalFrame->showCurveEditor(); } } } -BezierCurveProp::BezierCurveProp(String caption, String curveName) : PropProp(caption, "BezierCurve") { +BezierCurveProp::BezierCurveProp(String caption, String curveName) : PropProp(caption, PropProp::PROP_BEZIER_CURVE) { this->curveName = curveName; @@ -1196,7 +1204,7 @@ void BezierCurveProp::handleEvent(Event *event) { } } -MaterialProp::MaterialProp(const String &caption) : PropProp(caption, "Material"){ +MaterialProp::MaterialProp(const String &caption) : PropProp(caption, PropProp::PROP_MATERIAL) { currentMaterial = NULL; previewShape = new UIRect(48, 48); @@ -1314,7 +1322,7 @@ void MaterialProp::setPropWidth(Number width) { } -TextureProp::TextureProp(String caption) : PropProp(caption, "Texture"){ +TextureProp::TextureProp(String caption) : PropProp(caption, PropProp::PROP_TEXTURE) { previewShape = new UIRect(48, 48); previewShape->setAnchorPoint(-1.0, -1.0, 0.0); previewShape->setPosition(2, 1); @@ -1389,7 +1397,7 @@ Texture* TextureProp::get() { return previewShape->getTexture(); } -SceneSpriteProp::SceneSpriteProp(String caption) : PropProp(caption, "SceneSprite"){ +SceneSpriteProp::SceneSpriteProp(String caption) : PropProp(caption, PropProp::PROP_SCENE_SPRITE) { previewSprite = NULL; @@ -1500,7 +1508,7 @@ Sprite *SceneSpriteProp::get() { return sprite; } -SceneEntityInstanceProp::SceneEntityInstanceProp(String caption) : PropProp(caption, "SceneEntityInstance"){ +SceneEntityInstanceProp::SceneEntityInstanceProp(String caption) : PropProp(caption, PropProp::PROP_SCENE_ENTITY_INSTANCE){ // previewInstance = new SceneEntityInstance("default/default.entity"); previewInstance->setAnchorPoint(-1.0, -1.0, 0.0); previewInstance->setPosition(2, 1); @@ -1565,7 +1573,7 @@ String SceneEntityInstanceProp::get() { return previewInstance->getFileName(); } -ShaderPassProp::ShaderPassProp(Material *material, int shaderIndex) : PropProp("", "ShaderPassProp") { +ShaderPassProp::ShaderPassProp(Material *material, int shaderIndex) : PropProp("", PropProp::PROP_SHADER_PASS) { this->material = material; this->shader = material->getShader(shaderIndex); this->shaderIndex = shaderIndex; @@ -1629,7 +1637,7 @@ void ShaderPassProp::setPropWidth(Number width) { editButton->Resize(floor(adjustedWidth * 0.25), editButton->getHeight()); } -TargetBindingProp::TargetBindingProp(Shader *shader, Material *material, ShaderBinding *binding, RenderTargetBinding *targetBinding) : PropProp("", "TargetBindingProp") { +TargetBindingProp::TargetBindingProp(Shader *shader, Material *material, ShaderBinding *binding, RenderTargetBinding *targetBinding) : PropProp("", PropProp::PROP_TARGET_BINDING) { this->targetBinding = targetBinding; this->material = material; this->shader = shader; @@ -1763,7 +1771,7 @@ void TargetBindingProp::setPropWidth(Number width) { } -RenderTargetProp::RenderTargetProp(ShaderRenderTarget *renderTarget, Material *material) : PropProp("", "RenderTargetProp") { +RenderTargetProp::RenderTargetProp(ShaderRenderTarget *renderTarget, Material *material) : PropProp("", PropProp::PROP_RENDER_TARGET) { this->material = material; this->renderTarget = renderTarget; @@ -1862,6 +1870,362 @@ void RenderTargetProp::handleEvent(Event *event) { PropProp::handleEvent(event); } +PropEditProp::PropEditProp(PropProp *newProp) : PropProp(newProp->getPropName(), PropProp::PROP_EDIT) { + nameInput = NULL; + typeChooser = NULL; + + nameLabel = new UILabel("Name:", 11); + nameLabel->color.a = 1.0; + propContents->addChild(nameLabel); + nameLabel->setPosition(0, 5); + + typeLabel = new UIMultilineLabel("Type:\n(ni) = not implemented", 11, 7); + typeLabel->color.a = 1.0; + propContents->addChild(typeLabel); + typeLabel->setPosition(0, 27); + + delButton = new UIImageButton("main/remove_icon.png", 1.0, 12, 12); + delButton->addEventListener(this, UIEvent::CLICK_EVENT); + addChild(delButton); + delButton->setPosition(0, 25); + + nameInput = new UITextInput(false, 200, 12); + nameInput->addEventListener(this, UIEvent::CHANGE_EVENT); + nameInput->setText(newProp->getPropName()); + propContents->addChild(nameInput); + nameInput->setPosition(70, 0); + + typeChooser = new UIComboBox(globalMenu, 200); + typeChooser->addComboItem("Vector3", (void*)0); + typeChooser->addComboItem("Vector2", (void*)1); + typeChooser->addComboItem("Slider", (void*)2); + typeChooser->addComboItem("Button (ni)", (void*)3); + typeChooser->addComboItem("Number", (void*)4); + typeChooser->addComboItem("Target Binding (ni)",(void*)5); + typeChooser->addComboItem("Render Target (ni)",(void*)6); + typeChooser->addComboItem("Shader Pass (ni)", (void*)7); + typeChooser->addComboItem("Removable String", (void*)8); + typeChooser->addComboItem("Layer (ni)", (void*)9); + typeChooser->addComboItem("Custom", (void*)10); + typeChooser->addComboItem("String", (void*)11); + typeChooser->addComboItem("Color", (void*)12); + typeChooser->addComboItem("Combo", (void*)13); + typeChooser->addComboItem("Bool", (void*)14); + typeChooser->addComboItem("Sound", (void*)15); + typeChooser->addComboItem("Bezier RGBA Curve (ni)", (void*)16); + typeChooser->addComboItem("Bezier Curve (ni)", (void*)17); + typeChooser->addComboItem("Material", (void*)18); + typeChooser->addComboItem("Material Preview", (void*)19); + typeChooser->addComboItem("Texture", (void*)20); + typeChooser->addComboItem("Scene Sprite", (void*)21); + typeChooser->addComboItem("Scene Entity Instance", (void*)22); + typeChooser->setSelectedIndex(newProp->propType); + typeChooser->addEventListener(this, UIEvent::CHANGE_EVENT); + propContents->addChild(typeChooser); + typeChooser->setPosition(70, 25); + + currentValue = newProp->propType; + setHeight(65); + + if (currentValue != PropProp::PROP_COMBO){ + comboEditProp = new ComboPropEditProp(new ComboProp(nameInput->getText())); + comboEditProp->enabled = false; + comboEditProp->visible = false; + } else { + comboEditProp = new ComboPropEditProp(((ComboProp*)newProp)); + setHeight(80 + comboEditProp->getHeight()); + } + comboEditProp->addEventListener(this, Event::CHANGE_EVENT); + propContents->addChild(comboEditProp); + comboEditProp->setPosition(-80, 60); + + if (currentValue != PropProp::PROP_SLIDER){ + sliderEditProp = new SliderEditProp(new SliderProp(nameInput->getText(), 0, 0)); + sliderEditProp->enabled = false; + sliderEditProp->visible = false; + } else { + sliderEditProp = new SliderEditProp(((SliderProp*)newProp)); + setHeight(80 + sliderEditProp->getHeight()); + } + sliderEditProp->addEventListener(this, Event::CHANGE_EVENT); + propContents->addChild(sliderEditProp); + sliderEditProp->setPosition(-80, 60); +} + +PropEditProp::~PropEditProp(){} + +void PropEditProp::handleEvent(Event *event){ + if (event->getDispatcher() == typeChooser) { + if (event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::CHANGE_EVENT) { + lastValue = currentValue; + currentValue = typeChooser->getSelectedIndex(); + if (!suppressChangeEvent) { + dispatchEvent(new Event(), Event::CHANGE_EVENT); + dispatchEvent(new PropEvent(this, NULL, PropDataInt(lastValue), PropDataInt(currentValue)), PropEvent::EVENT_PROP_CHANGE); + } + setHeight(80); + if (currentValue == PropProp::PROP_COMBO){ + comboEditProp->setPropName(nameInput->getText()); + comboEditProp->set(comboEditProp->currentCombo); + comboEditProp->enabled = true; + comboEditProp->visible = true; + setHeight(80 + comboEditProp->getHeight()); + } else if (lastValue == PropProp::PROP_COMBO){ + comboEditProp->enabled = false; + comboEditProp->visible = false; + } + if (currentValue == PropProp::PROP_SLIDER){ + sliderEditProp->setPropName(nameInput->getText()); + sliderEditProp->set(sliderEditProp->currentSlider); + sliderEditProp->enabled = true; + sliderEditProp->visible = true; + setHeight(80 + sliderEditProp->getHeight()); + } else if (lastValue == PropProp::PROP_SLIDER){ + sliderEditProp->enabled = false; + sliderEditProp->visible = false; + } + } + } + if (event->getDispatcher() == nameInput) { + if (event->getEventType() == "UIEvent" && event->getEventCode() == UIEvent::CHANGE_EVENT) { + lastName = currentName; + currentName = nameInput->getText(); + setPropName(nameInput->getText()); + if (!suppressChangeEvent) { + dispatchEvent(new Event(), Event::CHANGE_EVENT); + dispatchEvent(new PropEvent(this, NULL, PropDataString(lastName), PropDataString(currentName)), PropEvent::EVENT_PROP_CHANGE); + } + } + } + if (event->getDispatcher() == comboEditProp){ + if (event->getEventCode() == Event::CHANGE_EVENT) { + setHeight(80 + comboEditProp->getHeight()); + if (!suppressChangeEvent) { + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + } + } + + if (event->getDispatcher() == sliderEditProp){ + if (event->getEventCode() == Event::CHANGE_EVENT) { + setHeight(80 + sliderEditProp->getHeight()); + if (!suppressChangeEvent) { + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + } + } + + if (event->getDispatcher() == delButton) { + dispatchEvent(new Event(), Event::REMOVE_EVENT); + } +} + +void PropEditProp::set(PropProp *newProp){ + currentProp = newProp; + nameInput->setText(newProp->getPropName()); + typeChooser->setSelectedIndex(newProp->propType); + setHeight(65); + if (newProp->propType != PropProp::PROP_COMBO){ + comboEditProp->set(new ComboProp(nameInput->getText())); + } else { + comboEditProp->set(((ComboProp*)newProp)); + setHeight(80 + comboEditProp->getHeight()); + } + + if (newProp->propType != PropProp::PROP_SLIDER){ + sliderEditProp->set(new SliderProp(nameInput->getText(), 0, 0)); + } else { + sliderEditProp->set((SliderProp*)newProp); + setHeight(80 + sliderEditProp->getHeight()); + } +} + +PropProp *PropEditProp::get(){ + return currentProp; +} + +int PropEditProp::updatePadding(){ + return label->getWidth(); +} + +int PropEditProp::getPropType(){ + return currentValue; +} + +ComboPropEditProp::ComboPropEditProp(ComboProp* newCombo) : PropProp("", PropProp::PROP_COMBO_EDIT){ + nameLabel = new UILabel("New Item:", 11); + nameLabel->color.a = 1.0; + propContents->addChild(nameLabel); + nameLabel->setPosition(0, 5); + + newItemName = new UITextInput(false, 130, 12); + newItemName->addEventListener(this, UIEvent::CHANGE_EVENT); + newItemName->setText(newCombo->getPropName()); + propContents->addChild(newItemName); + newItemName->setPosition(70, 0); + + addItemButton = new UIButton("Add Item", 80); + addItemButton->addEventListener(this, UIEvent::CLICK_EVENT); + propContents->addChild(addItemButton); + addItemButton->setPosition(220, 0); + + label->enabled = false; + label->visible = false; + + currentCombo = newCombo; + + for (int c = 0; c < currentCombo->comboEntry->getNumItems(); c++){ + RemovableStringProp *newProp = new RemovableStringProp(currentCombo->comboEntry->getItemAtIndex(c)->label); + newProp->addEventListener(this, Event::REMOVE_EVENT); + propContents->addChild(newProp); + items.push_back(newProp); + + StringProp *newDataProp = new StringProp("Data:"); + newDataProp->set(String::NumberToString((int)currentCombo->comboEntry->getItemAtIndex(c)->data)); + newDataProp->stringEntry->setPosition(-70, 0); + newDataProp->stringEntry->Resize(40, newDataProp->stringEntry->getHeight()); + newDataProp->stringEntry->setNumberOnly(true); + newDataProp->addEventListener(this, Event::CHANGE_EVENT); + propContents->addChild(newDataProp); + datas.push_back(newDataProp); + } + + layoutProps(); + setWidth(370); +} + +ComboPropEditProp::~ComboPropEditProp(){} + +void ComboPropEditProp::handleEvent(Event *event){ + if (event->getDispatcher() == addItemButton) { + RemovableStringProp *newProp = new RemovableStringProp(newItemName->getText()); + newProp->addEventListener(this, Event::REMOVE_EVENT); + propContents->addChild(newProp); + items.push_back(newProp); + currentCombo->comboEntry->addComboItem(newItemName->getText()); + + StringProp *newDataProp = new StringProp("Data:"); + newDataProp->stringEntry->setPosition(-70, 0); + newDataProp->stringEntry->Resize(40, newDataProp->stringEntry->getHeight()); + newDataProp->stringEntry->setNumberOnly(true); + newDataProp->addEventListener(this, Event::CHANGE_EVENT); + propContents->addChild(newDataProp); + datas.push_back(newDataProp); + + layoutProps(); + newItemName->setText(""); + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + + for (int i = 0; i < items.size(); i++) { + if (event->getDispatcher() == datas[i]){ + currentCombo->comboEntry->getItemAtIndex(i)->data = (void*)datas[i]->get().toInteger(); + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + + if (items[i] == event->getDispatcher()) { + propContents->removeChild(items[i]); + items[i]->removeAllHandlersForListener(this); + + propContents->removeChild(datas[i]); + datas[i]->removeAllHandlersForListener(this); + + currentCombo->comboEntry->removeComboItemAtIndex(i); + items.erase(items.begin() + i); + datas.erase(datas.begin() + i); + layoutProps(); + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + } +} + +void ComboPropEditProp::layoutProps(){ + for (int i = 0; i < items.size(); i++){ + items[i]->setPosition(75, 30 + i * 20); + datas[i]->setPosition(0, 30 + i * 20); + } + setHeight(30 + items.size() * 20); +} + +void ComboPropEditProp::set(ComboProp *newCombo){ + for (int c = 0; c < currentCombo->comboEntry->getNumItems(); c++){ + delete items[c]; + } + items.clear(); + + + lastCombo = currentCombo; + currentCombo = newCombo; + + for (int c = 0; c < newCombo->comboEntry->getNumItems(); c++){ + RemovableStringProp *newProp = new RemovableStringProp(newCombo->comboEntry->getItemAtIndex(c)->label); + newProp->addEventListener(this, Event::REMOVE_EVENT); + propContents->addChild(newProp); + items.push_back(newProp); + + StringProp *newDataProp = new StringProp("Data:"); + newDataProp->set(String::IntToString((int)currentCombo->comboEntry->getItemAtIndex(c)->data)); + newDataProp->stringEntry->setPosition(-70, 0); + newDataProp->stringEntry->Resize(40, newDataProp->stringEntry->getHeight()); + newDataProp->stringEntry->setNumberOnly(true); + newDataProp->addEventListener(this, Event::CHANGE_EVENT); + propContents->addChild(newDataProp); + datas.push_back(newDataProp); + } + + layoutProps(); +} + +ComboProp *ComboPropEditProp::get(){ + return currentCombo; +} + +SliderEditProp::SliderEditProp(SliderProp* newSlider) : PropProp("", PropProp::PROP_COMBO_EDIT){ + minProp = new StringProp("Min:"); + minProp->stringEntry->setNumberOnly(true); + minProp->set(String::NumberToString(newSlider->slider->getStart(), 1)); + minProp->addEventListener(this, Event::CHANGE_EVENT); + propContents->addChild(minProp); + minProp->setPosition(10, 0); + + maxProp = new StringProp("Max:"); + maxProp->stringEntry->setNumberOnly(true); + maxProp->set(String::NumberToString(newSlider->slider->getEnd(), 1)); + maxProp->addEventListener(this, Event::CHANGE_EVENT); + propContents->addChild(maxProp); + maxProp->setPosition(10, 30); + + label->enabled = false; + label->visible = false; + + currentSlider = newSlider; + + setWidth(100); + setHeight(60); +} + +SliderEditProp::~SliderEditProp(){} + +void SliderEditProp::handleEvent(Event *event){ + if (event->getDispatcher() == minProp || event->getDispatcher() == maxProp){ + lastSlider = currentSlider; + currentSlider->slider->setStartEnd(minProp->get().toNumber(), maxProp->get().toNumber()); + dispatchEvent(new Event, Event::CHANGE_EVENT); + } +} + +void SliderEditProp::set(SliderProp *newSlider){ + lastSlider = currentSlider; + currentSlider = newSlider; + + minProp->set(String::NumberToString(currentSlider->slider->getStart(), 1)); + maxProp->set(String::NumberToString(currentSlider->slider->getEnd(), 1)); +} + +SliderProp *SliderEditProp::get(){ + return currentSlider; +} + ShaderPassesSheet::ShaderPassesSheet(ResourcePool *resourcePool) : PropSheet("SHADER PASSES", "shaderPasses") { this->resourcePool = resourcePool; propHeight = 70; @@ -2129,21 +2493,18 @@ void RenderTargetsSheet::handleEvent(Event *event) { PropSheet::handleEvent(event); } - -EntityPropSheet::EntityPropSheet() : PropSheet("CUSTOM PROPERTIES", "entityProps"){ - - addButtonProp = new ButtonProp("Add Property"); - addProp(addButtonProp); - addButtonProp->getButton()->addEventListener(this, UIEvent::CLICK_EVENT); +EntityPropSheet::EntityPropSheet(Plugin* plugin) : PropSheet(plugin->getResourceName().toUpperCase(), plugin->getResourceName().toLowerCase()){ + this->plugin = plugin->getResourceName(); customUndoHandler = true; - + entity = NULL; - + lastNumProps = 0; removeIndex = -1; - enabled = false; -} + enabled = false; + + refreshProps();} void EntityPropSheet::applyPropActionData(PolycodeEditorPropActionData *data) { if(!entity) @@ -2151,7 +2512,7 @@ void EntityPropSheet::applyPropActionData(PolycodeEditorPropActionData *data) { entity->entityProps.clear(); for(int i=0; i < data->entity->entityProps.size(); i++) { - entity->entityProps.push_back(data->entity->entityProps[i]); + entity->setEntityProp(data->entity->entityProps[i]); } refreshProps(); @@ -2161,16 +2522,6 @@ void EntityPropSheet::applyPropActionData(PolycodeEditorPropActionData *data) { void EntityPropSheet::handleEvent(Event *event) { if(!entity) return; - - if(event->getDispatcher() == addButtonProp->getButton() && event->getEventType() == "UIEvent") { - PolycodeEditorPropActionData *beforeData = PropDataEntity(entity); - entity->entityProps.push_back(EntityProp()); - refreshProps(); - PolycodeEditorPropActionData *afterData = PropDataEntity(entity); - PropEvent *propEvent = new PropEvent(NULL, this, beforeData, afterData); - dispatchEvent(propEvent, PropEvent::EVENT_PROP_CHANGE); - - } for(int i=0; i < props.size(); i++) { if(event->getDispatcher() == props[i] && event->getEventType() == "") { @@ -2180,13 +2531,81 @@ void EntityPropSheet::handleEvent(Event *event) { break; case Event::CHANGE_EVENT: PolycodeEditorPropActionData *beforeData = PropDataEntity(entity); - if(i-1 < entity->entityProps.size()) { - entity->entityProps[i-1].propName = ((CustomProp*)props[i])->getKey(); - entity->entityProps[i-1].propValue = ((CustomProp*)props[i])->getValue(); + if(i <= entity->entityProps.size()) { + switch (props[i]->propType) { + case PropProp::PROP_VECTOR3: + entity->setEntityProp(plugin + props[i]->getPropName() + "x", ((Vector3Prop*)props[i])->get().x); + entity->setEntityProp(plugin + props[i]->getPropName() + "y", ((Vector3Prop*)props[i])->get().y); + entity->setEntityProp(plugin + props[i]->getPropName() + "z", ((Vector3Prop*)props[i])->get().z); + break; + case PropProp::PROP_VECTOR2: + entity->setEntityProp(plugin + props[i]->getPropName() + "x", ((Vector2Prop*)props[i])->get().x); + entity->setEntityProp(plugin + props[i]->getPropName() + "y", ((Vector2Prop*)props[i])->get().y); + break; + case PropProp::PROP_SLIDER: + entity->setEntityProp(plugin + props[i]->getPropName(), ((SliderProp*)props[i])->get()); + break; + //case PropProp::PROP_BUTTON: + // prop = new ButtonProp(caption); + // break; + case PropProp::PROP_NUMBER: + entity->setEntityProp(plugin + props[i]->getPropName(), ((NumberProp*)props[i])->get()); + break; + //case PropProp::PROP_TARGET_BINDING: + // + // break; + //case PropProp::PROP_RENDER_TARGET: + // break; + //case PropProp::PROP_SHADER_PASS: + // break; + case PropProp::PROP_REMOVABLE_STRING: + entity->setEntityProp(plugin + props[i]->getPropName(), ((RemovableStringProp*)props[i])->getCaption()); + break; + //case PropProp::PROP_LAYER: + // break; + case PropProp::PROP_STRING: + entity->setEntityProp(plugin + props[i]->getPropName(), ((StringProp*)props[i])->get()); + break; + case PropProp::PROP_COLOR: + entity->setEntityProp(plugin + props[i]->getPropName() + "R", ((ColorProp*)props[i])->get().r); + entity->setEntityProp(plugin + props[i]->getPropName() + "G", ((ColorProp*)props[i])->get().g); + entity->setEntityProp(plugin + props[i]->getPropName() + "B", ((ColorProp*)props[i])->get().b); + entity->setEntityProp(plugin + props[i]->getPropName() + "A", ((ColorProp*)props[i])->get().a); + break; + case PropProp::PROP_COMBO: + entity->setEntityProp(plugin + props[i]->getPropName(), ((int)((ComboProp*)props[i])->comboEntry->getSelectedItem()->data)); + break; + case PropProp::PROP_BOOL: + entity->setEntityProp(plugin + props[i]->getPropName(), ((BoolProp*)props[i])->get()); + break; + case PropProp::PROP_SOUND: + entity->setEntityProp(plugin + props[i]->getPropName(), ((SoundProp*)props[i])->get()); + break; + //case PropProp::PROP_BEZIER_RGBA_CURVE: + // break; + //case PropProp::PROP_BEZIER_CURVE: + // break; + case PropProp::PROP_MATERIAL: + entity->setEntityProp(plugin + props[i]->getPropName(), ((MaterialProp*)props[i])->get()->getName()); + break; + case PropProp::PROP_TEXTURE: + entity->setEntityProp(plugin + props[i]->getPropName(), ((TextureProp*)props[i])->get()->getResourceName()); + break; + case PropProp::PROP_SCENE_SPRITE: + entity->setEntityProp(plugin + props[i]->getPropName(), ((SceneSpriteProp*)props[i])->get()->getResourceName()); + break; + case PropProp::PROP_SCENE_ENTITY_INSTANCE: + entity->setEntityProp(plugin + props[i]->getPropName(), ((SceneEntityInstanceProp*)props[i])->get()); + break; + case PropProp::PROP_CUSTOM: + default: + entity->setEntityProp(plugin + ((CustomProp*)props[i])->getKey(), ((CustomProp*)props[i])->getValue()); + break; + } } - PolycodeEditorPropActionData *afterData = PropDataEntity(entity); + PolycodeEditorPropActionData *afterData = PropDataEntity(entity); PropEvent *propEvent = new PropEvent(NULL, this, beforeData, afterData); - dispatchEvent(propEvent, PropEvent::EVENT_PROP_CHANGE); + dispatchEvent(propEvent, PropEvent::EVENT_PROP_CHANGE); break; } } @@ -2194,28 +2613,157 @@ void EntityPropSheet::handleEvent(Event *event) { PropSheet::handleEvent(event); } -void EntityPropSheet::refreshProps() { +void EntityPropSheet::reloadSheetFromEntry(ObjectEntry *sheetEntry) { + ObjectEntry *propsEntry = (*sheetEntry)["props"]; + if (propsEntry) { + refreshProps(); + } +} +void EntityPropSheet::refreshProps() { for(int i=0; i < props.size(); i++) { - if(props[i] != addButtonProp) { - contents->removeChild(props[i]); - props[i]->removeAllHandlersForListener(this); - delete props[i]; - } + contents->removeChild(props[i]); + props[i]->removeAllHandlersForListener(this); + delete props[i]; } props.clear(); - props.push_back(addButtonProp); - - - for(int i=0; i < entity->entityProps.size(); i++) { - EntityProp prop = entity->entityProps[i]; - CustomProp *newProp = new CustomProp(prop.propName, prop.propValue); - newProp->addEventListener(this, Event::CANCEL_EVENT); - newProp->addEventListener(this, Event::CHANGE_EVENT); - addProp(newProp); + + if (!entity) + entity = new Entity(); + + if (!entity->isRequiredPlugin(plugin)) { + this->enabled = false; + this->visible = false; + return; + } else { + this->enabled = true; + this->visible = true; + } + + std::vector props = dynamic_cast(Services()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_PLUGIN, plugin))->getProps(); + PropProp* prop; + + for (int i = 0; i < props.size(); i++) { + Prop* propEntry = props[i]; + String caption = propEntry->name; + + switch (propEntry->type) { + case PropProp::PROP_VECTOR3: + prop = new Vector3Prop(caption); + dynamic_cast(prop)->set(Vector3(entity->getEntityPropNumberByName(plugin + caption + "x"), entity->getEntityPropNumberByName(plugin + caption + "y"), entity->getEntityPropNumberByName(plugin + caption + "z"))); + break; + case PropProp::PROP_VECTOR2: + prop = new Vector2Prop(caption); + dynamic_cast(prop)->set(Vector2(entity->getEntityPropNumberByName(plugin + caption + "x"), entity->getEntityPropNumberByName(plugin + caption + "y"))); + break; + case PropProp::PROP_SLIDER: + Number min, max; + for (int s = 0; s < propEntry->children.size(); s++){ + if (propEntry->children[s]->name == "min"){ + min = propEntry->children[s]->value; + } else if (propEntry->children[s]->name == "max"){ + max = propEntry->children[s]->value; + } + } + prop = new SliderProp(caption, min, max); + dynamic_cast(prop)->set(entity->getEntityPropNumberByName(plugin + caption)); + break; + //case PropProp::PROP_BUTTON: + // prop = new ButtonProp(caption); + // break; + case PropProp::PROP_NUMBER: + prop = new NumberProp(caption); + prop->setPropData(PropDataNumber(entity->getEntityPropNumberByName(plugin + caption))); + break; + //case PropProp::PROP_TARGET_BINDING: + // Shader *shader = ((Shader*)Services()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_SHADER, entity->getEntityPropStringByName(plugin + caption))); + // Material *material = ((Material*)Services()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, entity->getEntityPropStringByName(plugin + caption))); + // ShaderBinding *shaderBin = new ShaderBinding(shader); + // RenderTargetBinding *targetBin = new RenderTargetBinding(); + // + // prop = new TargetBindingProp(shader, material, shaderBin, targetBin); + // + // break; + //case PropProp::PROP_RENDER_TARGET: + // ShaderRenderTarget *renderTarget; + // Material *material; + // prop = new RenderTargetProp(renderTarget, material); + // break; + //case PropProp::PROP_SHADER_PASS: + // prop = new ShaderPassProp(); + // break; + case PropProp::PROP_REMOVABLE_STRING: + prop = new RemovableStringProp(caption); + prop->setPropData(PropDataString(entity->getEntityPropStringByName(plugin + caption))); + break; + //case PropProp::PROP_LAYER: + // SceneEntityInstance *instance = new SceneEntityInstance(); + // prop = new LayerProp(); + // break; + case PropProp::PROP_STRING: + prop = new StringProp(caption); + ((StringProp*)prop)->set(entity->getEntityPropStringByName(plugin + caption)); + break; + case PropProp::PROP_COLOR: + prop = new ColorProp(caption); + ((ColorProp*)prop)->set(new Color(entity->getEntityPropNumberByName(plugin + caption + "r"), entity->getEntityPropNumberByName(plugin + caption + "g"), entity->getEntityPropNumberByName(plugin + caption + "b"), entity->getEntityPropNumberByName(plugin + caption + "a"))); + break; + case PropProp::PROP_COMBO: + prop = new ComboProp(caption); + for (int c = 0; c < propEntry->children.size(); c++) { + Prop* comboEntry = propEntry->children[c]; + ((ComboProp*)prop)->comboEntry->addComboItem(comboEntry->name, ((void*)comboEntry->value)); + } + for (int s = 0; s < ((ComboProp*)prop)->comboEntry->getNumItems(); s++){ + if (((int)((ComboProp*)prop)->comboEntry->getItemAtIndex(s)->data) == entity->getEntityPropIntByName(plugin + caption)){ + ((ComboProp*)prop)->comboEntry->setSelectedIndex(s); + } + } + break; + case PropProp::PROP_BOOL: + prop = new BoolProp(caption); + ((BoolProp*)prop)->set(entity->getEntityPropBoolByName(plugin + caption)); + break; + case PropProp::PROP_SOUND: + prop = new SoundProp(caption); + ((SoundProp*)prop)->set(entity->getEntityPropStringByName(plugin + caption)); + break; + //case PropProp::PROP_BEZIER_RGBA_CURVE: + // prop = new BezierRGBACurveProp(caption); + // for (int c = 0; c < entity->getEntityPropArrayByName(plugin + caption + "r").size(); c++) { + // ((BezierRGBACurveProp*)prop)->curveR->addControlPoint2d(entity->getEntityPropArrayByName(plugin + caption + "r")[c]); + // } + // break; + //case PropProp::PROP_BEZIER_CURVE: + //prop = new BezierCurveProp(caption, (*propEntry)["curveName"]->stringVal); + //break; + case PropProp::PROP_MATERIAL: + prop = new MaterialProp(caption); + ((MaterialProp*)prop)->set(new Material(entity->getEntityPropStringByName(plugin + caption))); + break; + case PropProp::PROP_TEXTURE: + prop = new TextureProp(caption); + ((TextureProp*)prop)->set(((Texture*)Services()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_TEXTURE, entity->getEntityPropStringByName(plugin + caption)))); + break; + case PropProp::PROP_SCENE_SPRITE: + prop = new SceneSpriteProp(caption); + ((SceneSpriteProp*)prop)->set(((Sprite*)Services()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_SPRITE, entity->getEntityPropStringByName(plugin + caption)))); + break; + case PropProp::PROP_SCENE_ENTITY_INSTANCE: + prop = new SceneEntityInstanceProp(caption); + ((SceneEntityInstanceProp*)prop)->set(entity->getEntityPropStringByName(plugin + caption)); + break; + case PropProp::PROP_CUSTOM: + default: + prop = new CustomProp(caption, entity->getEntityPropStringByName(plugin + caption)); + break; + } + prop->addEventListener(this, Event::CHANGE_EVENT); + addProp(prop); + prop->Resize(getWidth(), prop->getHeight()); } - + if(lastNumProps != entity->entityProps.size()) { dispatchEvent(new Event(), Event::COMPLETE_EVENT); } @@ -2271,12 +2819,12 @@ void ShaderOptionsSheet::handleEvent(Event *event) { LocalShaderParam *param = binding->getLocalParamByName(props[i]->label->getText()); - if(props[i]->propType == "Number") { + if(props[i]->propType == PropProp::PROP_NUMBER) { if(!param){ param = binding->addParam(ProgramParam::PARAM_NUMBER, props[i]->label->getText()); } (*(Number*)param->data) = ((NumberProp*)props[i])->get(); - } else if(props[i]->propType == "Color") { + } else if(props[i]->propType == PropProp::PROP_COLOR) { if(!param){ param = binding->addParam(ProgramParam::PARAM_COLOR, props[i]->label->getText()); @@ -3203,7 +3751,7 @@ EntitySheet::EntitySheet() : PropSheet("ENTITY", "entity"){ blendingProp->comboEntry->addComboItem("Color"); blendingProp->comboEntry->addComboItem("Premultiplied"); blendingProp->comboEntry->addComboItem("Multiply"); - + propHeight = 160; entity = NULL; @@ -3246,7 +3794,8 @@ void EntitySheet::handleEvent(Event *event) { } else if(event->getDispatcher() == layersProp && event->getEventCode() == Event::CHANGE_EVENT) { SceneEntityInstanceLayer *layer = (SceneEntityInstanceLayer*)layersProp->comboEntry->getSelectedItem()->data; entity->layerID = layer->layerID; - } + } + PropSheet::handleEvent(event); } @@ -3281,12 +3830,56 @@ void EntitySheet::setEntity(Entity *entity) { bBoxProp->set(entity->getLocalBoundingBox()); refreshLayers(); + enabled = true; } else { enabled = false; } } +PluginsSheet::PluginsSheet() : PropSheet("PLUGINS SHEETS", "plugins"){ + for (int p = 0; p < Services()->getResourceManager()->getGlobalPool()->getResources(Resource::RESOURCE_PLUGIN).size(); p++){ + BoolProp *pluginProp = new BoolProp(Services()->getResourceManager()->getGlobalPool()->getResources(Resource::RESOURCE_PLUGIN)[p]->getResourceName()); + pluginsProp.push_back(pluginProp); + addProp(pluginProp); + } + + entity = NULL; + + propHeight = 160; + enabled = false; +} + +PluginsSheet::~PluginsSheet() {} + +void PluginsSheet::handleEvent(Event *event) { + for (int p = 0; p < pluginsProp.size(); p++){ + if (event->getDispatcher() == pluginsProp[p]) { + if (pluginsProp[p]->get()){ + entity->addPluginByName(pluginsProp[p]->getPropName()); + } else { + entity->removePluginByName(pluginsProp[p]->getPropName()); + } + dispatchEvent(new Event(), Event::CHANGE_EVENT); + } + } + + PropSheet::handleEvent(event); +} + +void PluginsSheet::setEntity(Entity *entity) { + this->entity = entity; + if (entity) { + for (int p = 0; p < pluginsProp.size(); p++){ + pluginsProp[p]->set(entity->isRequiredPlugin(pluginsProp[p]->getPropName())); + } + + enabled = true; + } else { + enabled = false; + } +} + CameraSheet::CameraSheet() : PropSheet("CAMERA", "camera") { enabled = false; camera = NULL; @@ -3920,7 +4513,6 @@ void LinkedMaterialsSheet::updateMaterials() { addProp(addMaterialProp); } - void LinkedMaterialsSheet::setEntityInstance(SceneEntityInstance *instance) { this->instance = instance; if(instance) { @@ -3995,19 +4587,20 @@ void SoundSheet::handleEvent(Event *event) { } void SoundSheet::setSound(SceneSound *sound) { - this->sound = sound; + this->sound = sound; - if(sound) { - enabled = true; + if (sound) { + enabled = true; - soundProp->set(sound->getSound()->getFileName()); - referenceDistance->set(sound->getSound()->getReferenceDistance()); - maxDistance->set(sound->getSound()->getMaxDistance()); - volume->set(sound->getSound()->getVolume()); - pitch->set(sound->getSound()->getPitch()); - soundProp->previewSound->setPitch(sound->getSound()->getPitch()); + soundProp->set(sound->getSound()->getFileName()); + referenceDistance->set(sound->getSound()->getReferenceDistance()); + maxDistance->set(sound->getSound()->getMaxDistance()); + volume->set(sound->getSound()->getVolume()); + pitch->set(sound->getSound()->getPitch()); + soundProp->previewSound->setPitch(sound->getSound()->getPitch()); } else { enabled = false; } -} + +} \ No newline at end of file diff --git a/Modules/Contents/2DPhysics/Include/PolyPhysicsScreen.h b/Modules/Contents/2DPhysics/Include/PolyPhysicsScreen.h index adf4dedd7..02619dca6 100755 --- a/Modules/Contents/2DPhysics/Include/PolyPhysicsScreen.h +++ b/Modules/Contents/2DPhysics/Include/PolyPhysicsScreen.h @@ -185,6 +185,13 @@ class _PolyExport PhysicsScene2D : public Scene, b2ContactListener { */ PhysicsScene2DEntity *addPhysicsChild(Entity *newEntity, int entType, bool isStatic, Number friction=0.1, Number density=1, Number restitution = 0, bool isSensor = false, bool fixedRotation = false, int groupIndex = 0); + /** + * Adds a Entity as a physics enabled child. Once an entity is added as a physics child, its transforms are set by the physics engine and you are not able to position it manually. Use addCollisionChild/trackCollisionChild to track collisions of entities that you can position manually. + * @param newEntity Screen entity to add, with the Physics2D plugin EntityProps loaded. + * @return The physics entity wrapper. + */ + PhysicsScene2DEntity *addPhysicsChildEntity(Entity *newEntity); + /** * Tracks a Entity as a physics enabled child. Once an entity is added as a physics child, its transforms are set by the physics engine and you are not able to position it manually. Use addCollisionChild/trackCollisionChild to track collisions of entities that you can position manually. * @param newEntity Screen entity to add. @@ -223,7 +230,13 @@ class _PolyExport PhysicsScene2D : public Scene, b2ContactListener { * @param entityToRemove Entity to remove from the screen. */ PhysicsScene2DEntity *addCollisionChild(Entity *newEntity, int entType, int groupIndex = 0, bool sensorOnly = true); - + + /** + * Begins tracking collisions for a Entity and adds it to the scene. + * @param newEntity Entity to track collisions for, with the Physics2D plugin EntityProps loaded. + */ + PhysicsScene2DEntity *addCollisionChildEntity(Entity *newEntity); + /** * Begins tracking collisions for a Entity. * @param newEntity Entity to track collisions for. diff --git a/Modules/Contents/2DPhysics/Source/PolyPhysicsScreen.cpp b/Modules/Contents/2DPhysics/Source/PolyPhysicsScreen.cpp index 12fa83c7d..c852e42f1 100755 --- a/Modules/Contents/2DPhysics/Source/PolyPhysicsScreen.cpp +++ b/Modules/Contents/2DPhysics/Source/PolyPhysicsScreen.cpp @@ -343,6 +343,14 @@ PhysicsScene2DEntity *PhysicsScene2D::addCollisionChild(Entity *newEntity, int e return ret; } +PhysicsScene2DEntity *PhysicsScene2D::addCollisionChildEntity(Entity *newEntity) { + PhysicsScene2DEntity *ret; + ret = addPhysicsChild(newEntity, newEntity->getEntityPropIntByName("Physics2DShape"), false, 0, 0, 0, newEntity->getEntityPropBoolByName("Physics2DSensor?"), false, newEntity->getEntityPropIntByName("Physics2DGroup")); + newEntity->ignoreParentMatrix = false; + ret->collisionOnly = true; + return ret; +} + PhysicsScene2DEntity *PhysicsScene2D::trackCollisionChild(Entity *newEntity, int entType, int groupIndex) { PhysicsScene2DEntity *ret; ret = trackPhysicsChild(newEntity, entType, false, 0,0.0,0, true, false, groupIndex); @@ -471,6 +479,12 @@ PhysicsScene2DEntity *PhysicsScene2D::addPhysicsChild(Entity *newEntity, int ent } +PhysicsScene2DEntity *PhysicsScene2D::addPhysicsChildEntity(Entity *newEntity) { + addChild(newEntity); + return trackPhysicsChild(newEntity, newEntity->getEntityPropIntByName("Physics2DShape"), newEntity->getEntityPropBoolByName("Physics2DStatic?"), newEntity->getEntityPropNumberByName("Physics2DFriction"), newEntity->getEntityPropNumberByName("Physics2DDensity"), newEntity->getEntityPropNumberByName("Physics2DRestitution"), newEntity->getEntityPropBoolByName("Physics2DSensor?"), newEntity->getEntityPropBoolByName("Physics2DFixed Rot?"), newEntity->getEntityPropIntByName("Physics2DGroup")); + +} + PhysicsScene2DEntity *PhysicsScene2D::trackPhysicsChild(Entity *newEntity, int entType, bool isStatic, Number friction, Number density, Number restitution, bool isSensor, bool fixedRotation, int groupIndex) { PhysicsScene2DEntity *newPhysicsEntity = new PhysicsScene2DEntity(newEntity, world, worldScale, entType, isStatic, friction, density, restitution, isSensor,fixedRotation, groupIndex); diff --git a/Modules/Contents/3DPhysics/Include/PolyCollisionScene.h b/Modules/Contents/3DPhysics/Include/PolyCollisionScene.h index 1d54de811..db5f300d9 100755 --- a/Modules/Contents/3DPhysics/Include/PolyCollisionScene.h +++ b/Modules/Contents/3DPhysics/Include/PolyCollisionScene.h @@ -114,7 +114,8 @@ struct CollisionResult { bool isColliding(Entity *ent1); virtual CollisionEntity *addCollisionChild(Entity *newEntity, int type=0, int group=1); - CollisionEntity *trackCollision(Entity *newEntity, int type=0, int group=1); + virtual CollisionEntity *addCollisionChildEntity(Entity *newEntity); + CollisionEntity *trackCollision(Entity *newEntity, int type = 0, int group = 1); void removeCollision(Entity *entity); void adjustForCollision(CollisionEntity *collisionEntity); diff --git a/Modules/Contents/3DPhysics/Include/PolyCollisionSceneEntity.h b/Modules/Contents/3DPhysics/Include/PolyCollisionSceneEntity.h index c97ae679c..975d40cff 100755 --- a/Modules/Contents/3DPhysics/Include/PolyCollisionSceneEntity.h +++ b/Modules/Contents/3DPhysics/Include/PolyCollisionSceneEntity.h @@ -42,6 +42,7 @@ namespace Polycode { * Main constructor. */ CollisionEntity(Entity *entity, int type, bool compoundChildren = false); + CollisionEntity(Entity *entity); virtual ~CollisionEntity(); /** @name Collision scene entity diff --git a/Modules/Contents/3DPhysics/Include/PolyPhysicsScene.h b/Modules/Contents/3DPhysics/Include/PolyPhysicsScene.h index d723917b8..72e79f302 100644 --- a/Modules/Contents/3DPhysics/Include/PolyPhysicsScene.h +++ b/Modules/Contents/3DPhysics/Include/PolyPhysicsScene.h @@ -109,7 +109,8 @@ namespace Polycode { void removePhysicsChild(Entity *entity); PhysicsEntity *getPhysicsEntityByEntity(Entity *entity); - PhysicsEntity *addPhysicsChild(Entity *newEntity, int type=0, Number mass = 0.0f, Number friction=1, Number restitution=0, int group=1, bool compoundChildren = false); + PhysicsEntity *addPhysicsChild(Entity *newEntity, int type=0, Number mass = 0.0f, Number friction=1, Number restitution=0, int group=1, bool compoundChildren = false); + PhysicsEntity *addPhysicsChildEntity(Entity *newEntity); PhysicsEntity *trackPhysicsChild(Entity *newEntity, int type=0, Number mass = 0.0f, Number friction=1, Number restitution=0, int group=1, bool compoundChildren = false); PhysicsCharacter *addCharacterChild(Entity *newEntity, Number mass, Number friction, Number stepSize, int group = 1); diff --git a/Modules/Contents/3DPhysics/Include/PolyPhysicsSceneEntity.h b/Modules/Contents/3DPhysics/Include/PolyPhysicsSceneEntity.h index 2621d17b4..c421ff13d 100644 --- a/Modules/Contents/3DPhysics/Include/PolyPhysicsSceneEntity.h +++ b/Modules/Contents/3DPhysics/Include/PolyPhysicsSceneEntity.h @@ -41,6 +41,7 @@ namespace Polycode { class _PolyExport PhysicsEntity : public CollisionEntity { public: PhysicsEntity(Entity *entity, int type, Number mass, Number friction, Number restitution, bool compoundChildren = false); + PhysicsEntity(Entity *entity); virtual ~PhysicsEntity(); virtual void Update(); diff --git a/Modules/Contents/3DPhysics/Source/PolyCollisionScene.cpp b/Modules/Contents/3DPhysics/Source/PolyCollisionScene.cpp index abace7559..8dd0e1b0a 100755 --- a/Modules/Contents/3DPhysics/Source/PolyCollisionScene.cpp +++ b/Modules/Contents/3DPhysics/Source/PolyCollisionScene.cpp @@ -259,3 +259,12 @@ CollisionEntity *CollisionScene::addCollisionChild(Entity *newEntity, int type, return trackCollision(newEntity, type, group); } + +CollisionEntity *CollisionScene::addCollisionChildEntity(Entity *newEntity) { + addEntity(newEntity); + int group = newEntity->getEntityPropIntByName("Collision3DGroup"); + if (group == 0){ + group = 1; + } + return trackCollision(newEntity, newEntity->getEntityPropIntByName("Collision3DShape"), group); +} \ No newline at end of file diff --git a/Modules/Contents/3DPhysics/Source/PolyCollisionSceneEntity.cpp b/Modules/Contents/3DPhysics/Source/PolyCollisionSceneEntity.cpp index e60630b5f..627e95337 100755 --- a/Modules/Contents/3DPhysics/Source/PolyCollisionSceneEntity.cpp +++ b/Modules/Contents/3DPhysics/Source/PolyCollisionSceneEntity.cpp @@ -83,6 +83,56 @@ CollisionEntity::CollisionEntity(Entity *entity, int type, bool compoundChildren // } } +CollisionEntity::CollisionEntity(Entity *entity){ + this->entity = entity; + shape = NULL; + + this->type = entity->getEntityPropIntByName("Collision3DShape"); + enabled = true; + lastPosition = entity->getPosition(); + + + btMatrix3x3 basisA; + basisA.setIdentity(); + + collisionObject = new btCollisionObject(); + collisionObject->getWorldTransform().setBasis(basisA); + + if (entity->getEntityPropBoolByName("Collision3DComp Children?")) { + btCompoundShape* compoundShape = new btCompoundShape(); + + for (int i = 0; i < entity->getNumChildren(); i++) { + Entity *child = (Entity*)entity->getChildAtIndex(i); + btCollisionShape *childShape = createCollisionShape(child, child->collisionShapeType); + btTransform transform; + + child->rebuildTransformMatrix(); + + btScalar mat[16]; + Matrix4 ent_mat = child->getTransformMatrix(); + + for (int i = 0; i < 16; i++) { + mat[i] = ent_mat.ml[i]; + } + + transform.setFromOpenGLMatrix(mat); + compoundShape->addChildShape(transform, childShape); + } + + shape = compoundShape; + } else { + shape = createCollisionShape(entity, type); + } + + if (shape) { + collisionObject->setCollisionShape(shape); + } + + collisionObject->setUserPointer((void*)this); + + convexShape = dynamic_cast(shape); +} + btCollisionShape *CollisionEntity::createCollisionShape(Entity *entity, int type) { btCollisionShape *collisionShape = NULL; diff --git a/Modules/Contents/3DPhysics/Source/PolyPhysicsScene.cpp b/Modules/Contents/3DPhysics/Source/PolyPhysicsScene.cpp index 8dfe0935b..30e55a8e5 100644 --- a/Modules/Contents/3DPhysics/Source/PolyPhysicsScene.cpp +++ b/Modules/Contents/3DPhysics/Source/PolyPhysicsScene.cpp @@ -451,3 +451,12 @@ PhysicsEntity *PhysicsScene::addPhysicsChild(Entity *newEntity, int type, Number addEntity(newEntity); return trackPhysicsChild(newEntity, type, mass, friction, restitution, group, compoundChildren); } + +PhysicsEntity *PhysicsScene::addPhysicsChildEntity(Entity *newEntity) { + addEntity(newEntity); + int group = newEntity->getEntityPropIntByName("Physics3DGroup"); + if (group == 0){ + group = 1; + } + return trackPhysicsChild(newEntity, newEntity->getEntityPropIntByName("Physics3DShape"), newEntity->getEntityPropNumberByName("Physics3DMass"), newEntity->getEntityPropNumberByName("Physics3DFriction"), newEntity->getEntityPropNumberByName("Physics3DRestitution"), group, newEntity->getEntityPropBoolByName("Physics3DComp Children?")); +} \ No newline at end of file diff --git a/Modules/Contents/3DPhysics/Source/PolyPhysicsSceneEntity.cpp b/Modules/Contents/3DPhysics/Source/PolyPhysicsSceneEntity.cpp index 0bc5cc99d..2b1b58034 100644 --- a/Modules/Contents/3DPhysics/Source/PolyPhysicsSceneEntity.cpp +++ b/Modules/Contents/3DPhysics/Source/PolyPhysicsSceneEntity.cpp @@ -213,6 +213,38 @@ PhysicsEntity::PhysicsEntity(Entity *entity, int type, Number mass, Number frict } } +PhysicsEntity::PhysicsEntity(Entity *entity) : CollisionEntity(entity) { + enabled = true; + this->mass = entity->getEntityPropNumberByName("Physics3DMass"); + btVector3 localInertia(0, 0, 0); + btTransform transform; + transform.setIdentity(); + + Matrix4 ent_mat = entity->getConcatenatedMatrix(); + Vector3 pos = ent_mat * Vector3(0.0, 0.0, 0.0); + transform.setOrigin(btVector3(pos.x, pos.y, pos.z)); + + Quaternion q = entity->getConcatenatedQuat(); + transform.setRotation(btQuaternion(q.x, q.y, q.z, q.w)); + + if (mass != 0.0f) { + shape->calculateLocalInertia(mass, localInertia); + } + + if (entity->getEntityPropIntByName("Physics3DShape") == CHARACTER_CONTROLLER) { + rigidBody = NULL; + myMotionState = NULL; + } else { + myMotionState = new btDefaultMotionState(transform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, shape, localInertia); + rigidBody = new btRigidBody(rbInfo); + // rigidBody->setActivationState(ISLAND_SLEEPING); + rigidBody->setFriction(entity->getEntityPropNumberByName("Physics3DFriction")); + rigidBody->setRestitution(entity->getEntityPropNumberByName("Physics3DRestitution")); + rigidBody->setUserPointer((void*)this); + } +} + void PhysicsEntity::setFriction(Number friction) { rigidBody->setFriction(friction); } diff --git a/Modules/Contents/UI/Include/PolyUIComboBox.h b/Modules/Contents/UI/Include/PolyUIComboBox.h index 3d6f017f5..4e10b7778 100755 --- a/Modules/Contents/UI/Include/PolyUIComboBox.h +++ b/Modules/Contents/UI/Include/PolyUIComboBox.h @@ -54,7 +54,10 @@ namespace Polycode { int addComboItem(String itemName); int addComboItem(String itemName, void *data); - + + void removeComboItem(const String& itemName); + void removeComboItemAtIndex(int index); + int getSelectedIndex(); UIComboBoxItem *getSelectedItem(); void setSelectedIndex(unsigned int newIndex, bool suppressChangeEvent = false); diff --git a/Modules/Contents/UI/Include/PolyUIHSlider.h b/Modules/Contents/UI/Include/PolyUIHSlider.h index 500e04c37..80c74a9d2 100755 --- a/Modules/Contents/UI/Include/PolyUIHSlider.h +++ b/Modules/Contents/UI/Include/PolyUIHSlider.h @@ -46,7 +46,11 @@ namespace Polycode { void setContinuous(bool _continuous); void setSliderValue(Number val); - Number getSliderValue(); + Number getSliderValue(); + + void setStartEnd(Number start, Number end); + Number getStart(); + Number getEnd(); private: diff --git a/Modules/Contents/UI/Source/PolyUIComboBox.cpp b/Modules/Contents/UI/Source/PolyUIComboBox.cpp index ae4d397d7..582f865b1 100755 --- a/Modules/Contents/UI/Source/PolyUIComboBox.cpp +++ b/Modules/Contents/UI/Source/PolyUIComboBox.cpp @@ -140,6 +140,22 @@ int UIComboBox::addComboItem(String itemName) { return addComboItem(itemName, NULL); } +void UIComboBox::removeComboItem(const String& itemName){ + for (int i = 0; i < items.size(); i++){ + if (items[i]->label == itemName){ + items.erase(items.begin() + i); + if (i == selectedIndex){ + setSelectedIndex(0); + } + return; + } + } +} + +void UIComboBox::removeComboItemAtIndex(int index){ + items.erase(items.begin() + index); +} + UIComboBoxItem *UIComboBox::getSelectedItem() { if(selectedIndex < items.size()) { return items[selectedIndex]; diff --git a/Modules/Contents/UI/Source/PolyUIHSlider.cpp b/Modules/Contents/UI/Source/PolyUIHSlider.cpp index 9dc3be2db..7e1df4018 100755 --- a/Modules/Contents/UI/Source/PolyUIHSlider.cpp +++ b/Modules/Contents/UI/Source/PolyUIHSlider.cpp @@ -102,6 +102,19 @@ void UIHSlider::setSliderValue(Number val) { } } +void UIHSlider::setStartEnd(Number start, Number end){ + startValue = start; + endValue = end; +} + +Number UIHSlider::getStart(){ + return startValue; +} + +Number UIHSlider::getEnd(){ + return endValue; +} + bool UIHSlider::isContinuous() { return continuous; }