From 4b4758bc7f42723bd05230aec1618f96f846dc24 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Mon, 17 Dec 2012 22:21:54 +0100 Subject: [PATCH] [DEV] import engine instead of creating an extern --- Makefile.mk | 1 - external/etk | 2 +- sources/Linux.mk | 2 +- sources/ewol/game/Bounding.cpp | 24 + sources/ewol/game/Bounding.h | 59 ++ sources/ewol/game/BoundingAABB.cpp | 38 ++ sources/ewol/game/BoundingAABB.h | 40 ++ sources/ewol/game/BoundingOBB.cpp | 30 ++ sources/ewol/game/BoundingOBB.h | 41 ++ sources/ewol/game/BoundingPlane.cpp | 30 ++ sources/ewol/game/BoundingPlane.h | 39 ++ sources/ewol/game/BoundingSphere.cpp | 31 ++ sources/ewol/game/BoundingSphere.h | 40 ++ sources/ewol/game/Element.cpp | 9 +- sources/ewol/game/Element.h | 14 +- sources/ewol/game/Engine.cpp | 1 - sources/ewol/game/Engine.h | 3 - sources/ewol/game/GameElement.cpp | 64 --- sources/ewol/game/GameElement.h | 145 ----- sources/ewol/game/Geometry.cpp | 79 +++ sources/ewol/game/Geometry.h | 59 ++ sources/ewol/game/Map.cpp | 7 + sources/ewol/game/Map.h | 15 + sources/ewol/game/Mass.cpp | 7 + sources/ewol/game/Mass.h | 25 + sources/ewol/game/MeshObject.h | 33 ++ sources/ewol/game/MeshProperty.h | 82 +++ sources/ewol/game/SceneElement.cpp | 506 ------------------ sources/ewol/game/SceneElement.h | 86 --- sources/ewol/game/Sky.cpp | 7 + sources/ewol/game/Sky.h | 15 + sources/ewol/renderer/resources/Mesh.cpp | 2 +- sources/ewol/renderer/resources/Mesh.h | 4 +- .../renderer/resources/image/ImagePNG.cpp | 59 +- sources/ewol/widget/Scene.cpp | 62 ++- sources/ewol/widget/Scene.h | 18 +- sources/file.mk | 11 +- test/human/appl/TestScene.cpp | 33 ++ test/human/data/cube.bmp | Bin 196662 -> 0 bytes test/human/data/cube.obj | 79 ++- test/human/data/stone.png | Bin 0 -> 8664 bytes test/human/data/stone2.png | Bin 0 -> 7793 bytes test/human/file.mk | 1 + 43 files changed, 894 insertions(+), 909 deletions(-) create mode 100644 sources/ewol/game/Bounding.cpp create mode 100644 sources/ewol/game/Bounding.h create mode 100644 sources/ewol/game/BoundingAABB.cpp create mode 100644 sources/ewol/game/BoundingAABB.h create mode 100644 sources/ewol/game/BoundingOBB.cpp create mode 100644 sources/ewol/game/BoundingOBB.h create mode 100644 sources/ewol/game/BoundingPlane.cpp create mode 100644 sources/ewol/game/BoundingPlane.h create mode 100644 sources/ewol/game/BoundingSphere.cpp create mode 100644 sources/ewol/game/BoundingSphere.h delete mode 100644 sources/ewol/game/GameElement.cpp delete mode 100644 sources/ewol/game/GameElement.h create mode 100644 sources/ewol/game/Geometry.cpp create mode 100644 sources/ewol/game/Geometry.h create mode 100644 sources/ewol/game/Map.cpp create mode 100644 sources/ewol/game/Map.h create mode 100644 sources/ewol/game/Mass.cpp create mode 100644 sources/ewol/game/Mass.h create mode 100644 sources/ewol/game/MeshObject.h create mode 100644 sources/ewol/game/MeshProperty.h delete mode 100644 sources/ewol/game/SceneElement.cpp delete mode 100644 sources/ewol/game/SceneElement.h create mode 100644 sources/ewol/game/Sky.cpp create mode 100644 sources/ewol/game/Sky.h delete mode 100644 test/human/data/cube.bmp create mode 100644 test/human/data/stone.png create mode 100644 test/human/data/stone2.png diff --git a/Makefile.mk b/Makefile.mk index 1103a47f..f481f8ce 100644 --- a/Makefile.mk +++ b/Makefile.mk @@ -19,7 +19,6 @@ USER_PACKAGES+= $(TMP_DIR)/external/portaudio USER_PACKAGES+= $(TMP_DIR)/external/tinyxml USER_PACKAGES+= $(TMP_DIR)/external/z USER_PACKAGES+= $(TMP_DIR)/external/zip -USER_PACKAGES+= $(TMP_DIR)/external/ePhysics #include te generic toolchain : include $(TMP_DIR)/build/Makefile.mk diff --git a/external/etk b/external/etk index e6af555b..0b2050cf 160000 --- a/external/etk +++ b/external/etk @@ -1 +1 @@ -Subproject commit e6af555b152d01a561526bc8c5515338cec464fe +Subproject commit 0b2050cf687a0f698b838df781a8095a9e92939d diff --git a/sources/Linux.mk b/sources/Linux.mk index 182e50a9..6f6b1932 100644 --- a/sources/Linux.mk +++ b/sources/Linux.mk @@ -12,7 +12,7 @@ LOCAL_VERSION=$(shell cat $(LOCAL_PATH)/tag) $(info [TAG:$(LOCAL_MODULE)] $(LOCAL_VERSION)) # name of the dependency -LOCAL_LIBRARIES := etk freetype tinyxml libzip libpng parsersvg lua portaudio ephysics +LOCAL_LIBRARIES := etk freetype tinyxml libzip libpng parsersvg lua portaudio LOCAL_C_INCLUDES := diff --git a/sources/ewol/game/Bounding.cpp b/sources/ewol/game/Bounding.cpp new file mode 100644 index 00000000..c8b4250e --- /dev/null +++ b/sources/ewol/game/Bounding.cpp @@ -0,0 +1,24 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#include + + +game::Bounding::Bounding(boundingMode mode) : + m_markedToUpdate(true), + m_mode(mode) +{ + +} + +game::Bounding::~Bounding(void) +{ + +} + + diff --git a/sources/ewol/game/Bounding.h b/sources/ewol/game/Bounding.h new file mode 100644 index 00000000..5b03b83d --- /dev/null +++ b/sources/ewol/game/Bounding.h @@ -0,0 +1,59 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __GAME_BOUNDING_H__ +#define __GAME_BOUNDING_H__ + +#include "ewol/debug.h" +#include "ewol/game/MeshObject.h" +#include "ewol/game/MeshProperty.h" + +namespace game +{ + typedef enum { + BoundingModeNone, //!< No Bounding. + BoundingModePlane, //!< plane Bounding. + BoundingModeAABB, //!< Anti-aligned Bounding Boxes. + BoundingModeSphere, //!< Sphere. + BoundingModeOBB, //!< Oriented Bounding Box. + // TODO : Add more if needed to implement + } boundingMode; + + class Bounding + { + protected : + bool m_markedToUpdate; //!< Marked to update the bounding properties. + boundingMode m_mode; //!< bounding mode of this system. + public: + /** + * @biref Main constructor. + * @param[in] mode Bounding mode. + */ + Bounding(boundingMode mode); + /** + * @biref Main constructor. + */ + virtual ~Bounding(void); + /** + * @brief Request the update of the bounding for the next step + */ + void NeedUpdate(void) { m_markedToUpdate = true; }; + /** + * @brief Get the bounding type + * @return the bounding type; + */ + boundingMode GetType(void) { return m_mode; }; + /** + * @brief Update Bounding properties. + */ + virtual void Update(game::MeshObject& object, game::MeshProperty& property) = 0; + }; + +}; + +#endif diff --git a/sources/ewol/game/BoundingAABB.cpp b/sources/ewol/game/BoundingAABB.cpp new file mode 100644 index 00000000..3e8cfebd --- /dev/null +++ b/sources/ewol/game/BoundingAABB.cpp @@ -0,0 +1,38 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#include +#include +#include + + +game::BoundingAABB::BoundingAABB(void) : + Bounding(game::BoundingModeAABB) +{ + +} + +game::BoundingAABB::~BoundingAABB(void) +{ + +} + +void game::BoundingAABB::Update(game::MeshObject& object, game::MeshProperty& property) +{ + if (true==m_markedToUpdate) { + mat4 transMat = etk::matRotate(property.m_angle) * etk::matTranslate(property.m_position); + m_markedToUpdate=false; + for (int32_t iii=0; iii +#include + + +game::BoundingOBB::BoundingOBB(game::MeshObject& object, game::MeshProperty& property) : + Bounding(game::BoundingModeOBB) +{ + +} + +game::BoundingOBB::~BoundingOBB(void) +{ + +} + +void game::BoundingOBB::Update(game::MeshObject& object, game::MeshProperty& property) +{ + +} + + + diff --git a/sources/ewol/game/BoundingOBB.h b/sources/ewol/game/BoundingOBB.h new file mode 100644 index 00000000..ffe920f5 --- /dev/null +++ b/sources/ewol/game/BoundingOBB.h @@ -0,0 +1,41 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __GAME_BOUNDING_OBB_H__ +#define __GAME_BOUNDING_OBB_H__ + +#include "ewol/game/Bounding.h" +#include "etk/math/Vector3D.h" + +namespace game +{ + class BoundingOBB : public Bounding + { + private : + vec3 m_PointCenter; + vec3 m_radius; + vec3 m_angle; + public: + /** + * @biref Main constructor. + * @param[in] mode Bounding mode. + */ + BoundingOBB(game::MeshObject& object, game::MeshProperty& property); + /** + * @biref Main constructor. + */ + virtual ~BoundingOBB(void); + /** + * @brief Update Bounding properties. + */ + virtual void Update(game::MeshObject& object, game::MeshProperty& property); + }; +} + + +#endif diff --git a/sources/ewol/game/BoundingPlane.cpp b/sources/ewol/game/BoundingPlane.cpp new file mode 100644 index 00000000..4a67d91d --- /dev/null +++ b/sources/ewol/game/BoundingPlane.cpp @@ -0,0 +1,30 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#include +#include + + +game::BoundingPlane::BoundingPlane(void) : + Bounding(game::BoundingModePlane) +{ + +} + +game::BoundingPlane::~BoundingPlane(void) +{ + +} + +void game::BoundingPlane::Update(game::MeshObject& object, game::MeshProperty& property) +{ + +} + + + diff --git a/sources/ewol/game/BoundingPlane.h b/sources/ewol/game/BoundingPlane.h new file mode 100644 index 00000000..36c07aa5 --- /dev/null +++ b/sources/ewol/game/BoundingPlane.h @@ -0,0 +1,39 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __GAME_BOUNDING_PLANE_H__ +#define __GAME_BOUNDING_PLANE_H__ + +#include "ewol/game/Bounding.h" +#include "etk/math/Vector3D.h" + +namespace game +{ + class BoundingPlane : public Bounding + { + private : + vec3 m_equation; + public: + /** + * @biref Main constructor. + * @param[in] mode Bounding mode. + */ + BoundingPlane(void); + /** + * @biref Main constructor. + */ + virtual ~BoundingPlane(void); + /** + * @brief Update Bounding properties. + */ + virtual void Update(game::MeshObject& object, game::MeshProperty& property); + }; +} + + +#endif diff --git a/sources/ewol/game/BoundingSphere.cpp b/sources/ewol/game/BoundingSphere.cpp new file mode 100644 index 00000000..c658631c --- /dev/null +++ b/sources/ewol/game/BoundingSphere.cpp @@ -0,0 +1,31 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#include +#include + + +game::BoundingSphere::BoundingSphere(void) : + Bounding(game::BoundingModeSphere) +{ + +} + +game::BoundingSphere::~BoundingSphere(void) +{ + +} + +void game::BoundingSphere::Update(game::MeshObject& object, game::MeshProperty& property) +{ + +} + + + + diff --git a/sources/ewol/game/BoundingSphere.h b/sources/ewol/game/BoundingSphere.h new file mode 100644 index 00000000..f6baffdb --- /dev/null +++ b/sources/ewol/game/BoundingSphere.h @@ -0,0 +1,40 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __GAME_BOUNDING_SPHERE_H__ +#define __GAME_BOUNDING_SPHERE_H__ + +#include "ewol/game/Bounding.h" +#include "etk/math/Vector3D.h" + +namespace game +{ + class BoundingSphere : public Bounding + { + private : + vec3 m_position; //!< Position of the center of the bounding + float m_radius; //!< Radius of the Bounding + public: + /** + * @biref Main constructor. + * @param[in] mode Bounding mode. + */ + BoundingSphere(void); + /** + * @biref Main constructor. + */ + virtual ~BoundingSphere(void); + /** + * @brief Update Bounding properties. + */ + virtual void Update(game::MeshObject& object, game::MeshProperty& property); + }; +} + + +#endif diff --git a/sources/ewol/game/Element.cpp b/sources/ewol/game/Element.cpp index b38ceb88..98bac69b 100644 --- a/sources/ewol/game/Element.cpp +++ b/sources/ewol/game/Element.cpp @@ -29,6 +29,10 @@ game::Element::Element(etk::UString meshResource) : m_resource = tmpObject; } uniqueId++; + + m_property.Scale(vec3(100,100,100) ); + //m_property.Rotate(m_property.m_angle, rotx); + m_property.Translate(vec3(0.01,0.0,0.0)); } game::Element::~Element(void) @@ -43,10 +47,7 @@ game::Element::~Element(void) void game::Element::Draw(void) { if (NULL != m_resource) { - m_property.m_matrix = etk::matScale(vec3(100,100,100) ) - /* etk::matRotate(m_property.m_angle, rotx)*/ - * etk::matTranslate(vec3(0.01,0.0,0.0)); - m_resource->Draw(m_property.m_matrix); + m_resource->Draw(m_property.GetMatrix()); } } diff --git a/sources/ewol/game/Element.h b/sources/ewol/game/Element.h index 915a6f84..bdbb531b 100644 --- a/sources/ewol/game/Element.h +++ b/sources/ewol/game/Element.h @@ -14,16 +14,16 @@ #include #include #include -#include +#include #include namespace game { class Element { - private: - ewol::Mesh* m_resource; //!< Resource to display the element. - ephysics::MeshProperty m_property; //!< display property f the element. + protected: + ewol::Mesh* m_resource; //!< Resource to display the element. + game::MeshProperty m_property; //!< display property f the element. protected: uint32_t m_uniqueId; //!< General element ID (uint16_t, because all is reference with the groupId like this only a uint32_t reference an element) uint32_t m_groupId; //!< General group Id More than 65000 group can be really interesting to create supid game ... @@ -39,17 +39,17 @@ namespace game /** * @brief Basic destructor. */ - ~Element(void); + virtual ~Element(void); /** * @brief Draw the element. */ - void Draw(void); + virtual void Draw(void); /** * @brief Process IA of this element. * @param[in] deltaMicroSecond delta from the last call. * @return true if this element must be destroyed */ - bool ArtificialIntelligence(int32_t deltaMicroSecond); + virtual bool ArtificialIntelligence(int32_t deltaMicroSecond); }; }; diff --git a/sources/ewol/game/Engine.cpp b/sources/ewol/game/Engine.cpp index 9129286e..89f0c268 100644 --- a/sources/ewol/game/Engine.cpp +++ b/sources/ewol/game/Engine.cpp @@ -39,7 +39,6 @@ void game::Engine::Process(int64_t lastTime, int32_t deltaTime) void game::Engine::Draw(ewol::DrawProperty& displayProp) { - EWOL_DEBUG("Draw ..."); for (int32_t iii=0; iiiDraw(); diff --git a/sources/ewol/game/Engine.h b/sources/ewol/game/Engine.h index 24e58e8f..bd0ce199 100644 --- a/sources/ewol/game/Engine.h +++ b/sources/ewol/game/Engine.h @@ -14,17 +14,14 @@ #include #include #include -#include namespace game { class Engine { private: - //game::Map* m_map; //!< basic system map (BSD or other ...) etk::Vector m_elementsStatic; etk::Vector m_elementsDynamic; - ephysics::World m_world; //!< physical world engine public: /** * @brief Basic constructor. diff --git a/sources/ewol/game/GameElement.cpp b/sources/ewol/game/GameElement.cpp deleted file mode 100644 index ceb14b70..00000000 --- a/sources/ewol/game/GameElement.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @author Edouard DUPIN - * - * @copyright 2011, Edouard DUPIN, all right reserved - * - * @license BSD v3 (see license file) - */ - -#include - - -#undef __class__ -#define __class__ "GameElement" - -ewol::GameElement::GameElement(SceneElement & sceneElement, etk::UString& tmpName) : m_fileNameConfig(tmpName), m_sceneElement(sceneElement) -{ - m_uniqueId = sceneElement.GetUniqueId(); - m_group = -1; - m_type = -1; - m_visible = true; - m_position.x = 0.0; - m_position.y = 0.0; - m_speed = 0.0; - m_size = 64.0; - m_sizeDisplay = 64.0; - m_angle = 0.0; - m_mass = 0.0; - m_fileNameConfig = tmpName; - m_canBeCibled = false; - m_canHaveImpact = true; - m_life = 0; - m_enable = true; -} - - - - -float quadDist(vec2 pos1, vec2 pos2) -{ - float tmpVal1 = pos1.x - pos2.x; - float tmpVal2 = pos1.y - pos2.y; - - return tmpVal1*tmpVal1 + tmpVal2*tmpVal2; -} - - -bool ewol::GameElement::HaveImpact(int32_t group, int32_t type, vec2 position, float size) -{ - if (true != m_canHaveImpact) { - return false; - } - // check if it was in the same group - if (group == m_group) { - return false; - } - float quadDistance = quadDist(m_position, position); - float radiusElement = m_size * m_size; - if (radiusElement < quadDistance) { - //distance is greten than expected - return false; - } - return true; -} - diff --git a/sources/ewol/game/GameElement.h b/sources/ewol/game/GameElement.h deleted file mode 100644 index 3fa8c9d4..00000000 --- a/sources/ewol/game/GameElement.h +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @author Edouard DUPIN - * - * @copyright 2011, Edouard DUPIN, all right reserved - * - * @license BSD v3 (see license file) - */ - -#ifndef __EWOL_GAME_ELEMENT_H__ -#define __EWOL_GAME_ELEMENT_H__ - -#include -#include -#include -#include -#include -#include - -#define CYCLIC_CALL_PERIODE_US (10000) -#define NB_SPECIAL_PARAM (5) - -namespace ewol { - - class GameElement - { - private: - etk::UString m_fileNameConfig; - protected: - SceneElement & m_sceneElement; //!< All element neede in the scene - uint16_t m_uniqueId; //!< General element ID (uint16_t, because all is reference with the groupId like this only a uint32_t reference an element) - uint16_t m_group; //!< General group Id More than 65000 group can be really interesting to create supid game ... - float m_life; //!< Current life of the element - int32_t m_type; //!< - float m_power; //!< Current power of the element - bool m_visible; //!< This is to know if the element is displayed or not ==> TODO : check if usefull ... - vec2 m_position; //!< Current position of the element - float m_speed; //!< Speed of the element (only one value, the angle is generated by the m_angle - float m_angle; //!< Angle of the speed - float m_mass; //!< Current element Mass ==> for the physical calculation - float m_size; //!< Current size of the element more specific size can be done in the under class => this is for simplify calculation ==> all is consider like sphere... - float m_sizeDisplay; //!< Current diplay size of the element - bool m_canBeCibled; //!< This is for automatic finding on an ennemy - bool m_canHaveImpact; //!< detection of impact is done with this ... - float m_specialParam[NB_SPECIAL_PARAM]; //!< specific game user parameter - bool m_enable; //!< Use to add element that can not be detected by the other when user select a place - public: - /** - * @brief Constructor : here are requested all the needed sprite and effect that can be used in the game - * @param --- - * @return --- - */ - GameElement(SceneElement & sceneElement, etk::UString& tmpName); - /** - * @brief Destructor : This does not remove the sprite requested, they will be supressed when the scene is removed ... - * @param --- - * @return --- - */ - virtual ~GameElement(void) { }; - - virtual void Init(void) { }; - virtual void UnInit(void) { }; - - uint16_t GetUniqueId(void) { return m_uniqueId; }; - - bool HasName(etk::UString tmpName) { return (tmpName == m_fileNameConfig); }; - bool IsVisible(void) { return m_visible; }; - void SetVisible(bool state) { m_visible = state; StatusUpdate();}; - bool IsEnable(void) { return m_enable; }; - void SetEnable(bool state) { m_enable = state; StatusUpdate();}; - vec2 PositionGet(void) { return m_position; }; - void PositionSet(vec2 state) { m_position = state; StatusUpdate();}; - void PositionSet(float xxx, float yyy) { m_position.x = xxx; m_position.y = yyy; StatusUpdate();}; - float SpeedGet(void) { return m_speed; }; - void SpeedSet(float state) { m_speed = state; StatusUpdate();}; - float MassGet(void) { return m_mass; }; - void MassSet(float state) { m_mass = state; StatusUpdate();}; - float SizeGet(void) { return m_size; }; - void SizeSet(float state) { m_size = state; StatusUpdate();}; - float DisplaySizeGet(void) { return m_sizeDisplay; }; - void DisplaySizeSet(float state) { m_sizeDisplay = state; StatusUpdate();}; - float AngleGet(void) { return m_angle; }; - void AngleSet(float state) - { - m_angle = state; - while (m_angle > M_PI) { - m_angle -= 2.0*M_PI; - } - while (m_angle < -M_PI) { - m_angle += 2.0*M_PI; - } - StatusUpdate(); - }; - float PowerGet(void) { return m_power; }; - void PowerSet(float state) { m_power = state; StatusUpdate();}; - bool CanBeCibledGet(void) { return m_canBeCibled; }; - void CanBeCibledSet(bool state) { m_canBeCibled = state; StatusUpdate();}; - bool CanHaveImpactGet(void) { return m_canHaveImpact; }; - void CanHaveImpactSet(bool state) { m_canHaveImpact = state; StatusUpdate();}; - - int32_t GetType(void) { return m_type; }; // TODO : DEPRECATED ... - int32_t TypeGet(void) { return m_type; }; - uint16_t GroupGet(void) { return m_group; }; - void GroupSet(uint16_t state) { m_group = state; StatusUpdate();}; - - float SpecialParamGet(int32_t id) { if (id<0 || id>=NB_SPECIAL_PARAM) {return 0.0;} return m_specialParam[id]; }; - void SpecialParamSet(int32_t id, float state) { if (id<0 || id>=NB_SPECIAL_PARAM) {return;} m_specialParam[id]=state; StatusUpdate();}; - - /** - * @brief Periodicly this fuction will be call tu change property of all the dynamic obbjects - * @param[in] time Current game time (start at 0) - * @param[in] deltaTime delta time before the previous call - * @param[in,out] listOfSprite Reference on the list where the display must be done for every sprite - * @param[in,out] listOfEffects Reference on the list where the display must be done for every effects - * @return true if the object must be remove - * @return false if the object must be keep - */ - virtual bool Process(int64_t time, int32_t deltaTime) { return false; }; - - /** - * @brief Requuest the draw of the current element, it will be done on the current Sprite list - * @param[in,out] listOfSprite Reference on the list where the display must be done for every sprite - * @param[in,out] listOfEffects Reference on the list where the display must be done for every effects - * @return --- - */ - virtual void Draw(void) { }; - /** - * @brief an element has been remove, just remove reference on it or ID on IT, it can be replace whith an other that have no link - * @param[in] idOfElement Id of the element that has been removed - * @return --- - */ - virtual void RemoveElement(int32_t idOfElement) { }; - virtual bool HaveImpact(int32_t group, int32_t type, vec2 position, float size); - virtual bool Explosion(int32_t group, int32_t type, vec2 position, float pxAtenuation, float power) { return false; } ; - - virtual etk::UString Message(etk::UString control, etk::UString message) { return ""; } ; - virtual void StatusUpdate(void) { }; - }; - -}; - -#include - -float quadDist(vec2 pos1, vec2 pos2); - -#endif diff --git a/sources/ewol/game/Geometry.cpp b/sources/ewol/game/Geometry.cpp new file mode 100644 index 00000000..5fd9b99d --- /dev/null +++ b/sources/ewol/game/Geometry.cpp @@ -0,0 +1,79 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#include +#include +#include +#include +#include +#include +#include + +game::Geometry::Geometry(game::MeshObject& object, game::MeshProperty& property) : + m_dynamic(false), + m_object(object), + m_property(property), + m_bounding(NULL), + m_mass(NULL) +{ + +} + +game::Geometry::~Geometry(void) +{ + +} + +void game::Geometry::SetStatic(void) +{ + m_dynamic = false; +} + +void game::Geometry::SetDynamic(void) +{ + m_dynamic = true; +} + +void game::Geometry::SetBoundingMode(game::boundingMode type) +{ + if (NULL != m_bounding) { + if (m_bounding->GetType() != type) { + delete(m_bounding); + m_bounding = NULL; + } else { + return; + } + } + switch(type) + { + default: + case BoundingModeNone: + break; + case BoundingModePlane: + EWOL_TODO("Implement plane..."); + break; + case BoundingModeAABB: + m_bounding = new game::BoundingAABB(); + break; + case BoundingModeSphere: + m_bounding = new game::BoundingSphere(); + break; + case BoundingModeOBB: + m_bounding = new game::BoundingOBB(m_object, m_property); + break; + } +} + +void game::Geometry::BoundingUpdate(void) +{ + if (NULL != m_bounding) { + m_bounding->Update(m_object, m_property); + } +} + + diff --git a/sources/ewol/game/Geometry.h b/sources/ewol/game/Geometry.h new file mode 100644 index 00000000..d716ccdf --- /dev/null +++ b/sources/ewol/game/Geometry.h @@ -0,0 +1,59 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __GAME_GEOMETRY_H__ +#define __GAME_GEOMETRY_H__ + +#include +#include +#include + + +namespace game +{ + class Geometry + { + private : + bool m_dynamic; //!< Set at true if the Geometry can move or not (bounding can change) + game::MeshObject& m_object; //!< Object vertex/ normal and other properties + game::MeshProperty& m_property; //!< Display properties of this element. + game::Bounding* m_bounding; //!< Bounding interface. + game::Mass* m_mass; //!< Mass properties. + public: + /** + * @brief main constructor + * @param[in] object the reference mesh object (must not be NULL) + * @param[in] property the reference mesh property (must not be NULL) + */ + Geometry(game::MeshObject& object, game::MeshProperty& property); + /** + * @brief main destructor + */ + ~Geometry(void); + /** + * @brief Set this object static (the bounding does not change) + */ + void SetStatic(void); + /** + * @brief Set this object Dynamic (the bounding change...) + */ + void SetDynamic(void); + /** + * @brief Set bounding type + * @param[in] type Selected bounding methode (if no set, by default it does not have one) + */ + void SetBoundingMode(game::boundingMode type); + /** + * @brief Update the bounding properties. + */ + void BoundingUpdate(void); + }; +}; + + +#endif diff --git a/sources/ewol/game/Map.cpp b/sources/ewol/game/Map.cpp new file mode 100644 index 00000000..4b6d4347 --- /dev/null +++ b/sources/ewol/game/Map.cpp @@ -0,0 +1,7 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ diff --git a/sources/ewol/game/Map.h b/sources/ewol/game/Map.h new file mode 100644 index 00000000..e56700f9 --- /dev/null +++ b/sources/ewol/game/Map.h @@ -0,0 +1,15 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __GAME_MAP_H__ +#define __GAME_MAP_H__ + +#include "ewol/debug.h" + + +#endif diff --git a/sources/ewol/game/Mass.cpp b/sources/ewol/game/Mass.cpp new file mode 100644 index 00000000..4b6d4347 --- /dev/null +++ b/sources/ewol/game/Mass.cpp @@ -0,0 +1,7 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ diff --git a/sources/ewol/game/Mass.h b/sources/ewol/game/Mass.h new file mode 100644 index 00000000..d069287c --- /dev/null +++ b/sources/ewol/game/Mass.h @@ -0,0 +1,25 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __GAME_MASS_H__ +#define __GAME_MASS_H__ + +#include "ewol/debug.h" + + + +namespace game +{ + class Mass + { + + }; +}; + + +#endif diff --git a/sources/ewol/game/MeshObject.h b/sources/ewol/game/MeshObject.h new file mode 100644 index 00000000..e7c8b10b --- /dev/null +++ b/sources/ewol/game/MeshObject.h @@ -0,0 +1,33 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __GAME_MESH_OBJECT_H__ +#define __GAME_MESH_OBJECT_H__ + +#include +#include +#include +#include + +namespace game +{ + class MeshObject + { + public: + etk::Vector m_indices; + etk::Vector m_vertices; + etk::Vector m_uvTextures; + etk::Vector m_normals; + public: + MeshObject(void) {}; + virtual ~MeshObject(void) {}; + }; +}; + + +#endif \ No newline at end of file diff --git a/sources/ewol/game/MeshProperty.h b/sources/ewol/game/MeshProperty.h new file mode 100644 index 00000000..94499790 --- /dev/null +++ b/sources/ewol/game/MeshProperty.h @@ -0,0 +1,82 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __GAME_MESH_PROPERTY_H__ +#define __GAME_MESH_PROPERTY_H__ + +#include +#include +#include +#include + +namespace game +{ + class MeshProperty + { + public: + vec3 m_scale; //!< scale of the element. + vec3 m_position; //!< position of the element. + vec3 m_speed; //!< Speed of the element. + vec3 m_angle; + mat4 m_rotation; //!< rotation matrix ... + bool needUpdate; + mat4 m_matrix; //!< generated dispaly matrix. + public: + MeshProperty(void) : + m_position(0,0,0), + m_speed(0,0,0), + needUpdate(true) + { + //m_matrix.Identity(); + }; + virtual ~MeshProperty(void) {}; + + void Identity(void) + { + m_position = vec3(0,0,0); + m_speed = vec3(0,0,0); + m_angle = vec3(0,0,0); + m_matrix.Identity(); + }; + void Translate(etk::Vector3D vect) + { + m_position += vect; + needUpdate = true; + } + void Scale(etk::Vector3D vect) + { + m_scale = vect; + needUpdate = true; + } + void Rotate(etk::Vector3D vect, float angleRad=0.0) + { + m_rotation *= etk::matRotate(vect, angleRad); + needUpdate = true; + } + mat4& GetMatrix(void) + { + if (needUpdate == true) { + m_matrix = etk::matScale(m_scale) * m_rotation * etk::matTranslate(m_position); + } + return m_matrix; + }; + vec3& GetSpeed(void) + { + return m_speed; + } + vec3& GetPosition(void) + { + return m_position; + } + }; +}; + + +#endif + + diff --git a/sources/ewol/game/SceneElement.cpp b/sources/ewol/game/SceneElement.cpp deleted file mode 100644 index 8749bce7..00000000 --- a/sources/ewol/game/SceneElement.cpp +++ /dev/null @@ -1,506 +0,0 @@ -/** - * @author Edouard DUPIN - * - * @copyright 2011, Edouard DUPIN, all right reserved - * - * @license BSD v3 (see license file) - */ - -#include -#include -#include -#include -#include - -static uint32_t createUniqueId(uint16_t uniqueID, uint16_t position) -{ - return ((uint32_t)uniqueID<< 16) + (uint32_t)position; -} - - -ewol::SceneElement::SceneElement(void) -{ - m_id = 1; - numberOfGroup = MAX_GROUP_NUMBER; - for (int32_t iii=0; iiiname = name; - tmpElement->userString = userString; - tmpElement->loadElement = loadElement; - listCreatorElement.PushBack(tmpElement); -} - - -void ewol::SceneElement::RmElement(int16_t group, int16_t idElement) -{ - if (group < 0 || group >= MAX_GROUP_NUMBER) { - EWOL_ERROR("group is wrong " << group << "!=[0," << MAX_GROUP_NUMBER << "]==> not rm at the system ..."); - return; - } - if (idElement < 0 || idElement >= listAnimatedElements[group].Size()) { - EWOL_ERROR("idElement is wrong " << idElement << "!=[0," << listAnimatedElements[group].Size() << "]==> not rm at the system ..."); - return; - } - if (NULL == listAnimatedElements[group][idElement]) { - return; - } - // inform remove system : - SendEventRemove(createUniqueId(listAnimatedElements[group][idElement]->GetUniqueId(), idElement) ); - - // try to find an empty slot : - for (int32_t iii=0; iiiUnInit(); - listGarbage.PushBack(listAnimatedElements[group][idElement]); - listAnimatedElements[group][idElement] = NULL; - return; -} - -void ewol::SceneElement::RmElement(int32_t idElement) -{ - if (0 == idElement) { - return; - } - uint16_t realUniqueId = (uint16_t)((idElement >> 16 ) & 0x0000FFFF); - uint16_t posInList = (uint16_t)(idElement & 0x0000FFFF); - for (int32_t iii=0; iiiGetUniqueId()) { - RmElement(iii, posInList); - return; - } - } -} - -uint32_t ewol::SceneElement::AddElement(int32_t group, ewol::GameElement* newElement) -{ - if (NULL == newElement) { - EWOL_ERROR("newElement is empty ==> not added at the system ..."); - return 0; - } - if (group < 0 || group >= MAX_GROUP_NUMBER) { - EWOL_ERROR("group is wrong " << group << "!=[0," << MAX_GROUP_NUMBER << "]==> not added at the system ..."); - return 0; - } - // for statistic - newElement->Init(); - newElement->GroupSet(group); - for (int32_t iii=0; iiiGetUniqueId(), iii); - } - } - //did not find empty slot : - listAnimatedElements[group].PushBack(newElement); - if (listAnimatedElements[group].Size()>0) { - return createUniqueId(newElement->GetUniqueId(), listAnimatedElements[group].Size()-1); - } else { - return 0; - } -} - -uint32_t ewol::SceneElement::AddElementNamed(int32_t group, etk::UString &elementName) -{ - // try to fined it in the garbase : - for (int32_t iii=0; iiiHasName(elementName)) { - // we find a previous element loaded ==> retreve it - int32_t idElementBackAdded = AddElement(group, listGarbage[iii]); - listGarbage[iii] = NULL; - retreviveElement++; - return idElementBackAdded; - } - } - } - ewol::GameElement* newElement=NULL; - // find in registered element - for (int32_t iii=0; iiiname == elementName) { - // create a new element : - allocatedElements ++; - newElement = (*listCreatorElement[iii]->loadElement)(*this, elementName, listCreatorElement[iii]->userString); - // we find a previous element loaded ==> retreve it - return AddElement(group, newElement); - } - } - } - allocatedElements++; - return AddElement(group, newElement); -} - - -ewol::GameElement* ewol::SceneElement::GetElement(uint32_t idElement) -{ - if (0 == idElement) { - return NULL; - } - uint16_t realUniqueId = (uint16_t)((idElement >> 16 ) & 0x0000FFFF); - uint16_t posInList = (uint16_t)(idElement & 0x0000FFFF); - for (int32_t iii=0; iiiGetUniqueId()) { - return listAnimatedElements[iii][posInList]; - } - } - return NULL; -} - - -uint32_t ewol::SceneElement::GetNearestEnemy(vec2 position, int32_t groupId, float maxRange) -{ - uint32_t result = 0; - float lastQuadDistance = 9999999999999999.0; - int32_t jjj=0; - if (groupId <0 || groupId >= MAX_GROUP_NUMBER) { - EWOL_ERROR("incorect group number : " << groupId); - return 0; - } - maxRange = maxRange*maxRange; - while (groupEnemy[groupId][jjj] != -1) { - int32_t gId = groupEnemy[groupId][jjj]; - if (gId == groupId) { - EWOL_ERROR("groupId=" << gId << " is ennemy of groupId:" << groupId); - } - for (int32_t iii=0; iiiIsEnable() - && true == listAnimatedElements[gId][iii]->CanBeCibledGet()) { - vec2 tmpPos = listAnimatedElements[gId][iii]->PositionGet(); - float distance = quadDist(position, tmpPos); - if( distance <= lastQuadDistance - && maxRange >= distance ) { - lastQuadDistance = distance; - result = createUniqueId(listAnimatedElements[gId][iii]->GetUniqueId(), iii); - } - } - } - } - jjj++; - } - return result; -} - -void ewol::SceneElement::GetNearestEnemy(vec2 position, int32_t groupId, float maxRange, etk::Vector& list) -{ - // remove all elements.. - list.Clear(); - int32_t jjj=0; - if (groupId <0 || groupId >= MAX_GROUP_NUMBER) { - EWOL_ERROR("incorect group number : " << groupId); - return; - } - maxRange = maxRange*maxRange; - while (groupEnemy[groupId][jjj] != -1) { - int32_t gId = groupEnemy[groupId][jjj]; - if (gId == groupId) { - EWOL_ERROR("groupId=" << gId << " is ennemy of groupId:" << groupId); - } - for (int32_t iii=0; iiiIsEnable() - && true == listAnimatedElements[gId][iii]->CanBeCibledGet()) { - vec2 tmpPos = listAnimatedElements[gId][iii]->PositionGet(); - float distance = quadDist(position, tmpPos); - if(maxRange >= distance) { - uint32_t tmpp = createUniqueId(listAnimatedElements[gId][iii]->GetUniqueId(), iii); - list.PushBack(tmpp); - } - } - } - } - jjj++; - } -} - -uint32_t ewol::SceneElement::GetNearestFriend(vec2 position, int32_t groupId, uint32_t us) -{ - uint32_t result = 0; - float lastQuadDistance = 9999999999999999.0; - if (groupId <0 || groupId >= MAX_GROUP_NUMBER) { - EWOL_ERROR("incorect group number : " << groupId); - return 0; - } - int32_t gId = groupId; - for (int32_t iii=0; iiiIsEnable() - && true == listAnimatedElements[gId][iii]->CanBeCibledGet()) { - vec2 tmpPos = listAnimatedElements[gId][iii]->PositionGet(); - float distance = quadDist(position, tmpPos); - if( distance <= lastQuadDistance - && us != listAnimatedElements[gId][iii]->GetUniqueId() ) { - lastQuadDistance = distance; - result = createUniqueId(listAnimatedElements[gId][iii]->GetUniqueId(), iii); - } - } - } - } - return result; -} - - -void ewol::SceneElement::GetNearestFriend(vec2 position, int32_t groupId, float maxRange, etk::Vector& list, uint32_t us) -{ - // remove all elements.. - list.Clear(); - if (groupId <0 || groupId >= MAX_GROUP_NUMBER) { - EWOL_ERROR("incorect group number : " << groupId); - return; - } - maxRange = maxRange*maxRange; - for (int32_t iii=0; iiiIsEnable() - && true == listAnimatedElements[groupId][iii]->CanBeCibledGet()) { - vec2 tmpPos = listAnimatedElements[groupId][iii]->PositionGet(); - float distance = quadDist(position, tmpPos); - if( maxRange >= distance - && us != listAnimatedElements[groupId][iii]->GetUniqueId() ) { - uint32_t tmpp = createUniqueId(listAnimatedElements[groupId][iii]->GetUniqueId(), iii); - list.PushBack(tmpp); - } - } - } - } -} - -bool ewol::SceneElement::HaveImpact(int32_t group, int32_t type, vec2 position, float size) -{ - for (int32_t jjj=0; jjjIsEnable() - && true == listAnimatedElements[jjj][iii]->HaveImpact(group, type, position, size )) { - return true; - } - } - } - } - } - return false; -} - -void ewol::SceneElement::Explosion(int32_t group, int32_t type, vec2 position, float pxAtenuation, float power) -{ - for (int32_t jjj=0; jjjIsEnable() - && true == listAnimatedElements[jjj][iii]->Explosion(group, type, position, pxAtenuation, power) ) { - RmElement(jjj, iii); - } - } - } - } -} - - -uint32_t ewol::SceneElement::GetElementAtPos(vec2 position, int32_t maxDistanceDetection) -{ - uint32_t result = 0; - float lastQuadDistance = 9999999999999999.0; - for (int32_t jjj=0; jjjIsEnable()) { - vec2 tmpPos = listAnimatedElements[jjj][iii]->PositionGet(); - float distance = quadDist(position, tmpPos); - if (distance <= lastQuadDistance) { - lastQuadDistance = distance; - result = createUniqueId(listAnimatedElements[jjj][iii]->GetUniqueId(), iii); - } - } - } - } - } - if (lastQuadDistance > maxDistanceDetection*maxDistanceDetection) { - return 0; - } - return result; -} - -void ewol::SceneElement::SetEventInput(uint32_t id, vec2 position) -{ - EWOL_TODO("but when ..."); -} - -void ewol::SceneElement::SetEventExternButton(uint32_t id, int32_t btId, int32_t state) -{ - EWOL_TODO("but when ..."); -} - -void ewol::SceneElement::SetEventExternJoystick(uint32_t id, int32_t joyId, float angle, float distance, int32_t state) -{ - EWOL_TODO("but when ..."); -} - - -/** - * @brief Load or get a previous loaded sprite, it will be done on the current Sprite list - * @param[in,out] listOfElement Reference on the list of sprite that we need to find if it exist or added a new one - * @param[in] fileName Sprite name - * @param[in] maxSize maximum size of the sprite - * @return the id of the sprite requested or -1 if it does not existed - */ -int32_t ewol::SceneElement::LoadSprite(etk::UString fileName, float maxSize) -{ - for (int32_t iii=0; iiiHasName(fileName) == true) { - // count the number of element registered ... - animated[iii]->IncreaseLoadedTime(); - return iii; - } - } - } - // we did not find the sprite ==> created it ... - ewol::Sprite* tmpSprite = new ewol::Sprite(fileName, maxSize, maxSize); - if (NULL == tmpSprite) { - EWOL_ERROR("Allocation error on the sprite : " << fileName); - return -1; - } - // add it : - animated.PushBack(tmpSprite); - - return animated.Size() -1; -} - -/** - * @brief UnLoad or not(if needed) the sprite selected, it will be done on the current Sprite list - * @param[in,out] listOfElement Reference on the list of sprite that we need to find if it exist or added a new one - * @param[in] spriteId Sprite registered id - * @return --- - */ -void ewol::SceneElement::UnLoadSprite(int32_t spriteId) -{ - if (spriteId >= 0 && spriteId < animated.Size()) { - if (animated[spriteId] != NULL) { - // count the number of element registered ... - if (true == animated[spriteId]->DecreaseLoadedTime() ) { - // must remove the sprite ==> pb with the double buffer ... - delete(animated[spriteId]); - animated[spriteId] = NULL; - } - } - } -} - -void ewol::SceneElement::AddEarrerDestroy(uint32_t uId) -{ - //EWOL_DEBUG("ADD eraer : " << uId); - if (uId==0) { - return; - } - eventDestroy.PushBack(uId); -} - -void ewol::SceneElement::RmEarrerDestroy(uint32_t uId) -{ - //EWOL_DEBUG("RM eraer : " << uId); - if (uId==0) { - return; - } - for (int32_t iii=0; iiiMessage("Destroy", uId); - } - } - } -} diff --git a/sources/ewol/game/SceneElement.h b/sources/ewol/game/SceneElement.h deleted file mode 100644 index ef1a7f53..00000000 --- a/sources/ewol/game/SceneElement.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @author Edouard DUPIN - * - * @copyright 2011, Edouard DUPIN, all right reserved - * - * @license BSD v3 (see license file) - */ - -#ifndef __EWOL_SCENE_ELEMENT_H__ -#define __EWOL_SCENE_ELEMENT_H__ - -#include -#include -#include - -namespace ewol { - class GameElement; - class SceneElement; - - typedef ewol::GameElement* (creatorElement_tf)(SceneElement & sceneElement, etk::UString& tmpName, etk::UString& userString); - - class listRegisteElement { - public: - etk::UString name; //!< name of an element - etk::UString userString; //!< additionnal sting defined by the user - creatorElement_tf * loadElement; //!< callback function to create it - }; - #define MAX_GROUP_NUMBER (32) - - class SceneElement { - private: - int16_t m_id; //!< Unique element ID ==> to reference the element unicly - int32_t retreviveElement; - int32_t allocatedElements; - public: - SceneElement(void); - ~SceneElement(void); - etk::Vector eventDestroy; //!< element uid when element is destroy - int32_t numberOfGroup; //!< curent scene number of group - etk::UString groupDescription[MAX_GROUP_NUMBER]; //!< name of all the groups - int32_t groupEnemy[MAX_GROUP_NUMBER][MAX_GROUP_NUMBER]; //!< list of the ennemy - ewol::OObject2DTextured* background; //!< background element - etk::Vector animated; //!< element that must be display the second - etk::Vector listAnimatedElements[MAX_GROUP_NUMBER]; //!< generic element to display order in the diffferent group - etk::Vector listGarbage; //!< garbage of the old element allocated ==> prevent multiple alloc and free - etk::Vector listCreatorElement; //!< list of all creatable elements - int16_t GetUniqueId(void) { int16_t iddd = m_id; m_id++; return iddd; }; - void RegisterElementType(etk::UString name, creatorElement_tf * loadElement, etk::UString userString); - void RmElement(int16_t group, int16_t posInList); - void RmElement(int32_t elementID); - uint32_t AddElement(int32_t group, ewol::GameElement* newElement); - uint32_t AddElementNamed(int32_t group, etk::UString &elementName); - ewol::GameElement* GetElement(uint32_t idElement); - uint32_t GetNearestEnemy(vec2 position, int32_t groupId, float maxRange=9999999999999999.0); - void GetNearestEnemy(vec2 position, int32_t groupId, float maxRange, etk::Vector& list); - uint32_t GetNearestFriend(vec2 position, int32_t groupId, uint32_t us); - void GetNearestFriend(vec2 position, int32_t groupId, float maxRange, etk::Vector& list, uint32_t us); - bool HaveImpact(int32_t group, int32_t type, vec2 position, float size); - void Explosion(int32_t group, int32_t type, vec2 position, float pxAtenuation, float power); - uint32_t GetElementAtPos(vec2 position, int32_t maxDistanceDetection); - void SetEventInput(uint32_t id, vec2 position); - void SetEventExternButton(uint32_t id, int32_t btId, int32_t state); - void SetEventExternJoystick(uint32_t id, int32_t joyId, float angle, float distance, int32_t state); - /** - * @brief Load or get a previous loaded sprite, it will be done on the current Sprite list - * @param[in] fileName Sprite name - * @param[in] maxSize maximum size of the sprite - * @return the id of the sprite requested or -1 if it does not existed - */ - int32_t LoadSprite(etk::UString fileName, float maxSize); - /** - * @brief UnLoad or not(if needed) the sprite selected, it will be done on the current Sprite list - * @param[in,out] listOfElement Reference on the list of sprite that we need to find if it exist or added a new one - * @param[in] spriteId Sprite registered id - * @return --- - */ - void UnLoadSprite(int32_t spriteId); - void AddEarrerDestroy(uint32_t uId); - void RmEarrerDestroy(uint32_t uId); - void SendEventRemove(uint32_t uId); - ewol::OObject2DTextured* GetBackground(void) { return background; }; - }; -}; - -#endif - diff --git a/sources/ewol/game/Sky.cpp b/sources/ewol/game/Sky.cpp new file mode 100644 index 00000000..4b6d4347 --- /dev/null +++ b/sources/ewol/game/Sky.cpp @@ -0,0 +1,7 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ diff --git a/sources/ewol/game/Sky.h b/sources/ewol/game/Sky.h new file mode 100644 index 00000000..334a607b --- /dev/null +++ b/sources/ewol/game/Sky.h @@ -0,0 +1,15 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __EPHYSICS_SKY_H__ +#define __EPHYSICS_SKY_H__ + +#include "ewol/debug.h" + + +#endif diff --git a/sources/ewol/renderer/resources/Mesh.cpp b/sources/ewol/renderer/resources/Mesh.cpp index 1cf3afdd..8a9a52f1 100644 --- a/sources/ewol/renderer/resources/Mesh.cpp +++ b/sources/ewol/renderer/resources/Mesh.cpp @@ -61,7 +61,7 @@ void ewol::Mesh::Draw(mat4& positionMatrix) m_GLprogram->Use(); // set Matrix : translation/positionMatrix mat4 tmpMatrix = ewol::openGL::GetMatrix(); - tmpMatrix = positionMatrix * tmpMatrix; + tmpMatrix = tmpMatrix * positionMatrix; m_GLprogram->UniformMatrix4fv(m_GLMatrix, 1, tmpMatrix.m_mat); // TextureID m_GLprogram->SetTexture0(m_GLtexID, m_texture1->GetId()); diff --git a/sources/ewol/renderer/resources/Mesh.h b/sources/ewol/renderer/resources/Mesh.h index f47c6f0e..0e8ba275 100644 --- a/sources/ewol/renderer/resources/Mesh.h +++ b/sources/ewol/renderer/resources/Mesh.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include namespace ewol { @@ -27,7 +27,7 @@ namespace ewol int32_t m_GLColor; int32_t m_GLtexture; int32_t m_GLtexID; - ephysics::MeshObject m_object; + game::MeshObject m_object; ewol::TextureFile* m_texture1; etk::Vector m_coordColor; //!< internal color of the different point public: diff --git a/sources/ewol/renderer/resources/image/ImagePNG.cpp b/sources/ewol/renderer/resources/image/ImagePNG.cpp index bdcd7a4e..83fb99af 100644 --- a/sources/ewol/renderer/resources/image/ImagePNG.cpp +++ b/sources/ewol/renderer/resources/image/ImagePNG.cpp @@ -14,7 +14,7 @@ #undef __class__ -#define __class__ "texture::TextureBMP" +#define __class__ "texture::TexturePNG" // we must change the access of the IO of the png lib : static void local_ReadData(png_structp png_ptr, png_bytep data, png_size_t length) @@ -97,6 +97,7 @@ bool ewol::imagePNG::GenerateImage(etk::UString & inputFile, draw::Image & ouput int32_t width = png_get_image_width(png_ptr, info_ptr); int32_t height = png_get_image_height(png_ptr, info_ptr); // reallocate the image + EWOL_DEBUG("Load PNG image : (" << width << "," << height << ")" ); ouputImage.Resize(ivec2(width,height)); int32_t bit_depth = png_get_bit_depth(png_ptr, info_ptr); @@ -113,27 +114,47 @@ bool ewol::imagePNG::GenerateImage(etk::UString & inputFile, draw::Image & ouput png_read_image(png_ptr, row_pointers); png_set_expand(png_ptr); png_set_strip_16(png_ptr); - if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGBA) { - EWOL_ERROR("Must be RGBA"); - return false; - } draw::Color tmpColor(0,0,0,0); - // Conversion to OpenGL texture - //texture = (GLubyte*)malloc (width * height * 4 * sizeof(GLubyte)); - for (y = 0; y < height; y++) + switch (png_get_color_type(png_ptr, info_ptr) ) { - png_byte* row = row_pointers[y]; - for (x = 0; x < width; x++) - { - png_byte* ptr = &(row[x*4]); - tmpColor.r = ptr[0]; - tmpColor.g = ptr[1]; - tmpColor.b = ptr[2]; - tmpColor.a = ptr[3]; - ouputImage.Set(ivec2(x,y), tmpColor); - } - delete row_pointers[y]; + case PNG_COLOR_TYPE_RGBA: + // Conversion to OpenGL texture + for (y = 0; y < height; y++) + { + png_byte* row = row_pointers[y]; + for (x = 0; x < width; x++) + { + png_byte* ptr = &(row[x*4]); + tmpColor.r = ptr[0]; + tmpColor.g = ptr[1]; + tmpColor.b = ptr[2]; + tmpColor.a = ptr[3]; + ouputImage.Set(ivec2(x,y), tmpColor); + } + delete row_pointers[y]; + } + break; + case PNG_COLOR_TYPE_RGB: + // Conversion to OpenGL texture + for (y = 0; y < height; y++) + { + png_byte* row = row_pointers[y]; + for (x = 0; x < width; x++) + { + png_byte* ptr = &(row[x*3]); + tmpColor.r = ptr[0]; + tmpColor.g = ptr[1]; + tmpColor.b = ptr[2]; + tmpColor.a = 0xFF; + ouputImage.Set(ivec2(x,y), tmpColor); + } + delete row_pointers[y]; + } + break; + default: + EWOL_ERROR("Must be RGBA/RGB"); + return false; } fileName.FileClose(); diff --git a/sources/ewol/widget/Scene.cpp b/sources/ewol/widget/Scene.cpp index 673db8cb..01dd2a29 100644 --- a/sources/ewol/widget/Scene.cpp +++ b/sources/ewol/widget/Scene.cpp @@ -21,7 +21,7 @@ widget::Scene::Scene(game::Engine* gameEngine) : { SetCanHaveFocus(true); PeriodicCallSet(true); - m_zoom = 1.0; + m_zoom = 1.0/1000.0; } @@ -63,21 +63,6 @@ void widget::Scene::PauseToggle(void) void widget::Scene::OnDraw(ewol::DrawProperty& displayProp) { - /* - //EWOL_ERROR(" On draw : " << m_currentDrawId); - // draw background : - // TODO : ... - if (NULL != m_sceneElement.background) { - m_sceneElement.background->Draw(); - } - //background - // draw elements - for (int32_t iii=0; iiiDraw(); - } - } - */ if (NULL != m_gameEngine) { m_gameEngine->Draw(displayProp); } @@ -122,7 +107,6 @@ void widget::Scene::GenDraw(ewol::DrawProperty displayProp) // set internal matrix system : ewol::openGL::SetMatrix(tmpMat); } else { - m_zoom = 1.0/1000.0; //EWOL_INFO("ratio : " << ratio); mat4 tmpProjection; @@ -177,3 +161,47 @@ vec2 widget::Scene::RelativePosition(vec2 pos) return pos; }; + +bool widget::Scene::OnEventInput(ewol::keyEvent::type_te type, int32_t IdInput, ewol::keyEvent::status_te statusEvent, vec2 pos) +{ + vec2 relativePos = RelativePosition(pos); + //EWOL_DEBUG("type : " << type << " IdInput=" << IdInput << " " << "status=" << statusEvent << " RelPos=" << relativePos); + + if (type == ewol::keyEvent::typeMouse) { + if (4 == IdInput && ewol::keyEvent::statusUp == statusEvent) { + m_zoom *= 0.91; + } else if (5 == IdInput && ewol::keyEvent::statusUp == statusEvent) { + m_zoom *= 1.1; + } + } else if (type == ewol::keyEvent::typeFinger) { + + } + // note : we did not parse the oether media ... + + return false; +} + + +bool widget::Scene::OnEventKb(ewol::keyEvent::status_te statusEvent, uniChar_t unicodeData) +{ + /* + EWOL_DEBUG("KB EVENT : \"" << unicodeData << "\"" << "type=" << statusEvent); + if (statusEvent == ewol::ewol::keyEvent::statusDown) { + + } + */ + return false; +} + + +bool widget::Scene::OnEventKbMove(ewol::keyEvent::status_te statusEvent, ewol::keyEvent::keyboard_te specialKey) +{ + /* + if (statusEvent == ewol::ewol::keyEvent::statusDown) { + MarkToRedraw(); + } + return true; + */ + return false; +} + diff --git a/sources/ewol/widget/Scene.h b/sources/ewol/widget/Scene.h index 3eea8059..6cbcd608 100644 --- a/sources/ewol/widget/Scene.h +++ b/sources/ewol/widget/Scene.h @@ -48,18 +48,10 @@ namespace widget { * @brief Toggle between pause and running */ void PauseToggle(void); - /** - * @brief extern interface to request a draw ... (called by the drawing thread [Android, X11, ...]) - * This function generate a clipping with the viewport openGL system. Like this a widget draw can not draw over an other widget - * @note This function is virtual for the scrolled widget, and the more complicated OpenGl widget - */ + // Derived function virtual void GenDraw(ewol::DrawProperty displayProp); protected: - /** - * @brief Periodic call in the sub element timed - * @param localTime curent system time - * @param deltaTime delta time while the previous call - */ + // Derived function virtual void ScenePeriodicCall(int64_t localTime, int32_t deltaTime) { }; // camera properties : private: @@ -91,6 +83,12 @@ namespace widget { // Derived function virtual void OnDraw(ewol::DrawProperty& displayProp); + // Derived function + virtual bool OnEventInput(ewol::keyEvent::type_te type, int32_t IdInput, ewol::keyEvent::status_te statusEvent, vec2 pos); + // Derived function + virtual bool OnEventKb(ewol::keyEvent::status_te statusEvent, uniChar_t unicodeData); + // Derived function + virtual bool OnEventKbMove(ewol::keyEvent::status_te statusEvent, ewol::keyEvent::keyboard_te specialKey); }; }; diff --git a/sources/file.mk b/sources/file.mk index 2a3ffb07..cd05397a 100644 --- a/sources/file.mk +++ b/sources/file.mk @@ -81,7 +81,16 @@ FILE_LIST+= ewol/widget/Widget.cpp \ # game mode area : FILE_LIST+= ewol/widget/Scene.cpp \ ewol/game/Engine.cpp \ - ewol/game/Element.cpp + ewol/game/Element.cpp \ + ewol/game/Bounding.cpp \ + ewol/game/BoundingAABB.cpp \ + ewol/game/BoundingOBB.cpp \ + ewol/game/BoundingPlane.cpp \ + ewol/game/BoundingSphere.cpp \ + ewol/game/Geometry.cpp \ + ewol/game/Map.cpp \ + ewol/game/Mass.cpp \ + ewol/game/Sky.cpp LOCAL_COPY_FILES := ../data/textured3D.prog:textured3D.prog \ diff --git a/test/human/appl/TestScene.cpp b/test/human/appl/TestScene.cpp index a545f2eb..12615cab 100644 --- a/test/human/appl/TestScene.cpp +++ b/test/human/appl/TestScene.cpp @@ -28,6 +28,9 @@ static const char * l_eventAddBox = "event-add-box"; static const char * l_eventAddSphere = "event-add-sphere"; +static const char * l_eventRotationX = "event-rotation-X"; +static const char * l_eventRotationY = "event-rotation-Y"; +static const char * l_eventRotationZ = "event-rotation-Z"; @@ -58,6 +61,21 @@ TestScene::TestScene(void) myButton->RegisterOnEvent(this, ewolEventButtonPressed, l_eventAddSphere); mySizerHori->SubWidgetAdd(myButton); } + myButton = new widget::Button("Rotation X"); + if (NULL != myButton) { + myButton->RegisterOnEvent(this, ewolEventButtonPressed, l_eventRotationX); + mySizerHori->SubWidgetAdd(myButton); + } + myButton = new widget::Button("Rotation Y"); + if (NULL != myButton) { + myButton->RegisterOnEvent(this, ewolEventButtonPressed, l_eventRotationY); + mySizerHori->SubWidgetAdd(myButton); + } + myButton = new widget::Button("Rotation Z"); + if (NULL != myButton) { + myButton->RegisterOnEvent(this, ewolEventButtonPressed, l_eventRotationZ); + mySizerHori->SubWidgetAdd(myButton); + } widget::Spacer* mySpacer = new widget::Spacer(); if (NULL != mySpacer) { @@ -129,10 +147,19 @@ TestScene::~TestScene(void) #include + +vec3 baseRotationVect; class stupidCube : public game::Element { public: stupidCube(void) : game::Element("DATA:cube.obj") {}; + + // herited methode + virtual bool ArtificialIntelligence(int32_t deltaMicroSecond) + { + m_property.Rotate(baseRotationVect, 0.01); + return false; + } }; @@ -158,6 +185,12 @@ void TestScene::OnReceiveMessage(ewol::EObject * CallerObject, const char * even if (NULL!=m_testWidget) { } + } else if (eventId == l_eventRotationX) { + baseRotationVect = vec3(1,0,0); + } else if (eventId == l_eventRotationY) { + baseRotationVect = vec3(0,1,0); + } else if (eventId == l_eventRotationZ) { + baseRotationVect = vec3(0,0,1); } return; diff --git a/test/human/data/cube.bmp b/test/human/data/cube.bmp deleted file mode 100644 index 63b4df8e4ab5627496e5b19e453a9428a25e8ce2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196662 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 z zm(6TVA!{^}P)xi${C^z(8Rr7G$ypaxL@NE!xpJ?cuJO+KT4OHMz9YBMZE5gR*MfvT z3*tQ9zw+{P=kJ5;j^eyhO=f*28QqqRlg zDJ2W_3h%JC7>IFL(Vnk{WcK)`Sj}@;)wkDX?rA)*4?(sEo&)>azHUO}8FNvBqfFCX z{WedUlsDR-XEYSMY;y9h(Yxyo*^r5ekxC>4)IALKJM#0;zwSc$b5+=^*PqJ1<7lOc zc|)}S{CDeHIM_L`@!FbD#-UeKy}|57VIMPjpN^*SPKipxAwuoU6F*kMa4Pa6*#79H z`}&=2++$ZZ)M0&0jKL$9LUj--5F&aUc`=s#-7_bwZGrRC|40tBLw?MB>^n#b%!R3Q zyae#m1{&7Ge>gGm(#)LJ^SYIrGbxO;N=RGV&QwH=!2iXFXkA9Zm~3F<%X>9hUwi!9 zCD~T5Y^WN&N5%-I7t}i%N9;>L%=H~X_1QsfrJ;DuNE)$aESR1aKW4u5ZqqN1ywW4p z#Dp4w1#R`|`SM2}UT&y)e%39P7gu=K03pFVSl`Ni5lSS+9FuTYjtz)uABF zvS?ssL#kZrhWQT{AN%QC?Y#d9DG1Afm0n&b6-U;=xGM9Wuk+CPmN^BX4k2t`j9bja z7XLQ{IXjlR_{y~3zT3(pNdJWL)J+JFK!>K**HXcW0K+#I0@_|{yS^lZ zHDf|p9xSP*qn$JM^)BB1i;8u>Xi{#tw9gk14jmd%qy85XZBOM$ZjsQd{K)jw z=nlurQST(0bnopI8o{l>4E*fi82*KRd@!T@fK%P+dE>k>=a>8$8v=rW_Q1d7AG!B< zI0LGj0>y$i0`r9DYgFIR6c0rBl_E6#M4`gW+xF)SUc?VgWL~fl1npL1*4P2dE0c5r z$PxBxnpbOhK@Wq8F^Jk^{PN({Qut{_hyEG)(vS0A$mzSg^z1_ehhOLJGwI@?;>14aGS*MKOdZ1VK#krG@AK&ofJ5vE$=m7rlAEQW^53?)CAgDrIOHaf1x$dQ^+V}5S{oOonm(S8G4R`xeU8`eeW**tE*o_v9TMtnEbC)Fm)-vucXKgU=Gtjp^B#GTnCPC$OiVGHBMDX83xGRI1em=AKq!JI_u zmyEQVIdIg+Sr{hFgE|85sZO^Iorv>@`S7-Av$O_d5P^Te?8F1BO85P)+;`hv8*s>8OtcCYl?U2kW8^%3!J%Vz#K zyULXKG))AqT8SRO)d3qh*J8whMqT8$H&0ezVUPTBbn)V!YmfSnwl~x+ zw-(w3_Y5^EM`Q9eZ4*KtqRlLCqjf_b>pW^@aef@3qs_P*C`YS&6ss;sJNxEGaOz%*aIiJee!f|nh;_s%qKodymdMh245PHpSDrtpZ;gZUrt`l zg?RXEy@{8GHAt3x_Uq0|XO<>bsJ`SMTpFp+dfLrncwaOd4bvcfca`dLzE;nkMVaJ2ZB~=10DJ{qFwXS8DxZi3c`S-8#F?!gm@xI1*71=W9VsuK7H{$*sFa2wHKGJxScYo6g&d?*%~#fUEfVL~ zJ9q>9kF7BGaO0a#`x;R`v{+gM9=q*P$fT}~caQ>2$MVMX)v`?-CG^HzPObs%@z~p0 zQ#RFIx%cr|8(SFDbOO0xaB)apCxQX+OfXpbFK!9;^cbB_CGv2=5@?Ofh?9Uy_x)wX z&&^jtCzf1U)ahjF2Fpj4xi5sisrnFAJ6cZghi*}z6(gcy%GLU&{}Wvamkqmc7aPm& zMhG*{g11ZW2`ITQ(i^8=cHfct;g$!~52VDDlQj?{>^$rIy^9yOgke;{vuz)m_~<}z z*_7+)7nyG}T&R8Ir$6--F{0kdGCgt|^*C4&?V&E-o*pF2E4w?+Ls4)9m;f|JEQJev z$DZs#r<#6n<*nLLszW^O5!%TD{EPnx`^WA;yZp{?|NJUeW>`T`i-R8nz`^;cR~NjT zs`~ijv}?NK;vJ0xdnHHCOCRr8;iHe*HTM`i@gf!A$@W3NEqK1v>x&z{zxSa-d0W#+ zd0sa1pwcX{OuN zdmQpzl~-Oa<$OXR*3EGPHv7mA&IuBv1`=QZmEua+L4kmiVw|)zC`l-NZbfZ?R1nFa zlI--^mmYrq`>kz1m=p$j_Er~L6XJ*mfY=2#x8jg_edo3bBz8r37zjkXNfvX@TJgl= z2!C)!J_yl|z{FN325rh(_37{{mrffs0DHv;1no^2T=~ngiKlxH*;vfe!atE|cRJ9X z`cdWs`YIM=yC+JDkP9(EUQnvexP8q9XEcI)k!y~mcH`Q3BW;CCun0I667tQkOj&1( zue{3WH_59d$PewnPv>)f1$^T1U!;g!bh>zl@+O8h1j+aPzFSg93_-hbe%A!jC6s0JhMw~ z)4He2^LZIoBvU?&>Da(uZDZ4#XS13e$#5y$-UCpx0)4)+1(ZKEPU7$@&Ik@Bpyy%4 zh1P#?ckSeA0A9mQ`ku{E1 z)o%0N|Q54C+Ve5s*K2wkzY`c!B6e0h0Y^z#7^_P#_|L%{+U;(>o5O#$rc|}cK8PD zw@{xBE%!!Tls*jr<}xl}nm$r!N8IWCN3xgBEYs)v@(WjYJ@d`7)QKJSk~yS+M0f^H zfmx0HlN}qLs#12^48sAkphG&)jE6CzVokm_DXe(=HNZ~_>aA%ns}PxN5VfS(GBtt- zeU_WCeQk*|eKOr$6`GTS64H7Lz4cAM5`hb+~da<}am{6wdPj}!-8&Md!`^5_3@;$*Xkp@FV=jzFRaKcRqaFo0wn z00R-Mz?7(E0Dx^e&<|rWjG~ANqQ{s?^P@qsSQaRitSBuI>E)BkrIfX9Ol0k^E2T6~ z$Q@JXcqRTFFR#k79xd0^7`i%(tRdb)PaI5xsveRPfvuq&v8;JuqX|eFIaSlRw7QM(%T)G-mU$Gs%BSVTv54(Q2D_I@HD@eXRP+) zBcecEF7_-qBzipnj2m~k5YBJ#bxxJZC!%#33c=udUo{;W@$h<<|8lBx&JP32KKxaq z7U#=-ae0MD!v9U2mtj6GHLS^F3pv7Js)A&s<-O>C!@*&;{_)ZwLu2uP${+L?bT*qN zc`2#`_IlKkt0UX0df1B35_8SS_#v_ARKg7I8&6`rUTZjx8SdHh`|Gd&{O-V;S3Xor z?eFHwIxk`nk~*R_&iE{bTq_P-(EH_9qgQ6)*fcGg5l7Ovv=E|aIk^l0c7*X#{xE>* z_!kiXPT&VcMh*T+0e&K`LJtEi%PUUevY>)_GApj%e@}U%sFa?tj4Tn3Fj%qzR5V9y z`iU8}wzMie@U6zn+KG)LihMd^C9472W07==m=2Lg@NFNb5C& zjPaNwRV*=H6oRiOYfcHNcMneeVn!VU)0~ty7AAV13oDlLg6BmA+!$`P9gw2MQEi7w zJc3h+BNlUN7D8CO0F;mEF=k5hi+|#K-u;DzIH2)H4;z3Z+Up>`YO;c|dL-yny&0ffzVzeFGH%Sn8a zpo|DVyRG}yi>qWglIS?&%i?`$v=_PKgj?zNW5@ou_uhZQ1l(Wo`9dtHARex_FD5J` zs4)wkAV-Dc%;n#;=$@C3+`ZL9Oa;0i31D^FC)ESY;kAM=W^TN z!D(m@5x{(aoOcYL;vsB@akRImhu^v&dm-`W(&Pb_wdMR`2($`(QY_*Otbl2TEW)5v z*G9+7ES^wWceo&vfkC-AyTd&fhw(5h5$uWhd7jCOvb%0C`^e57hc0g8HnP+fiHlpz zye$++7H+`?G$~1qj&Y~&SU5Y=^Bn1x*!WUn*_kj3fc69bjK2o))4ldeGBN2~V&%Lb z0z4YrN#ocAku-Z=_v(9g%vYZQiz|4eju!_N3H$UxCloyY2Kz){@Zd`Y_1F#el@Z%e zuVs;VxbZ=SA5RQV?3iDKiLL9y_VwDtGkX%__a)x>p>&CytBz#xPM<-( zap8~`S73x9ez0c>BpO}Am89Zw?D@|VxwQ|SH%FMfl6{qpgm8^4bKUU_EX zt^+&n|8#MSSD&i#>ix27Xnv&~OY~W0$JmO*10Dg&E&Zn2)_SeJs?=^@2D(n|^P4b# zT$gsGzy%cz?$h>s1bF86IVjFU5930_L{OdJ(D3$c++mht)7{}xoL_E29G%`YrkP!gFAr2?&YqTY?wB7ZB4RdR;e^ zX|}d*)7~#nz5n#-(|>IK?F(DnXrdOPOogh@i0LWN;q%ayoj>-tnhJ8dPh#`lfd5yc z{2$i2P-ponnm6V^V%7A2QIDSFg|{mHy6)p5yUAjLX{Z;ucu1&3b`@rhwSL_@4 z!sfnDe%|4U_uIezT*HrsH{8^{=Ato`7mPNkM+SoMd$mnXIxlED@}q2EHYg0bNC>oZ zcma~ycTkKGbD)_~9SondfF_XwCy2~Ex+wev+DQsp?x0};a)hOOyiXoTNMOKEkbmod z2>S?5%8$kW`HU@cD~>$g=AN(1KlWw@Q6hSDtf?zh{esy+rf@LGr}HuJF&}2N`J#H| zXYY&C1Im?4&7S>JJY~%Ig5ewCI~5_^rC=Kx0zgjU1rt?}OSjmeheI!~j8?MKao zbvq?*QG-q2hjk6EedQvLbRE1XE8_VDZ+E@@+xsnfeRH!SuXDBKn`d6UuUopTN5P)D z>Hg)%Mx?v1$Q{-HL|F|0;n?&lK5X`lsGvz4AV&ksaq5+9^U&_++s}Qi){@}@k20Dn zzu&XfygTk#Tb}L(IeZ5G(GQ9p@rG(KLqok>0LVx69b7OwxCYLo=kXIm$(&_Jm<(bP zn9_g%8!S@37u*$)@2Y&UX!DJRP-i}Pxb4dj!zE7Brd ziEsGoQp+b~bzR)J(u7$eMd`*jM7U;6Fs33)1~iK-GH>zFbi)>`4l2A;WH%K$h!~`s zI;@!X^n~ky-(CJ&{6GD`c8I|H@BfmOb#o0|sq&e5OI}!aA-m8k{D)tkl$}-eCKbHX zJ#t&kJxoB6cT6{|cDK=(Ha(4XKZYN$ilJ^DHSe|c^iY16##WZz<4{xVvD0msEe?t@B--&IFbu`XxgJ6oO#zo zLX#P7VwLC4?981uP@DJ_oX3qLo-dT-j;<`=X&j9>@Ia+r_kX!r)sfG{r3uolZKrwj z{2yep+}dB>9aaDCg=UFcDUG{r)zxPczW8P3+cyBeN3g_mk+dg$&Pha`H8ySr*5qG+Ndrc)_(YvG6F9=*$^CV8vu{q;6?Iq z#1EMRxxRQlN0Q_0Am>*+B=!hIM;#$PP)#%#4vCIleBooo?pfOW-OVeFZvp^G9KEk` z+#o>CMsRH7uk6UG`~D@Z1^)MUEMB|syv%Y(3pI88b(0rVX_uWf7PC*F$|TSxz#<|F5?>;a`98_qX5v%*+3M$Kju5 zK>Nm2#e&aZAF7LGpDptB3mxn{@EwRP^z;Als|)rVG5;1t;Fj>u7jBdD(}Gzy)+c|r zPLxWK*Q-_xl0u(Q3XNFA*@<2J#A3?yyttx_4yh&*Jk%2wX@Puceunl$NEDWI9APF4 z_6H<8FWJBG&fTLM9jeuAcdZHYD^GYo1NVOOi4Yp4{FwmUhKQj?_W8wRfwq@q#X%4r zF|I@$L{p6s8z;qr$O3G8RPi(?;P7)BPI`FUshvB2|M}2?ISaGnSc($_;#wUH8AOHN zEB$q5)hQVzix|$1yB;@~I`zs8L_h__pO-JlAKVO*)7Ol5zWw4RBCzQ|=B4My-C{T0 zRR4F*?|$IQL$vz#i(PkJx^vsbj=L`n*m3cWofmt2liwKZzf5Lb5355b&nX1;>wWEZ z*PH(nBJkkcu{otqTzgZgL75c~`Sh<_;y-C0wsmnX?X9$}$p0^&E+#UCy06gJ3r~** zdyCG3_oRSML|d^Y*QnXCZW^wrav zjL^R3ci#*cV_z(VH7WE8*M2?JxMGW(jn_7N!6P|2sadmr5)LY;G2(sTH@p9OE9>3L zGQnprymReki#&2u{I^I}x*oi5dVK!I7G=sGDfrgc+oz~8mjAj4tj*1M`hy;g+pR5h zUlVhL6Adjnesljf4gP3HZr+Vus<@p+{zcKR#YTKYGLO-DBd3d2_ds}TGHrOiB8`}a zOg|LJ98Bo}5es@9;AO~INrxb)a^^I0VGy5CkQ%Fst35LD{M~o$s{iofl2kX8iaiSH zh!JrLX!3Z5uUIJ8<8<4QpTJ+hTX@Z)HzWdS@odPCj7>uZG58(X*Qn}}TK(e3mSW*j z@&5Hb&$cWztm3~6=M`%F^jC{(OrCtDkO&C1-FTriVZfULZ|B9{Xn8@vUyr4COf|k9 z^NEkQO%^6LH@$no6CP8O@YZ;Ei_V|EvbJ5p-~LzjiNIT18+IG=R>?BQ(k*Y*q)8KfINU?i6UY4&kia#s!gc$5hHGr3}A7Y z+luX%_4<0v5y#v7OOWTrw?5Y;vHP8yn}AJuRkmI1bW@hzAzAUp_;*4Y75{8!>G##B z-?Z*E4l68RHp<^e5?6IauMzYA*)59vl~vNzkpFIB;`qogf@Z93bNyzI_wChfVavP5 z_kFtkfR5jm==n|7;wKWT-wySZl-IDil<5HQFWdIU9T8&7QFj-FeR}`e$iE3D@-yYK z#+McRT=e-J;{3F_>;g+~gEYcVy$gh5LEsJiJYPZ~9Aq3Sb_a~iB0uJOBSP`Ni{40u^CxJO9QNfb7b5)z*M=#E?T0ygJW-<#I7X)_F`p5ObYfRqfhDa_{1^n7^W2TkOR|hf1;Tp0~bP70q^)+lvQhlz2I-J zxBt_E*+p7`Ya{=Pk6{`cMqIrt20r>^2MkAo0q8OT!aLT=QHDk0r6S(+IjEZzCG1Jz zD3X2?fvpXZu88#ybOJz=v8f)2FMXA*V&%wvdon?40RZ{+p4JTdUEQArC%vJrQ_6 zRdQf5`~Li<@BcLW;LqC^9G^UPON~BTGUDz-FxHO<=H5VzG_XQ_YD7jnP?VeBC+|@j zz=GK!`bQkFk>lMGvp0ox1Di!lg!hl~YztlCdS8pQ0@pgfijZ(WW2Vg;?XkBccvJPl zn>=5f2lHnR@Og7ffnTzXWMI|2!5jYV+mU`LG-{o0|K$|OA~T7JA>bE)J##=bOr-t! z&!1vT6iY#J)`$Z`Z#&vKOl|mobCa}oVrXLTs{!pdUHL`+8@~GCe*^!Pu8T{ZT#Nkp z$hG=^u0+$nZjCwP38tjoR4#}>``+)zP?yRW7O;MHyb^7u2}{veKqjm9u2?{FN}V1x zW$~IrLv~&2E6^H;TlZZad+^G%%|9=E>B_Xh`5i4B(BVY+mPa$EzMH|COJb3K4)!KM z;n-pnA{B8*W4!SIs1z4bZc#n~5IbTcPBX25yr2i9VEDR3i!&jOR#y4&XuCzIAVPeB zLhdjcQ0V6fk7x5>yiqwb<2F=;SlN&KT-Y|*#6)H;fRtmAAHJ;(`H4x6gkezU^Wy(D z{{ns{!@z+=0@|M1_tj~pg>L)pt27NOC+_l2NI;g+rYnap=01N*6|FEo8qw03Fy5!zovkt z@t>{*;h?!-ZIk8K7JxUjn>q6GUq?(yP=HPrz0@PQXL0%&@wCM^l3k2W$D%rM;jl8} zUXYNfo{aoPm9pd^OVKplBUEf#I83g-dFv&*e^{mIAxT7W-x+*2MFJ`)y}9|*7wx_O z;LIM_tW;aEZUa4r>{~^(l_Yv$HIf00;2Q}w=r6xf_KSU!GDHH!KxC~LDqRrOQjh>9 zHqI8v8N-Fph%>T6?*TSlsEZ#brYwsdb?_^(7 zkFWi8ed`ebKb^^cG%;;dGIL(4;;Z>h=H)kx2g}~R*kN{F{m(9Tp~;tQ8B?zBa`obh z-@Zy(yB)G16r++1`8oa%PKvM$s6y?iK<<_ z7xm77Wa5n|@7GTriqtZE+IP^5$oM+u$TW&LEuRkB=lylONu-nEwn4H)T=to^SNVY; z_{4}9g}DA(>tuPCdMdg_?_{XN)iDyi&!T)|^U>V;<5bSvRMm&_o6Wy6WzLmJ$g04F zXoiV4X7tgM~hBPt_iNr0LTOienBK4o$AS0PQW5L1|0eLUIgr8u!PA49W|1vjy0`;!B49 zsa&Y@lbX31!@jTOSLB7^fPc#0aVhHz1UVu*eTl~DVo#(>cx#jOq_Eeu4j@ zH+YWOxRgKZpa{Tk|L3=}f1Fap;}(~53Qu*Ne54!5xER8b2Lo5xv_J9Xg}?P`46y5c z&W}JsTNZgj%p&4{abw{Yftehc-S}XPu2t9k9L*RQO#uLAI3E>(&`(^!@pyI^)4)4$ z(9G5mQSDGt;LOI!M7?MR<)UO_NF+EO&l(x3ozVHVnD9{hM8Lkuzoejfvf}Hh(o^!P zt;%n;<5Is7sY;{rYK+gT(Zwpgsgj*jWhdu1Kl<})U;Mmq^)JhmWiynocTAVlv*uSC zpcI!tZn#OL1fcsPT=%Lj{`y-L3|@iOJygVKx&~H$R$ab}X~ux$LIN z^7mcnwQ+oTS8xIxk_(PQYzwd;umsd*CyTYUY+o`1V2A*2kKx|{A%*^B!lRUa6EoAt zH;f4Lvy3-kV(uHuLic^8#$Fl}Pp87}B(@pGMTZ17O|uoxC-_o@1Sy zJ_yn_Utt)3nD!U8aTth2nBkvdhhgj*scsRKrh#)XW{#IfNJes?mv=^!+aDd3?}#sJ zM%ZH!BbpLjjm93DOuQIfhqz6Mmd~KBF_!L8-GjjqFKU=9t@vlmcH-h!aX5$}Q2&Z) z=#t-i+0XNZ6kr<_r>RVci#vivRwaXiik7))tvBhSt-o!AcD-X!3G;fe7oDhoS#56J z;0rxEeLk_mywM7$Dxoh89}wFtTZYmFZmXj`Ll*~SO>Z2>e!PM`7OtKlzeV!^%sA*dqds|;lVJc_1iKF zW`{yF%FDP2wG5o7(WIpzF&JpaZmjh9<$LE{>>i^FZ5H84gZWl=Lj9rwt8S6j4I{#Y z6j3She_3ZHun*o@fl4>EMC;)>tRxX&5vYCXZ9<)LkBI}?FG195-RVgp8vob-^9$vF z>)`+8kJD#=SuTTX{pn)=0L(!9Z*2gHlfxd6$4nB8ft=^)I=ok0+SmA+Bn9|w4?Ese-PJ2e%z zJXABybdj&(cyhOdFU%Natm!Mxo#kH%j-edD!(_y|*@c;><~07MTeV|lga2!m`olBC zLKSMTq;DvhPA{QuE+vpXEfzUxrE0q0xXcdbk!qg&&e6qYB&Oq7pIi&lZ?7f(}hw zcN^mI#O1#yz7YX&{#!x*-{%xaT;!V=Z<6i98Nt&;{^cZ$Umq%Z34ywo;avfIq*2uc zPOb*Te=H$K1ej68J`Mgtn5WV&{=VnbFN+RbnY{P%h@BUE375%HOlK-?zu4I*$@)~O ze+$4jJ-L6hEZy|KRC>YlspSWwF%(jOc)&UEuZ;>70{PMigj1urihe~iJJ>oxsn4Df zbq8`Bn=H`zi~{i2jpX9?2*WQ$7ikn}ewTH9cVR?a?U{()bc#fYSUE!C{K~vYXSPUY z%uH3jE3anjROPRKT@|-voBR&SzQv`^6@s?KEQlV2 znmE8VLtxC2rsBs@W#Sl;vdrS)#C`Vbim!hAl4v;DOgF1xI%mq6$^F;PsQh_n^IMhZ zfpg^Fyw|I13U8~ge7XRU|B{QEUpDKpF$ayI&&}q;)j^#P8{+(L2QGoM05hG>G<4k+ zSbf|58DlnAe0YDCCb?xt<@c60rc$mVOE%e(T@IG=6Vb?64-3c($n@A23;}@}z9unb zM@2CizbXi}*b4kxL@1U8GfjBb=ox>+bE@ei1%i7raA!HKMkDc+;ox z1Zt(NnG8mM_wUlK*`#s#RFL(`O}Gf6?!S zHXK!D#Ki5@GNPz)A)p0#lQ^&!|BYSUH)du$zPw!jqqRGy>KQPVDg#2)Dg4(=X37&2 zGnw>d6;n2dk}0bMfliKX2NB~kkf3%)N}zeHo}w-VQ5UShtB?H~?r;?LG(!sD@iYbt z|93~i%a*CJgV@t5XwUS^qZ_A6_sy&I(WSvVFZG*{=lM%d$gA;0e#2+-8a|cZZ1u%9 z{}U?xkw{@ulJqeA`~$&(b|4=VRgZzaHW4^65b(xE5EZ)DUC?z}8qR?ey%`uSVBvPF zB5{}!)gOByqCG;F9V6Vv0@XYEp(}Kaq>OZsBiFn)y3VlN#IW;;KDl9;RQE!An4Y?k zA3;p+j*7*xDKvlmWO3^o#;GRMpjbL3^WHDZDkXEoJo&tF!Dq~eAjBJ?U>EA8Dp2^Q zLW@f%PXz7gJyhWHfGu%_f--k0E?!D5oZ~ozD{}#OhBXb`h}RJZmYq0=4z)>DYnfZA z)yZ--ch?A& zH7^9#WGzChiS1CSzV5k9vO^nlLl!OiC7!Px3&Ou05o#7@8XA@G*yt8nBerg2e%7?L zRfk->y;ok{ZmCMGlNqg|&VmztO|#t}`H2v+B;vFv#6JM%qGST7K(x?r=l=!2_oEW} z)ajj(DxMT6+fS}JztGPK%hORvoB{`CiW;^lb~=AVv@#>`*NdPIv^JQBeE#X1kw@Sz zKpu-5-U7FSBO^jr6Cbc28wtX)bBT?Lk^Y!?@K9pj*2I{@iGD{DOSUG~txL?>lXzx( z;{8v>&=Ma!mw0l2SQo%=NgTPT6;(tWolJN;qC{lIyG35*xmPC24>V#@FO?&KwryU` zhN()`lZkl2Yxt+_0iN<_0vv>Y{%`GMaat7q0f6D4vJe>ih$|n>(w6oY|2&`0ClTB? zJC3spqS+uv^JBSa|EN^Y(Pz7KI90Lxp$Y@HmuYn*lRj*@y{v);VXa1s$XGsg^eakq z@`Xd4?d84HnS_7rsPfvjjlU}^LA53G zx3#uS*=C*$8}UT=;N&!xO#$`>XR@H(Lc`E5CSwGFIp9+;D-<=Es*#%*aiKG#2LHAP z9=Lq;=pQCE$A3Wto}Qpo``=VQ(({GB7Mj%m>bHrPb|uzqPTXh3t22rIM-#9Am@_g} zTF2>knyPoS!>#KO^*-A0c!aBGZ-z$Td^y4l!2$TRqySsr2&i~?K>&jstoliOP|O5A zF`0KFIx#s?;C#;^5uNxv5+5??YBM7R+dg_!2aEzX6~ zd$0PDXgkxByc#{K>l4i3k)#v$2O|N2d~dzrWXV1!i#0l%=(#5`U~`B|Q*=VsDp~1h zl$8!K$|Hg;os}oWp7z`q8qJNk242nWJS3Lo1sg|x1Rr61GW+YF9##B@ABx6^&%F54 zGgXo$@f?6R=1cS2R|Pu8e=Ha1Q0u(9l%e%jlq8Z~0#`gW!A#DY%_yXB9Oh43vMJ_h zkP%1|$Htl*6uu*ColD%QI?5Ta43Sj(~ z+9V72Lx+#R2fu0yy$+BrR< z6F!a1nOD9eH=}-TM!oY{wQ@5?o~t$gM6<`&cj|kf^33JEIvgqA=bOg;KJDCb?$`!D z7S{!aETy%GZ(yVfO~ggo@kWN5`ZDQWjU%!E0|U2)AxrW#K4M}7p>wpODKzh#=uKN{ z^HjNdsS*?*0E?mBe|dD($l(R@IQ|Lw)P5ZQiDjWlUi%Jtb+HH`I6Q}M3;*&DsZ(SI zp9ggjY*dP}74QLjZX?s+2&qxgvHyjZZO)YMbTFsM@eBlJ($XmOw>}h^;k^dF{cW*Y zKbEZgNoUO8n%dURrul`2gn$f$86B{c9uZ&*TCQl;;!q|Hzy#p@2v5Va#Tq3`dj<+0 z!}mNq4&J(`tiTlOBN!$6Q$0vwhSSamypu)~&8@}p>#1+znxL&QUH8`LGx>Np0P2r$+n*t(1lD2P4iNQpMl z;4F*7a(Q@<3iDn>3(zoiqE%Ce=eKT^ssf(?(*FB%rZhvO`A2Rr-;0jtiO`pRia`o7WrW!r43(uf&cMJTnu3|MR|Ep0CjMP*#s^;Q^S}tBcX^ z32m!MedSa1-jVG^3L@XW>HG~^ZW#aU_;+{JUv=hIBZ`puMx;pTPmrK9r$tf#mb!+* zd?q5vWC0HC+nEq;WPu$AQ5{NSFN=cePe-!w-d~~t&++zQgkgA#dwgOPgt<1ARWL-rnl9=8ml}d5%SS z)B-ZrsS0sel&b3Se$Rf|dTXECR(E9R={mKqi`CyYczFeyAO6MS3~@p}Wrgv=ysz_T z2gA*QGSK5+qIR&<e!cDfu=67ZR>4MfBLE`+Hny*z#QY z2IsPCU&wrKLH+p)t2aNAfnx~QPg)v6AE*WJ)3koYqaJF?5{Nc$b`npvUI+|Wf_vdZ>(7g4gK$d zjVK9VGF2qeIRt_5@?7vVzP!EPyO@4XI(<^$K zLHxp}o#%em>9zH(OlMnt{<`!1(`YQX^LoUSX-Fy*nDqs9s;7Ky8L3U()FjeZIu36E zzkZR5CJvOU(|o1P^sI|G;myBX;}sDpf?Lu7)ng-h@e@L{AQBT2^jsu3xP8o6NEW%P z8>{8$E}j84`bO-FMR0eY#K%v(#gZuM;+nnDn^U2@~gcG^5ZOtD2Nf(#aq!+e1qf4zRvPv`@Q; zhG}OK-5~O;eKv}kTC+DvW>9OiH^9_PW>-%pY@{IG(qH3)wNm8}X38I~#PFF6!B6Ce z8;Dm>ym-_jm+tL&p+>t?icNZkZB zVkAj$vA}=!)C|ZM1qJ?7If6eSE{YMYZxxOlD^v4qiH5mlBBPT{9woDpKHoQ`oNZ&4>VtJk(nZWQuEhdj76xKvu(^ApS- z+roo2Ia9nKjQ{aI{LhZ?h5%E-(A6_SBfgN{UOo#T;l#8689WV3_X${RSgN?UBf|3|TUIL)0nL7QWE}60{?#B=0-h0r+R2<)`5W-EgZW7N#E5()4s1c2 z{MMjCe@b|el!8BinfyZ;xxf!;_nz*%5Yv{y$QlAZS?Y?=(8t zuthSsx(r$D(&Alq;NR1dN@?))ypnw?r@=hh!!B^%$qUJqQTh4V*LmW4P4{U`4->+k zXM-1@c{Me~()MUbf%~s)i;{s7qZTwgHu6GrS%H_>Qq!&guh(=Fe2$BD0GK|1GRh(V z-MgY~YD8DSo>5>9ND5i-FG57`b&GU61`Y!R3YpjA^gkhD5k8NU;jl9qU5_NjtV?_| zGST;&pnPBq>oYM&AMwbHuI3Y5a7od(UVUl zyYx?vGBx_+ZR4pX2Nrsl@7vu@lKzS1zC=WJq^!~GsKSw;W=ezJ;XF*l{wM& zwde0XGpN;$?lrz@B*Y=C7vCj>JI-H?PQwWb0V)C@`U_xSOqc0Cr`0{52@K6srC^?x zpcANzno;{;n3^|k90yyaN~^m_CDuv>ssr${-D0+n2m!y(_-lhyb&3?s5D9~lcGwP# z$k0-w3ngo4`7eX2_u_QBU=&G&B2UFV(Kw!*kop(cdvc*Fcq6Ke7pGn%(_45`PN<8B zjSu*|WX)5>mF~BsAhgr@SfWK6LpbO}Dg2O7gf-W`Zc=4?{odc-rAPu6=S2`6;%sO` z=oP%7UD^QGn^1Uu`X6%(@0-lB|I?pW*e@+GcJpl>j1AS-VhgyX&h>a6zQ?xksCVoy z^Phts`TsC-HX#sic_JdEQ0>Z(M__(7>Zyk!Z4b1~qOEDfh)|ta7N8wp0)DoDN{9dX z5uR5^Or8j|3FafCX)>!@s#KF?wm`>&d37Jjt2xntODd;-UX{Li)taPAjkwt9j@_A% zLnC=jnMei`C4PK3F|+{gC*&ekNr%!)@nlJgS5rvdFlk85I{y`o)VZtx0^v{u9cV$?{Nf00N3B@3R%E8Kptgb|;%soUx$GpG@qr(Q(! z>~xL2DUGJd;+PD@ST|Lc+K*jeLtrpZ?Xv^(l0b;M@Q~V2(*YF?W879DN=?KxIKdk!7w^*%r#T`Y ztk;%|w!3nwpUlxj@}f~k29y+#1^8z-Rg#n-O%PDWYWu4+I$x0)B9Cy6?Rb4&2_q%W z!wZgBPzX;+C-eNQgVY-0AZE)71gH2!HoZYSu`(Ms#6Yb_qS-iB+SVFC|2h6wMOb|} z;vSzw(RkYa-Y6o(954Z-fPSW(sOv!y?3+X#M|aivD|el$_Y)HIU}O~Dhyt50MqCJk z>YvJa_G0(9u1tINrw7_jMtb};N1~USIaCNt)UO*tnnOlLEF4)e&seS;B5sTW|y**@e){2Lo1{{utsLRA1X8#k;2J z(?a!fOV-HEte%^3HJYsxPnSSwgLAj1rqvBh`eO@l+7R5cIxW{=>EIq)sw4IqAG*X$ zJSrQ+)%Czc59uPd^s3FhXjHTI^qs`Q5!)(LgKhGv)d}=ISVNj*OvDmvNBfKdWuhhP zCNulww?q}HN3=2Dw$((klD?I*DWn)902Sj-v8i)9MaaPiUiNxYL zo`+T;o4(Q>k`tWo2}M^#tF$m<>b>BNieORot8x~V)RV*#R| z{$&^r`9c1zu)vWw`ph~=|5&lGCEx17r9pn_Lm70Z+6G8?Nao1{_t{(aKgU1)|8|6J z7I|hA$q9~R(z@9ctJpUkNI{A777Y(X&V+`1#>!^r;jdcoJ*TRm9w z-L*DM)L4DvL`fzKxdf za}gdkl-i+8YDa2>+eIRsgcQ(!OjgHbK#Yc!6nlYKe?)IB+bJB`ia$jgBV*6qwyF>ie+qt&tE zt2O!)NGVA+xK;a`Gmrz$o}Rzhq7E6b}- z$;-HqgQ}bqZEqH#(Ko?Qav^zD3MDVzIu4S}jOCf1WgQtv5M=XUq?WkM-+v|>X~D7Meo=FczkB$`9ybv(MJ>gwr33ezQ&!oEhU`9J`0U4flvx4 z^m5@zw>Oe9#JeHX2HXwA#KnJDYOgFBCOg+VB8TE~f_3mO|Ac5re3A+^_VW^;h36mc z65dqLvf#4BsVQnrPuU>?{-uL-G?>L5=aZ_Z#3(LT00V{_8aWP#5G_rD@K_j_u(8_F zlk3d&FtvGLvTMDwetj#NEeL`T->DokK`M4z+T>_} zoL&$%@jOtJ)|0q2ut5&jICv-r!sF>FX2MfV`?40b#^~2iW}}h)BG@;M;#!Ch`n2FRZ z_9rb3__yzAVM*gKVVVM^M1E*guOqddU5LE^8l%yPjF!iXKeFfctw-N^H~%GL$J8}^ ziqF(fma1{Cc)6!0S-`Zyn|EoM5HwrY+GI&v&frC%8IP3_VXIg%^~e`1?n~Vjuf!Vb zeCZa_<9WMMuZ@DKiY7*+JLE5s3-K#)p~v#aj@Vd|@;3`i18PRENim|k>?~iv8$JJF z{r?L7<=f9WleiabeoV~Wm3VVYV&>k&eLp06A5YBKl6Zgx{3g+HUuZ_{)_z|`v(qKo zCaY4~9-9s~v7HnU2L#6a3)6&wpEywUrT|FrAo#LPIQ24HXk8*eeEc_*gZp_Q%*Q9Y zpfr_xz91={U^t*fcL_i0Q{heU_7kdDCpt3v(=bp@T@Vwh zLy0*PuBi@3IIY0hac@S4gW0_gRGhZ8dEYY)>*eM&IA5;D;mXxclnxO*s|Ft_U;Oq} z!5kc_Ncjr{QT|o7*R6H1T>VoSlsVPv0pLxWcrZ?43^VX^cXo%41wtEMwDN&4Mkc34 zx8k>rQzg46GwBwpo+021&^C1=Z8JVnJKUv4$&7jzvYMPI5Bzbq1GNwN5`KKOV>2S$ z@Mtzcqpsh4BJdfv6C3nZnFUe+Ap%nx5WEHXSyGP;*mB*0$_b4pT+r`~BFj#`BL@x3uij6GJQQs-1J^dnJ0V z5H2%!%re&SU%YErExq*z6GxsLVUU-eBt+~Q-Hz&rTv3eFqnMR^Btyf@fjK6Ms?Exu zFzsOXrPH#+@klW{J7QHxQ6mm|*&sEu?%?p9RsTc$uREF8yeE{bUo$=N{ELA-A`+Z9 zKoSkZB9JaSZtBx?W+j@rqT@fvxO-QXPmjNdvoU9$+$Yywim*oMO zFHbrU9>kBo1NPjXnD}x08>h;V7uJC2l1j!lUeelDHnOwKQy3qN`zToD7;#q>7B;=tev!wiR8P=oewKU(_sBeiOO(^9Vm zLi^Dj1_**FKT%5mhVe~C;cRxpBiW3OU%5VlLB7VX2*Sn9bdX@OICQ>iGC*37vh^Yy zPa3T0Nr{>{0yT|Nr5hTzjhN5ih-&hrIKP5viz7oYA@Z}@8t(a~LOjXK%tx@N_634S z1n~RHBd&L%n8%0*st7`yA)|4KxfX*N6UgNTsgsigTI^_*-h+-zDE01%YlD-Pco_$IQCH% zlV#l&=RVuzXgQg0{2C@{>_?%?WR^;@V!Y^oq)4AWxTEQf@voxGCnriR*;`%Bu9w%e ze{y**pL3S=S+lyl*@fm9nrV1)P*{#l{6wgnB1Kt|C^2~*(q)JGAHBpBFfRMVNi%A!+KA zfEV`_gAywv`*YsRfmLxHV$S^$x1^xxG=ZSKy+SwXZfZ&=`U?Eu$KmyyF+1Xr5+54R z28S@O_c?&NThp-u=#V!B6$;Zv4F`p1hkK9pVObY}fy z#e8BKE%z6D^2K7%s6X)SxlnIKy9E1xOGBQAkRp3qq6%0RY0~79G!3AGA4(V-n8-rhC1SeJaJ9vaLGN z*TKgcT@U|;fZyF+%b;+FKFcZ;Slov_vMKi$>&!x*Dk__yj6zTvVu>14po!68!Qmg+ z=sl9i#5?XuS{%)2cd{HV1m`>>V@2!bH zj~I#K1!&cd`!YrQJ;~I?S2;GcV-y5a1kBy1zL!Z~#WWQfi39Y~v~Z}%06-#XzySR8 zKWy00#nWvA`KKgfmzjtGfOGti=V-@iAWf?`WO)baXUVm^MjLeG`s>rV&8jpFd~qf=oyJXuV}R8ok-`mj=(=J8d4c& zAUHRZs;B%VKT!B_=0i+`c*IOYy%SmBP0)C+U>_H5wQ32KP8jtg2}PLUM{}`*$e0

qX^%!hCsi7;wv~d??_b~)lAXBUf{v1bp z%=B?Eq7yx7(XYOlMf>3!By{8O5JMo^m>ZkU8Pp35+@cpMZagyo%VgGuRJm{S+wHj6 zP5l=2xVBvAw`kqC`(`}RxZT=oksm*jT9<{8AAdd7HW&gi7W$TEa8t-P2Z#0mIRP1M z8@nDbNez0u4fp1(UOuo_vMCOOA0qiQxe%^)!|^O3$1WJnr1@o@do}WI)+E!Qoq7Gp zzyBh}$e|MJcJBYQgr36ZX=bQ{YPyE2b$-ajD_E7>X>wq3+Km1Fj$so@CYTd zLoNVbUl1#we0C?WQ)D4@PUGsmr~@YZ+tP0bC{!St6gDf&v_W&iKrvBNQbgu@{u#2D}-{3iO1PNP5B zR!!Ytp}JI^*%HLIY5#HYS}}^SoNGP z#Ww_R)XwvBgjr98c1gFkb%M6F1N<)HG;vfhOz-Fgu~3Mj3g}oD^dwX(-<-I)6oL&} z7@9MQlFO15M#Mw1J{prsIou`afAZ^f#E3jIPqX6>iFUb(1yS(1M>IZexI_rr0OG={ zW94OwCqw=x<&WyaJiy0kZ|IOwU|(yW%kcVCq9@co_B9di>X9_X#^E7Etd(f6``4Cj zcB({&b5+is35ytNd4UK_Tl|?I&`~&#-r<4bJlKxjAq#p+TCzAElg(ID(dNrjaXOUl zA}{O(Vqg10PPKy}X)2_HK096}iScxyA;3e8nteIwsUxq_gdAr#H5{NA4heEof8;3M zi9Zegg3yEC)b$paEkTBPu{&Hhj&cAbls>RBd)kTq*8DZQyx`B%`$XXDuYVgm_Hx69 zc_m7u3W>n=_)pp>Z0T5O(W99(q&N%`j&1<}&W{~YbOJ9RYM!WH1 zcfQjz)l_>Da8pegI3^M`LW;yausi<}0;Nn4B!MH$M?4(;V=oMdaGB3tKJwBlCA~Eq za${p{hH22rRGeo3KOpSAztWh~om-zM)#^|NSC00ENtlNL&qMjsv~)O?=pdbp#y}=o zg}?Dk!Ici-=Et~oK>`jiK#MRKvEpJAAIKpE#DP76UizG#cO5dQM?BA-Xniqi%Iydd z#ZL4*ykq@}?LB^qbiC3+tTi4X=~L_r0aKaOaR;Ez~nj}Yw) zG5I`_0qurWQk{XtNqN_fhs-zM*0^?T%YpXP_CqX=Hx^n#TK-9yK>)zsRPpe8)Q9BEGf<2l? zV+i(|c_Apo*zxzp(Cq6D+|QsGWx^ZMm~88F`|qMEu@s1+%`g+H+lI-|t~STH9&f#T zTZaqP#LeE@b^mi;wz>PuFkR01ASdVn!@vfIumP4dM(p_lGtg>4o0HuLwviSbiLf{a zsiS0E0Y@TqXeW&wiv}%3E(n)$tnNY*4|NTi_Tvdb^K(O-pasYmg|8V;whR2qH9eST z(1TD|*>ta_`<)J^s8I8klz$)^32t)I$gcIW8}$Y+%0 zo@se#u|p$)rN-x(>J*sgr~>)vKTgJQ5|+2c`?R-N=jcjY>jRV5akQ5ILfW${w{?GP zP3@*vmsG1=J8#gSOCz_=_$2iyL*tx+HPG0O_?iU|#z!o+``qHnKm}u5b&eZvl-=}I zYtuHG_u`n&@yWONX=q`=f}fi-$&U?zLicH?7rEnvs&~EA`>h7!mSy8$m?V>p2|znf z3VtAgvZXoW&j|azKcF!=>qe21sUXtFvXf%p>!9wo2aC_(JK?M_PUV z>Rlr@m%DvmCf-8ddQNyA5eMwz#KFm2Ay2{( zV0}`8r4o@TN`M{lFWEA#pb>x{eWH|T2~3+kvUmsIQ*#kRHidqsF<5N|g^G4H;zK$n ztVqlVOhVgHfJg+hhsZ{-BQb_>2SotbqO45ZDp?Z?`WfNsWK|zKkRD zMyYAG@p2eR)a)qbmfto?JQh@>Q87}Z&!8^f7{eElfE;X-A*P7L_UWa#YLFoqTamcZ ziRsmlg@AC{w3s+QRdw?;bN?+k@2lUP+ex@g%!ig{2!w;UKgb@?QW|K#HD!1K^uL*^Y^yTS zZE|npbif9L!xiwm5qYOtgD1Nws8(o%Ui!1;Dd`qLpmZf!GiW&Z;)pwvjapu)FyTPE zC5u{2Sy5u<>lrjKzTvmz2&z3KZ3&qk-e3VG%tmk@+!42-tC?NzLKbis;s#nA3TO}E zuP1^F0B=NwyzsI;3`baV#f?c>tr-&<%45SkGemsYEP+ST$Kv2=?nRIZrl+DY9{nbe zpMg=%VXY|s$rs=V*G^{A{IRPWa~|Ml2yAvj{m;{t=e(3XWMkHm2`!g>J-W$-(m&*G z+;;g(d`8g5K#YJhJn&>S4mv9Az~wyt$5A}rzVs*m6^M|Tpz-ZHXtP5QY<8~wi&ykys6q#gBGnKj*L*UqIeKolYiSAkCuD z)riE$;{(kT8bYf5gve+XOOg=~mI6D1WY6YOMkFo97q_H=X%SAX3A4o6=E9iCWdLfD8q18loTZAiV3Kd%mi|qfDhWk7TAf)9%4QsLiK*A z@%58!Cmii;qBja5wnh~&tO{5eT@}ELX(vj9X)pxN!Qo-X(2Py#E0w1o;QX+{mH*RM zHiK0k&6!Zo3J75)VB0UG`PKTQUF)so7e1azIn$i9BK;2r`cZd7yPx0^My0Ve{m%QN z;wFDm_RgcV+NG*fM_8iBj|c$fN!3e!pl#R!+KCqo#@wjGuaD(NKpn)wIWYuOm;@E@ zgC7p25DgI0;q}gD3b7(ihRj$N(O0wQ1kjjr0XpFe-2fLr{bN2l17_qvQF~u{bUBy+%K;6J18pA)O^V9uqhyKTc_`C%V+E>BMR_I`n zUy=W`M^NMm|H(m%45p!Yy&cQWS~)Ae3qD_|Qi@8)zHa@#>B`S~&}tX4PZ8ga(cxuG zc)YRrl|`VGe3Z^n`O7xd_Ezn%s`}8?Spt&4!x=G>7<2N1KgR)3Weiy_LszH0nZv)Y zGdJ%MQ8fV{%tyr7U|;M&d0;UI@m{et!;9^Xm10D2X0!ofVU>$&Fhbab62@U%5N)7= zeQk5B1b0k73P*^bB2?zOx;_}F{O)^)(w#prVyTQtVQ8$*P7;HQ&$7JarP z4tEaVBo{m##>-vYm;6%Kam=~h58*3?&-ul05ImUormP|9;9q+-V2;x>G^4B=akHt5 z12uA*CdGWT7<0*@VPC8yE8~u2YL=;LC&LUoG5?REc|$8g@V`P7BY6!_Zi7D@B& zF`v2izyB+agz9ZY)#@pD5c#omZ~Qv3KU=C)ipO#5B9N}JFQoy7B}b*NFTq|6W#_kBN2`x#vC)g!fOf<^M6Gf@JS9b+_pTH?P2&7z|RYI5g`{A0sdj0Q4r5$ z5nPt?yn9PIXh(HWS&~Jk@%tDTEC>c9)AIX7Jnl@jetca6@J4UI9#D}tI}DaMA$YT5 zZu;;i75jZxuJ;cWIv*(6`B3Sxn<`(J((A{EI;ntq$M-qbCIfpeEx{)>u`^5O+lS$T z$WJ$8>@PUyRP*AW)$O>TcdKDckFm^)v8}H{2RQfCbC`ntHwV1x_(6H$Mn6#^hEXy5V)o_h=E^rtDWrTo1{VB z_U6FhEgpYmN<~Uc81P`%U@RDSjv>9xH4ZVr55thb>U)DyrQf)*!bBa9l^>Jpjqt!c zn#x_3DI^b832t7P5QH(8-A{D|8(t@b3$`1zfgi93SJx4)$4RJb1PL3t^Sko!Pn3Y4 zG_fEC+C-cL^hlN??1C_?8*SSEGHLaA!c&9`kD}yhW6GR(lC^NnJ;l16tZG(*U)kiJ zYeR&sPhP8!7I!|}C8T7GUmpAds58*ej%m|uZifkP93F_rXLUP=Yi8tT z)%Y%~{qf*aGCC~zQU0}iO156p=)I0Dca>^%Jm^xtrTP8#yWRm6C^Xdy#&QcOZ8}_> zL~L;RBgKd8t1&e9cG+%xRe>O+Met1&)EJpjFy8UJcWU!V#ZT}J%9c+mdK04^g%F|< z`H7uSauwDpX2P0x62?y9)hzS>o0>S!USglKj(07lp@@B!IVYLMeaX zC!56I)84yXpOjt@$;DZwUc6OkhHiLj$&oE-$F$PP*$Bm&}H=6Bz=Q(4tS&&o{-m(Waj7UKk4V1vg7N7D;>32k*S}cj@o{rD(tQ zv9Dc_I^CG*ol6t?6#QWt`2}}|4ZCzb5s>B~NCN-=x4irClB&wq0RFc~H%*cxp~+F` zh9L-uO;8lcq98KDkP(DI9f^vFf&(amqa!$sFiJ)kWCTV82?ELxBzGdG_kOo8-q&`x zU9>n$)?@Wz-MUqEtLof+_WAa=zr7F8%f|R{_OCEXKnKJ46rdNT{p$;@8#Krc?pnE1 z0s-o7l^{WxLte|fnyWJEkNM-sKRm*by365rlWOElV&OGm7oz9qh3WERtI6A72%6bDdnjh{q!aM}PrAi+4%eG~Jv3IzE9#?I>`!`X7YaLdboDL?z`#|LG0VVSs4 z{#Je@6ryOs$1Q_oAPP**)XgAs0q`)VEG3LKNb7$X?_;78t5W`Ew97kBq7@7D=NOj2JJdT}Xp6NHn}GTmO=*v61bfC?PKvEBdG zJ2K0D4pzqt?#S}P`z2DFIVY=phYcxhzQ})rRMzwS(U}jH9o~}lvpsyf@Ik~2Nz!41E$Ff#-sPcAywa2i9G;n23uR|IxY5i5 zBZM9dTJ>I>G4tr$UhDo;Gh=H?i?29;rTr?}6o$Y;{>KZ|`e%B>qZPVrPhqQ=JzrbF zreiRBN8eysL2+~1VocmPvJ`>u*_W55yt=h*dS*3F8$pe=W2orsPZzcU$y^6yV(QG^ zFea%@+S-5py*8h{uhp1etl!+?XG3ZgPPxfTYYd(jH|Fc7|0CUTbSw(=}ZSvyTWXAZrg7>%t}&wlf>wHLoTmMbj?E$ghZ;?HSpiSy_EaM8T0W7AOuQN&n^mwTV-*5=#Jbq?1+0crdatOf54)D=g9xcW!EYHe;^fAZMw%Nz2{l2a&p z1|O2!Tq}Qz9TK`qX-QyN4wyHb56{@epy7GVT7%{QzL@eTQa8^^{+cEq{4v1iUIukz zlMpz}b?KDA{w)o@`S6WZG)hGx!Tg9&Q%P!4uG55qv$R zJx>I)%n~5#N6`p=0~>Cgd~w?Fh+DXEm-^J#?m-_-@%J8Q4WIWAQ5in+=@c8^IpQUzCnO zVEwSNt2Pbkl--a~i5KkQyZgf4$t%}2*xXq?Ecz~N`9dQhA}|Zo{^)wq`k$%hk)?!b zAxOo%T2#pqFk`8o5XLiX!KS6bv;J>?C~3p$-)A1*1+GtBRbODs+O0>R4wQmBwJL#U z76Q|X29E?t&~1J3EK0{-vA9#Phr^fmmj&SV)!l^SW62X55H|)Q#zj*R!IsxQX+q+PTf3mc^3Phmzh$#B=B>8R`VrS zmq#{mPag<-bBA?}8OHFb>~5*oHvFydFU6#B^2jv(`b+_H0W!B+J<2 zxNEfuRVGfW(eLl+CmOXpSssu8fn?-Ec7K3C81#N$*;T6?9Z+=xuJ+E5ny(KZ_+r=TbIbAnkPIxul0}*fo~MO~ z*e&Zd5k$C1ev5@_skv{Z%>S^_)F1jkbf~Nei0bqmBwGOunBjlLDy3Su#d zP_;13$nA}=loDP>hA0IJA|=W{N*W3gt1GF<`F8Ws0rhaRrT{%#kprI9zT)k~`mI}+ z-+8&n*Cc*&c=b0EvHb8g)Vb%bY-j&NgRPF@kU!_&JUe60jRX0A<~@2W?7cK^N@lC1 z5=ZsI=$mPGv}nRVFEdUumf@+x=Kg`=&~-53He-c$M+cl z_C}d{w#D%>y}m31iE;HfAM?>%czS(+e9TI#5`&kmrmGQ0hr@->CwKpI?sU^rH6?W} z^;e{jw^sCo%#0uEkY2la`b7TCVdLLYDRoU#?Z{Rrr_c(WKpkOd|XD7i`kB zp*_qaC{}vmuEtu}pv>tly*xBvaFW}A0A@90ul@Muk8 zu`rA*Gc(5IaNTVbiEj%&f{}+|0+26EhDJj0gKS61TAM5!!UviefdeyR|0a=j!7)xo zYT*4D6>c2ZW%m&Jx=5N{V3bfgC@kq9$>gtMP$e0}@I;(l7cV|_B-Sy1PNdG;pe+aVwLKe^66 zu2@W}ReMU?O=TbaO43RzOVp)??f4=bPThUA`>!b%VshRXx|R%r)p=S6pgYEL{)df0 zYb*+)UKA|ZDiD@V%G(0IwYn|k(u9{?Gt(YCQMbXzgQ~tU(&W+^72FECWKW*Zado|R z2g+DwAQ>LpDj>PW?74BDVwT~BEDHYT%*osMcKF;MBnE~-N8#XvTH^57c?>ODJ}i#N z8PJMuq`2`ZaGrU`k2aji`Db;wKmKJUK0Bc5`*&*pUT+`6c3Dm0?Y~V{gW`(53;fvM z^22Le*JSr-P~tF#q?{Uu;(p7JoSyF;Ti*5HV@)(JV5ySQ;5y zT7BvQ6?QZ>0tBjl1!1+k{THp%N!`$Cz zzz@799$JWznTd?8m)-aw zF4E_a>05$!7Fi3PTE0jRE^c4zA>^kJSYsk)Z)qt1`10gNyF{rL0vM^%*#I%8Qu~pMF&pufcFTQ}4i1e#mg`+)c{bkl4n!Y`& zjLR|`^ga{>+ixBm#NfgN**Dy#r;wbEi!-ev&-3chfW#kYsa@n1qLZkG=(uzTr_)l} zSKN?N=5#6Szh3WuRnBT0Z~p@1e`crNqe}qezr1i-LIc|-<;se8?x;T%d<1Jb;3% z3rO;HeJeNEoL2wq7Q?sCdiG5Ju;rKOW{3JvM`6;@7^t=rAQLl7mH|rw3T`T zxLzfE$}gjRTzvn7siiai`>Gs!;JufVGwa9OKZ0~aX42k^gYLN{;I`*4>JApZDVJuC z3ppQ(P3cSjM>jG5fn2Ay6{={}kAy{kiv2O+oz6Ay`F*br1NT&Ec0i&k*pg=6P;oI9 z)I&rN&-}ZuE3}wy}9rpBzPvL&x6S1{KHb*af$vv!B32N+57bdl*03SOSOz0wT@W= zlM**9k7Oz}a$KWGGinRgVJP!L{J zq~IH>$5fbHz0nbg38f#&b@zf{Qgw}9eSXxiE(ae@frZdGiOcDu!6|S+I*3e;#w6yT zMEqai%B6Vtc;)4#v;UftmR305EZ+V}BM2ne|At_Xj3=-D3LQvdMz7RQ-O4vXUZB=xJU_R<8q>2#zA{!++E6b@30(p<>KgdLWO6s;xPN(T7UVmlX zXH7PDdtmMe(Shukl(87OSI@Bn)&_}MOp6Tc-^T<&C|ZVY86pxC<7D=Bs?@5_40!}P zH)@KYDBh+X3x_m4Qg8UzQ}q-Q9qZdhW>01biP4);a*7C|Z%Y6?^pyjZM$QhVK)r93 zQUXP(PcHmpi;;&~)F_3475SC~vjDjxdldQhyLEDF)AZV94-~e4Lfpb9^Pf>|^vqFW z(>Ui}CbKSS9D!V({ol7WyKZ(~on|!Dzs&>2e`(Id#Esv*hzMRuU2lhPYDwBa>I44 z#!qV~{v}9O#4RDEFv=1j35EZJN$``N?eXSAf(VpRm6>BTf{^60cBqSgVD{LIXZOB6 z|I*t1-;r3Gp?b^EVfysKH{yexJNtk5zDz`P(`my7S6lE&!yZRkRQ=`VCrg4-F8sL# z&Rl$H@Gt+Ym@7O}by4&K^B;8Tlsj0)-yB ze9*Tuese*t%6s*|K~8!|wBVsw6@gE~FeIz@m}BGT%**LKdP|MhCe&WvuHQ4yZtqoA zE>$(Fg+Pl@ie+j9y=~EtCWYwunOUvq>jcysxID6W)}2+sL{KD~Q2v2qP18>Io%8wd z@5k=W{*D@X|Bc;+$KM>ZQv7f-cl-A1W5-?!Ex{B>FTeGzI?ta;D_dX?O7SqKe|ms| zic*P0-zSj@(^7nN_?FjGM^#EXp5N@FWBpeTAHMnNr`J?xck7m0w{AAUkAsgtzIyQB z?e0py+qiil)L7w93?cD=pt zlhJc`H(uR&pLcXhAdH z^XVnX(h{=CR!P~9*5z%2j7c%GfNx1W1WV{c^Vp2@=}D^^bxAF|KQj0N2YvcnDA6pH zG{)P%qR4#CKdhHeI(==$Z*U5Tc8M0~cJ2uFq%0Zb~s{{K7lOS-@L2bAzaK#d}x{jDNm>GXo1XIH+uUxxv?)=Rq2i6Q+U!B;D z{|Ejp1d3mf^XgM57U(vSljEl}m&vlz8B@0e5LXKXtO$B~kXs8S*nffB?V&ECPd<4; z^;66gm^$_H6ZJOkZk|9MJTcNNve*mbdSBb}k6V`tl0vjS*}a=bFS}a@Ct6kRRB=t= zL5R+1O;e)%YiSa1|BB)Z+5de9E{?c*>r9Ck|F6A(_og!pEI*@0jM`SlpY%N(f688h zmg7q&MV>$Uwkp<@a_j6T!6eCx+u`s@+;xscLh4tebBKii|L-K?-LV;Adoodg6qPm$ zRtGKC!4GkS1M|Whp=1j?_tHi#{GbW(k1v4yAF(1x#cE$hpQBId+x)_Uy|=t_7yXx09xyO;5gCc39v#5Yfe{&x;EJ>3H6X zV1y-$6A_#jxK#YZO=%hNoIhbhbWe*r(9$H{{xwA@Z2zhz&tLzdxNH8G&l}z=AI}R! zhOv@pS|~x9Sa#AB`?uel7oRM*Mg+u$=$$KXItP{2zLo;ZGoe zuAM$-OZQ@s0iMm3YbLMvYDx=*^fMu+r4{k@7}j#gdd0WjJLG2Y01Z0{!%q&^br@Q z47&EObqUGN6GmKu_vfn3FYsdvJQVEYHX8M_@5is%^0`u0LbD0 zoy72fF&KVqk3S5Lg}gjew`_(jDihH_1&Zi0k+a71HbMQ|PS0&|Y)p){uX0sfUA z`kx3VvKa@HY6hIoUH?l?&RpHJOa2ckeEen8wEk6=d{DpdU7<-`U;LZht7+j6D)pKF zw5)=~iXWVb6E8(0U)({5oZj*Hr>OWhh=R%Cio52ocb*JBuh;IW8wb8oD~jYf^SeYP zi~K63+3FExzZFTYh2_fMkldD;ai$l+_tuDOQCx7RFMZ}u9&63{G~YZ_kXW1sR}ZBrAv8Z*ylVt zng0NDwYt&6@q<&VR+hf3@uqn4=9xO#oK9T+t7~TUBK`la+(+Xte%GHBPU@;ODSOC{ zZ8I~w1W8OW?B>C@_kPMhKKYO7YM4EaMPAj`B=4?%DYb70`b4cy9#vx diff --git a/test/human/data/cube.obj b/test/human/data/cube.obj index 98e7aba6..47f3dbce 100644 --- a/test/human/data/cube.obj +++ b/test/human/data/cube.obj @@ -1,47 +1,46 @@ # Blender3D v249 OBJ File: untitled.blend # www.blender3d.org mtllib cube.mtl -v 1.000000 -1.000000 -1.000000 -v 1.000000 -1.000000 1.000000 -v -1.000000 -1.000000 1.000000 -v -1.000000 -1.000000 -1.000000 -v 1.000000 1.000000 -1.000000 -v 0.999999 1.000000 1.000001 -v -1.000000 1.000000 1.000000 -v -1.000000 1.000000 -1.000000 -vt 0.748573 0.750412 -vt 0.749279 0.501284 -vt 0.999110 0.501077 -vt 0.999455 0.750380 -vt 0.250471 0.500702 -vt 0.249682 0.749677 -vt 0.001085 0.750380 -vt 0.001517 0.499994 -vt 0.499422 0.500239 -vt 0.500149 0.750166 -vt 0.748355 0.998230 -vt 0.500193 0.998728 -vt 0.498993 0.250415 -vt 0.748953 0.250920 -vn 0.000000 0.000000 -1.000000 +v 1.0 -1.0 -1.0 +v 1.0 -1.0 1.0 +v -1.0 -1.0 1.0 +v -1.0 -1.0 -1.0 +v 1.0 1.0 -1.0 +v 1.0 1.0 1.0 +v -1.0 1.0 1.0 +v -1.0 1.0 -1.0 + +vt 0.0 0.0 +vt 1.0 0.0 +vt 1.0 1.0 +vt 0.0 1.0 + +vn 0.000000 0.000000 -1.000000 vn -1.000000 -0.000000 -0.000000 -vn -0.000000 -0.000000 1.000000 -vn -0.000001 0.000000 1.000000 -vn 1.000000 -0.000000 0.000000 -vn 1.000000 0.000000 0.000001 -vn 0.000000 1.000000 -0.000000 -vn -0.000000 -1.000000 0.000000 -usemtl cube.bmp +vn -0.000000 -0.000000 1.000000 +vn -0.000001 0.000000 1.000000 +vn 1.000000 -0.000000 0.000000 +vn 1.000000 0.000000 0.000001 +vn 0.000000 1.000000 -0.000000 +vn -0.000000 -1.000000 0.000000 +usemtl stone.png s off + f 5/1/1 1/2/1 4/3/1 f 5/1/1 4/3/1 8/4/1 -f 3/5/2 7/6/2 8/7/2 -f 3/5/2 8/7/2 4/8/2 -f 2/9/3 6/10/3 3/5/3 -f 6/10/4 7/6/4 3/5/4 -f 1/2/5 5/1/5 2/9/5 -f 5/1/6 6/10/6 2/9/6 -f 5/1/7 8/11/7 6/10/7 -f 8/11/7 7/12/7 6/10/7 -f 1/2/8 2/9/8 3/13/8 -f 1/2/8 3/13/8 4/14/8 \ No newline at end of file + +f 3/1/2 7/2/2 8/3/2 +f 3/1/2 8/3/2 4/4/2 + +f 2/1/3 6/2/3 3/3/3 +f 6/1/4 7/3/4 3/4/4 + +f 1/1/5 5/2/5 2/3/5 +f 5/1/6 6/3/6 2/4/6 + +f 5/1/7 8/2/7 6/3/7 +f 8/1/7 7/3/7 6/4/7 + +f 1/1/8 2/2/8 3/3/8 +f 1/1/8 3/3/8 4/4/8 + diff --git a/test/human/data/stone.png b/test/human/data/stone.png new file mode 100644 index 0000000000000000000000000000000000000000..94ee2e420ac753285740cafcf3d24e56e95bfff4 GIT binary patch literal 8664 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 literal 0 HcmV?d00001 diff --git a/test/human/data/stone2.png b/test/human/data/stone2.png new file mode 100644 index 0000000000000000000000000000000000000000..f8803666c72a15ba4df54eeb209a36a30ee7b7df GIT binary patch literal 7793 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 D0Y+2) literal 0 HcmV?d00001 diff --git a/test/human/file.mk b/test/human/file.mk index 92b91120..727a72e5 100644 --- a/test/human/file.mk +++ b/test/human/file.mk @@ -15,3 +15,4 @@ FILE_LIST:= appl/Debug.cpp \ LOCAL_COPY_FOLDERS := data/icon.*:theme/default \ data/cube.*: \ + data/stone*: \