Просмотр исходного кода

Merge pull request #98 from paulsapps/installer

Generate field_bg.xml from PC data
paulsapps 11 лет назад
Родитель
Сommit
fcc788623b

+ 4 - 3
QGearsMain/CMakeLists.txt

@@ -148,6 +148,7 @@ include/data/worldmap/MapFile.h
   include/data/QGearsSerializer.h
   include/data/QGearsTexCodec.h
   include/data/QGearsTexFile.h
+  include/data/QGearsTriggersFile.h
 )
 
 set(SOURCE_FILES_DATA
@@ -196,7 +197,7 @@ set(SOURCE_FILES_DATA
   src/data/QGearsSerializer.cpp
   src/data/QGearsTexCodec.cpp
   src/data/QGearsTexFile.cpp
-
+  src/data/QGearsTriggersFile.cpp
 )
 
 set(SOURCE_FILES
@@ -336,9 +337,9 @@ add_library(QGearsMain STATIC
 )
 
 # Coverage uses more memory, combined with PCH can cause OOM/ICE
-if ($ENV{COVERAGE}!=1)
+#if ($ENV{COVERAGE}!=1)
 cotire(QGearsMain)
-endif()
+#endif()
 SET_PROPERTY(TARGET QGearsMain PROPERTY FOLDER "q-gears")
 
 add_library(q-gears-data STATIC

+ 1 - 1
QGearsMain/include/common/TypeDefine.h

@@ -60,7 +60,7 @@ namespace QGears
     extern const String    EXT_TIM;
     extern const String    EXT_TEX;
 
-
+    extern const String    EXT_TRIGGERS;
     extern const String    EXT_BACKGROUND;
     extern const String    EXT_CAMERA_MATRIX;
     extern const String    EXT_MODEL_LIST;

+ 1 - 1
QGearsMain/include/data/QGearsBackgroundFileSerializer.h

@@ -39,7 +39,7 @@ namespace QGears
                         BackgroundFileSerializer();
         virtual        ~BackgroundFileSerializer();
 
-        virtual void    importBackgroundFile( Ogre::DataStreamPtr &stream, BackgroundFile *pDest );
+        void    importBackgroundFile( Ogre::DataStreamPtr &stream, BackgroundFile *pDest );
 
         enum {
             BIT_MASK_RED    = 0xF800

+ 12 - 12
QGearsMain/include/data/QGearsCameraMatrixFile.h

@@ -44,23 +44,23 @@ namespace QGears
 
         static const String RESOURCE_TYPE;
 
-        virtual const Ogre::Matrix3&    getMatrix() const;
-        virtual void                    setMatrix( const Ogre::Matrix3& matrix );
+        const Ogre::Matrix3&    getMatrix() const;
+        void                    setMatrix( const Ogre::Matrix3& matrix );
 
-        virtual const Ogre::Vector3&    getPosition() const;
-        virtual void                    setPosition( const Ogre::Vector3& position );
+        const Ogre::Vector3&    getPosition() const;
+        void                    setPosition( const Ogre::Vector3& position );
 
-        virtual const Pixel&            getOffset() const;
-        virtual void                    setOffset( const Pixel& offset );
+        const Pixel&            getOffset() const;
+        void                    setOffset( const Pixel& offset );
 
-        virtual const size_t&           getCount() const;
-        virtual void                    setCount( const size_t count );
+        const size_t&           getCount() const;
+        void                    setCount( const size_t count );
 
-        virtual const Ogre::Real&       getFocalLength() const;
-        virtual void                    setFocalLength( const Ogre::Real );
+        const Ogre::Real&       getFocalLength() const;
+        void                    setFocalLength( const Ogre::Real );
 
-        virtual Ogre::Quaternion        getOrientation() const;
-        virtual Ogre::Radian            getFov( const Ogre::Real& width ) const;
+        Ogre::Quaternion        getOrientation() const;
+        Ogre::Radian            getFov( Ogre::Real width ) const;
 
     protected:
         virtual void loadImpl( void );

+ 4 - 0
QGearsMain/include/data/QGearsFLevelFile.h

@@ -39,6 +39,7 @@ THE SOFTWARE.
 #include "QGearsCameraMatrixFile.h"
 #include "QGearsPaletteFile.h"
 #include "QGearsHRCFile.h"
+#include "QGearsTriggersFile.h"
 
 namespace QGears
 {
@@ -67,6 +68,7 @@ namespace QGears
         const ModelListFilePtr&     getModelList() const;
         const PaletteFilePtr&       getPalette() const;
         const WalkmeshFilePtr&      getWalkmesh() const;
+        const TriggersFilePtr&      getTriggers() const;
 
         void setRawScript(const std::vector<u8>& scriptData);
         void setBackground  ( const BackgroundFilePtr      &background    );
@@ -74,6 +76,7 @@ namespace QGears
         void setModelList   ( const ModelListFilePtr       &model_list    );
         void setPalette     ( const PaletteFilePtr         &palette       );
         void setWalkmesh    ( const WalkmeshFilePtr        &walkmesh      );
+        void setTriggers(const TriggersFilePtr& triggers);
 
         String getBackground2DName( void ) const;
         String getBackgroundTextureName( void ) const;
@@ -100,6 +103,7 @@ namespace QGears
         ModelListFilePtr            m_model_list;
         PaletteFilePtr              m_palette;
         WalkmeshFilePtr             m_walkmesh;
+        TriggersFilePtr             m_triggers;
         std::vector<u8>             m_rawScript;
 
         FLevelTextureLoader        *m_background_texture_loader;

+ 1 - 0
QGearsMain/include/data/QGearsFLevelFileSerializer.h

@@ -75,6 +75,7 @@ namespace QGears
         void    readPalette     ( Ogre::DataStreamPtr &stream, FLevelFile* pDest );
         void    readWalkmesh    ( Ogre::DataStreamPtr &stream, FLevelFile* pDest );
         void    readBackground  ( Ogre::DataStreamPtr &stream, FLevelFile* pDest );
+        void    readTriggers    (Ogre::DataStreamPtr &stream, FLevelFile* pDest);
 
         void    readEnd( Ogre::DataStreamPtr &stream );
 

+ 2 - 0
QGearsMain/include/data/QGearsSerializer.h

@@ -52,6 +52,7 @@ namespace QGears
         void    readObject( Ogre::DataStreamPtr &stream, Ogre::AxisAlignedBox &pDest );
         void    readObject( Ogre::DataStreamPtr &stream, Pixel &pDest );
 
+        void readChars(Ogre::DataStreamPtr& stream, char* pDest, size_t count);
         void    read1ByteBool( Ogre::DataStreamPtr &stream, bool &pDest );
         void    read2ByteBool( Ogre::DataStreamPtr &stream, bool &pDest );
         void    readShort( Ogre::DataStreamPtr &stream, uint16 &pDest );
@@ -60,6 +61,7 @@ namespace QGears
         void    readInt16( Ogre::DataStreamPtr &stream, sint16 &pDest );
         void    readUInt16( Ogre::DataStreamPtr &stream, uint16 &pDest );
         void    readUInt32( Ogre::DataStreamPtr &stream, uint32 &pDest );
+        void    readSInt32(Ogre::DataStreamPtr &stream, sint32 &pDest);
         void    readUInt32( Ogre::DataStream &stream, uint32 &pDest );
         void    readUInt8( Ogre::DataStream& stream, uint8 &pDest );
         void    readUInt8(Ogre::DataStreamPtr &stream, uint8 &pDest );

+ 141 - 0
QGearsMain/include/data/QGearsTriggersFile.h

@@ -0,0 +1,141 @@
+#pragma once
+
+#include <OgreResourceManager.h>
+#include "QGearsPrerequisites.h"
+#include "common/QGearsResource.h"
+#include "QGearsSerializer.h"
+
+namespace QGears
+{
+    class TriggersFileManager :
+        public Ogre::ResourceManager, 
+        public Ogre::Singleton<TriggersFileManager>
+    {
+    public:
+        TriggersFileManager();
+        virtual ~TriggersFileManager();
+        static TriggersFileManager& getSingleton();
+        static TriggersFileManager* getSingletonPtr();
+    protected:
+        virtual Ogre::Resource *createImpl(
+            const Ogre::String &name,
+            Ogre::ResourceHandle handle,
+            const Ogre::String& group,
+            bool isManual,
+            Ogre::ManualResourceLoader* loader,
+            const Ogre::NameValuePairList* createParams) override;
+    };
+
+    class TriggersFile : public Resource
+    {
+    public:
+        TriggersFile(Ogre::ResourceManager* creator, 
+            const String &name,
+            Ogre::ResourceHandle handle,
+            const String& group, 
+            bool isManual = false,
+            Ogre::ManualResourceLoader* loader = nullptr);
+        virtual ~TriggersFile();
+        static const String RESOURCE_TYPE;
+       
+        struct Range
+        {
+            s16 left;
+            s16 top;
+            s16 right;
+            s16 bottom;
+        };
+
+        const Range& getCameraRange() const
+        {
+            return mData->camera_range;
+        }
+
+    protected:
+        virtual void loadImpl(void) override;
+        virtual void unloadImpl(void) override;
+        virtual size_t calculateSize(void) const override;
+    private:
+
+        struct Vertex_s 
+        {
+            u16 x;
+            u16 y;
+            u16 z;
+        };
+
+        struct Exit
+        {
+            std::array<Vertex_s, 2> exit_line;
+            Vertex_s destination;
+            u16 fieldID;
+            u8 dir, dir_copy1, dir_copy2, dir_copy3;
+        };
+
+        struct Trigger
+        {
+            std::array<Vertex_s, 2> trigger_line;
+            u8 background_parameter;
+            u8 background_state;
+            u8 behavior;
+            /* 0 - OnTrigger - ON
+            * 1 - OnTrigger - OFF
+            * 2 - OnTrigger - ON, AwayFromTrigger - OFF
+            * 3 - OnTrigger - OFF, AwayFromTrigger - ON
+            * 4 - OnTrigger - ON, AwayFromTriggerOnPlusSide - OFF
+            * 5 - OnTrigger - OFF, AwayFromTriggerOnPlusSide - ON
+            */
+            u8 soundID;
+        };
+
+        struct Arrow
+        {
+            s32 positionX;
+            s32 positionZ;
+            s32 positionY;
+            u32 type;// 0 - Invisible, 1 - Red, 2 - Green
+        };
+
+        struct TriggerData
+        {
+            std::array<char,9> name;
+            u8 control;
+            s16 cameraFocusHeight;
+            Range camera_range; // 8 bytes
+            u8 bg_layer1_flag;
+            u8 bg_layer2_flag;
+            u8 bg_layer3_flag;
+            u8 bg_layer4_flag;
+            s16 bg_layer3_width;
+            s16 bg_layer3_height;
+            s16 bg_layer4_width;
+            s16 bg_layer4_height;
+            std::array<u8,24> unknown;
+            std::array<Exit,12> doors;// 24 * 12 bytes
+            std::array<Trigger, 12> triggers;// 16 * 12 bytes
+            // Only in occidental/international version
+            std::array<u8,12> display_arrow;
+            std::array<Arrow,12> arrows;// 16 * 12 bytes
+        };
+        
+
+        std::unique_ptr<TriggerData> mData;
+
+        friend class TriggerFileSerializer;
+    };
+    
+    class TriggerFileSerializer : public Serializer
+    {
+    public:
+        TriggerFileSerializer();
+        void importTriggerFile(Ogre::DataStreamPtr &stream, TriggersFile *pDest);
+    private:
+        void ReadVertex_s(Ogre::DataStreamPtr& stream, TriggersFile::Vertex_s& vertex);
+        void ReadRange(Ogre::DataStreamPtr& stream, TriggersFile::Range& range);
+        void ReadExit(Ogre::DataStreamPtr& stream, TriggersFile::Exit& exit);
+        void ReadArrow(Ogre::DataStreamPtr& stream, TriggersFile::Arrow& arrow);
+        void ReadTrigger(Ogre::DataStreamPtr& stream, TriggersFile::Trigger& trigger);
+    };
+
+    typedef Ogre::SharedPtr<TriggersFile> TriggersFilePtr;
+}

+ 2 - 0
QGearsMain/src/common/QGearsApplication.cpp

@@ -35,6 +35,7 @@ GNU General Public License for more details.
 #include "map/QGearsWalkmeshFileManager.h"
 #include "data/FF7ModelListFileManager.h"
 #include "data/QGearsLGPArchiveFactory.h"
+#include "data/QGearsTriggersFile.h"
 #include "common/make_unique.h"
 #include "qgears_version.h"
 
@@ -279,6 +280,7 @@ namespace QGears
         m_resource_managers.emplace_back( std::make_shared<QGears::LZSFLevelFileManager>() );
         m_resource_managers.emplace_back( std::make_shared<QGears::BackgroundFileManager>() );
         m_resource_managers.emplace_back( std::make_shared<QGears::Background2DFileManager>() );
+        m_resource_managers.emplace_back(std::make_shared<QGears::TriggersFileManager>());
     }
 
     //--------------------------------------------------------------------------

+ 1 - 0
QGearsMain/src/common/TypeDefine.cpp

@@ -39,6 +39,7 @@ namespace QGears
     const String    EXT_TEX     ( ".tex"        );
     const String    EXT_TIM     ( ".tim"        );
 
+    const String    EXT_TRIGGERS     (".triggers");
     const String    EXT_BACKGROUND   ( ".background" );
     const String    EXT_CAMERA_MATRIX( ".cam_matrix" );
     const String    EXT_MODEL_LIST   ( ".model_list" );

+ 1 - 1
QGearsMain/src/data/QGearsCameraMatrixFile.cpp

@@ -155,7 +155,7 @@ namespace QGears
 
     //---------------------------------------------------------------------
     Ogre::Radian
-    CameraMatrixFile::getFov( const Ogre::Real& width ) const
+    CameraMatrixFile::getFov( Ogre::Real width ) const
     {
         return 2 * Ogre::Math::ATan( width / (2 * m_focal_length ) );
     }

+ 43 - 16
QGearsMain/src/data/QGearsCameraMatrixFileSerializer.cpp

@@ -45,30 +45,57 @@ namespace QGears
     void
     CameraMatrixFileSerializer::importCameraMatrixFile( Ogre::DataStreamPtr &stream, CameraMatrixFile* pDest )
     {
+        // Read matrix
         sint16 matrix_sint16[CAMERA_MATRIX_ROW_COUNT][CAMERA_MATRIX_COL_COUNT];
-        readShorts( stream, reinterpret_cast< uint16* >( matrix_sint16 ), CAMERA_MATRIX_ENTRY_COUNT  );
+        readInt16(stream, matrix_sint16[0][0]);
+        readInt16(stream, matrix_sint16[1][0]);
+        readInt16(stream, matrix_sint16[2][0]);
+        readInt16(stream, matrix_sint16[0][1]);
+        readInt16(stream, matrix_sint16[1][1]);
+        readInt16(stream, matrix_sint16[2][1]);
+        readInt16(stream, matrix_sint16[0][2]);
+        readInt16(stream, matrix_sint16[1][2]);
+        readInt16(stream, matrix_sint16[2][2]);
         stream->skip( 2 ); // unused
+    
+        // Array to matrix
+        Ogre::Matrix3 camera_matrix;
+        camera_matrix[0][0] = static_cast<float>(matrix_sint16[0][0]) / 4096.0f;
+        camera_matrix[1][0] = static_cast<float>(matrix_sint16[1][0]) / 4096.0f;
+        camera_matrix[2][0] = static_cast<float>(matrix_sint16[2][0]) / 4096.0f;
+        camera_matrix[0][1] = static_cast<float>(matrix_sint16[0][1]) / 4096.0f;
+        camera_matrix[1][1] = static_cast<float>(matrix_sint16[1][1]) / 4096.0f;
+        camera_matrix[2][1] = static_cast<float>(matrix_sint16[2][1]) / 4096.0f;
+        camera_matrix[0][2] = static_cast<float>(matrix_sint16[0][2]) / 4096.0f;
+        camera_matrix[1][2] = static_cast<float>(matrix_sint16[1][2]) / 4096.0f;
+        camera_matrix[2][2] = static_cast<float>(matrix_sint16[2][2]) / 4096.0f;
 
+        // Read POS
         sint32 pos[CAMERA_MATRIX_ROW_COUNT];
-        readInts( stream, reinterpret_cast< uint32* >( pos ), CAMERA_MATRIX_ROW_COUNT );
+        readInts(stream, reinterpret_cast<uint32*>(pos), CAMERA_MATRIX_ROW_COUNT);
 
-        Ogre::Matrix3 camera_matrix;
+        // Array to vector
         Ogre::Vector3 position;
-        for( size_t i(0); i < CAMERA_MATRIX_ROW_COUNT; ++i )
+        for (int i = 0; i < 3; i++)
         {
-            position[i] = Ogre::Real(pos[i]);
-            for( size_t j(0); j < CAMERA_MATRIX_COL_COUNT; ++j )
-            {
-                camera_matrix[j][i] = matrix_sint16[i][j] / 4096.0f;
-            }
+            position[i] = -Ogre::Real(pos[i]);
         }
-        position = camera_matrix * position;
-        camera_matrix[0][1] *= -1;
-        camera_matrix[1][1] *= -1;
-        camera_matrix[2][1] *= -1;
-        camera_matrix[0][2] *= -1;
-        camera_matrix[1][2] *= -1;
-        camera_matrix[2][2] *= -1;
+
+        Ogre::Quaternion orientation;
+        orientation.FromRotationMatrix(camera_matrix);
+        position = orientation * (position / 128.0f);
+
+        // Matrix fix up
+        camera_matrix[0][0] = camera_matrix[0][0];
+        camera_matrix[1][0] = camera_matrix[1][0];
+        camera_matrix[2][0] = camera_matrix[2][0];
+        camera_matrix[0][1] = -camera_matrix[0][1];
+        camera_matrix[1][1] = -camera_matrix[1][1];
+        camera_matrix[2][1] = -camera_matrix[2][1];
+        camera_matrix[0][2] = -camera_matrix[0][2];
+        camera_matrix[1][2] = -camera_matrix[1][2];
+        camera_matrix[2][2] = -camera_matrix[2][2];
+
         pDest->setMatrix( camera_matrix );
         pDest->setPosition( position );
 

+ 11 - 0
QGearsMain/src/data/QGearsFLevelFile.cpp

@@ -162,6 +162,7 @@ namespace QGears
         m_model_list.setNull();
         m_walkmesh.setNull();
         m_hrc_files.clear();
+        m_triggers.setNull();
     }
 
     //--------------------------------------------------------------------------
@@ -252,6 +253,11 @@ namespace QGears
         return m_walkmesh;
     }
 
+    const TriggersFilePtr& FLevelFile::getTriggers() const
+    {
+        return m_triggers;
+    }
+
     //--------------------------------------------------------------------------
     void
     FLevelFile::setWalkmesh( const WalkmeshFilePtr &walkmesh )
@@ -259,6 +265,11 @@ namespace QGears
         m_walkmesh = walkmesh;
     }
 
+    void FLevelFile::setTriggers(const TriggersFilePtr& triggers)
+    {
+        m_triggers = triggers;
+    }
+
     //--------------------------------------------------------------------------
     String
     FLevelFile::getBackgroundTextureName( void ) const

+ 24 - 0
QGearsMain/src/data/QGearsFLevelFileSerializer.cpp

@@ -41,6 +41,7 @@ THE SOFTWARE.
 #include "data/QGearsPaletteFileSerializer.h"
 #include "map/QGearsWalkmeshFileManager.h"
 #include "map/FF7WalkmeshFileSerializer.h"
+#include "data/QGearsTriggersFile.h"
 
 namespace QGears
 {
@@ -206,6 +207,18 @@ namespace QGears
             case SECTION_BACKGROUND:
                 readBackground( stream, pDest );
                 break;
+
+            case SECTION_TILE_MAP:
+                // TODO
+                break;
+
+            case SECTION_ENCOUNTER:
+                // TODO
+                break;
+
+            case SECTION_TRIGGER:
+                readTriggers(stream, pDest);
+                break;
         }
     }
 
@@ -285,6 +298,17 @@ namespace QGears
         pDest->setBackground( background );
     }
 
+    void FLevelFileSerializer::readTriggers(Ogre::DataStreamPtr &stream, FLevelFile* pDest)
+    {
+        TriggersFilePtr triggers = createResource<TriggersFileManager>(pDest, EXT_TRIGGERS).staticCast<TriggersFile>();
+
+        TriggerFileSerializer ser;
+        ser.importTriggerFile(stream, triggers.getPointer());
+
+        pDest->setTriggers(triggers);
+    }
+
+
     //--------------------------------------------------------------------------
     String
     FLevelFileSerializer::getBaseName( const FLevelFile *pDest ) const

+ 10 - 0
QGearsMain/src/data/QGearsSerializer.cpp

@@ -89,6 +89,11 @@ namespace QGears
         flipFromLittleEndian( &pDest, 2, 2 );
     }
 
+    void Serializer::readChars(Ogre::DataStreamPtr& stream, char* pDest, size_t count)
+    {
+        stream->read(pDest, count);
+    }
+
     //---------------------------------------------------------------------
     void
     Serializer::read1ByteBool( Ogre::DataStreamPtr &stream, bool &pDest )
@@ -141,6 +146,11 @@ namespace QGears
         readInts( stream, &pDest, 1 );
     }
 
+    void Serializer::readSInt32(Ogre::DataStreamPtr &stream, sint32 &pDest)
+    {
+        stream->read(&pDest, sizeof(sint32));
+    }
+
     void Serializer::readUInt32( Ogre::DataStream &stream, uint32 &pDest )
     {
         stream.read(&pDest,sizeof(uint32));

+ 185 - 0
QGearsMain/src/data/QGearsTriggersFile.cpp

@@ -0,0 +1,185 @@
+#include "data/QGearsTriggersFile.h"
+
+template<> QGears::TriggersFileManager *Ogre::Singleton<QGears::TriggersFileManager>::msSingleton = nullptr;
+
+namespace QGears
+{
+    TriggersFileManager::TriggersFileManager()
+    {
+        mResourceType = TriggersFile::RESOURCE_TYPE;
+
+        // low, because it will likely reference other resources
+        mLoadOrder = 30.0f;
+
+        // this is how we register the ResourceManager with OGRE
+        Ogre::ResourceGroupManager::getSingleton()._registerResourceManager(mResourceType, this);
+    }
+
+    TriggersFileManager::~TriggersFileManager()
+    {
+        Ogre::ResourceGroupManager::getSingleton()._unregisterResourceManager(mResourceType);
+    }
+
+    /*static*/ TriggersFileManager& TriggersFileManager::getSingleton()
+    {
+        assert(msSingleton);
+        return(*msSingleton);
+    }
+
+    /*static*/ TriggersFileManager* TriggersFileManager::getSingletonPtr()
+    {
+        return msSingleton;
+    }
+
+    // ===========================================================================
+
+    TriggersFile::TriggersFile(Ogre::ResourceManager* creator,
+        const String &name,
+        Ogre::ResourceHandle handle,
+        const String& group,
+        bool isManual,
+        Ogre::ManualResourceLoader* loader)
+        : Resource(creator, name, handle, group, isManual, loader)
+    {
+    }
+
+    TriggersFile::~TriggersFile()
+    {
+        unload();
+    }
+ 
+    void TriggersFile::loadImpl(void)
+    {
+        TriggerFileSerializer serializer;
+        Ogre::DataStreamPtr stream(openResource());
+        serializer.importTriggerFile(stream, this);
+    }
+
+    void TriggersFile::unloadImpl(void)
+    {
+
+    }
+
+    size_t TriggersFile::calculateSize(void) const
+    {
+        return sizeof(TriggerData);
+    }
+
+    /*static*/ const String TriggersFile::RESOURCE_TYPE("FF7FieldTriggersSection");
+
+    // ===========================================================================
+
+    Ogre::Resource* TriggersFileManager::createImpl(
+        const Ogre::String &name,
+        Ogre::ResourceHandle handle,
+        const Ogre::String& group,
+        bool isManual,
+        Ogre::ManualResourceLoader* loader,
+        const Ogre::NameValuePairList* createParams)
+    {
+        return new TriggersFile(this, name, handle, group, isManual, loader);
+    }
+
+
+    TriggerFileSerializer::TriggerFileSerializer()
+    {
+
+    }
+
+    void TriggerFileSerializer::ReadVertex_s(Ogre::DataStreamPtr& stream, TriggersFile::Vertex_s& vertex)
+    {
+        readShort(stream, vertex.x);
+        readShort(stream, vertex.y);
+        readShort(stream, vertex.z);
+    }
+
+    void TriggerFileSerializer::ReadRange(Ogre::DataStreamPtr& stream, TriggersFile::Range& range)
+    {
+        readInt16(stream, range.left);
+        readInt16(stream, range.top);
+        readInt16(stream, range.right);
+        readInt16(stream, range.bottom);
+    }
+
+    void TriggerFileSerializer::ReadExit(Ogre::DataStreamPtr& stream, TriggersFile::Exit& exit)
+    {
+        for (size_t i = 0; i < exit.exit_line.size(); i++)
+        {
+            ReadVertex_s(stream, exit.exit_line[i]);
+        }
+        ReadVertex_s(stream, exit.destination);
+        readShort(stream, exit.fieldID);
+        readUInt8(stream, exit.dir);
+        readUInt8(stream, exit.dir_copy1);
+        readUInt8(stream, exit.dir_copy2);
+        readUInt8(stream, exit.dir_copy3);
+    }
+
+    void TriggerFileSerializer::ReadArrow(Ogre::DataStreamPtr& stream, TriggersFile::Arrow& arrow)
+    {
+        readSInt32(stream, arrow.positionX);
+        readSInt32(stream, arrow.positionZ);
+        readSInt32(stream, arrow.positionY);
+        readUInt32(stream, arrow.type);
+    }
+
+    void TriggerFileSerializer::ReadTrigger(Ogre::DataStreamPtr& stream, TriggersFile::Trigger& trigger)
+    {
+        for (size_t i = 0; i < trigger.trigger_line.size(); i++)
+        {
+            ReadVertex_s(stream, trigger.trigger_line[i]);
+        }
+        readUInt8(stream, trigger.background_parameter);
+        readUInt8(stream, trigger.background_state);
+        readUInt8(stream, trigger.behavior);
+        readUInt8(stream, trigger.soundID);
+    }
+
+    void TriggerFileSerializer::importTriggerFile(Ogre::DataStreamPtr &stream, TriggersFile *pDest)
+    {
+        std::unique_ptr<TriggersFile::TriggerData> data = std::unique_ptr<TriggersFile::TriggerData>(new TriggersFile::TriggerData());
+
+        readChars(stream, data->name.data(), data->name.size());
+        readUInt8(stream, data->control);
+        readInt16(stream, data->cameraFocusHeight);
+        ReadRange(stream, data->camera_range);
+
+        readUInt8(stream, data->bg_layer1_flag);
+        readUInt8(stream, data->bg_layer2_flag);
+        readUInt8(stream, data->bg_layer3_flag);
+        readUInt8(stream, data->bg_layer4_flag);
+   
+        readInt16(stream, data->bg_layer3_width);
+        readInt16(stream, data->bg_layer3_height);
+        readInt16(stream, data->bg_layer4_width);
+        readInt16(stream, data->bg_layer4_height);
+
+        stream->read(data->unknown.data(), data->unknown.size());
+
+
+        for (size_t i = 0; i < data->doors.size(); i++)
+        {
+            TriggersFile::Exit& exit = data->doors[i];
+            ReadExit(stream, exit);
+        }
+        
+        for (size_t i = 0; i < data->triggers.size(); i++)
+        {
+            TriggersFile::Trigger& trigger = data->triggers[i];
+            ReadTrigger(stream, trigger);
+        }
+
+        stream->read(data->display_arrow.data(), data->display_arrow.size());
+
+        for (size_t i = 0; i < data->arrows.size(); i++)
+        {
+            TriggersFile::Arrow& arrow = data->arrows[i];
+            ReadArrow(stream, arrow);
+        }
+
+        pDest->mData = std::move(data);
+
+
+    }
+
+}

+ 39 - 12
utilities/q-gears-launcher/src/ff7DataInstaller.cpp

@@ -153,7 +153,6 @@ static void FF7PcFieldToQGearsField(QGears::FLevelFilePtr& field, const std::str
 {
     // Save out the tiles as a PNG image
     
-    const QGears::BackgroundFilePtr& bg = field->getBackground();
 
     try
     {
@@ -170,8 +169,13 @@ static void FF7PcFieldToQGearsField(QGears::FLevelFilePtr& field, const std::str
         std::cerr << "InternalDecompilerError: " << ex.what() << std::endl;
     }
 
-    
+
+    //const QGears::ModelListFilePtr& models = field->getModelList();
+    //const QGears::ModelListFile::ModelDescription& desc = models->getModels().at(0);
+
+
     const QGears::PaletteFilePtr& pal = field->getPalette();
+    const QGears::BackgroundFilePtr& bg = field->getBackground();
     std::unique_ptr<Ogre::Image> bgImage(bg->createImage(pal));
     bgImage->save(outDir + "/" + field->getName() + ".png");
 
@@ -179,28 +183,51 @@ static void FF7PcFieldToQGearsField(QGears::FLevelFilePtr& field, const std::str
         TiXmlDocument doc;
         std::unique_ptr<TiXmlElement> element(new TiXmlElement("background2d"));
 
-        // TODO: Write out the required attributes: image, position, orientation, fov, range and clip
-        auto& layers = bg->getLayers();
-        const QGears::CameraMatrixFilePtr& camMatrix = field->getCameraMatrix();
+        // Magic constants
+        const int kScaleUpFactor = 3;
+        const int kPsxScreenWidth = 320;
+        const int kPsxScreenHeight = 240;
+
+        // Get texture atlas size
+        const int width = bgImage->getWidth();
+        const int height = bgImage->getHeight();
 
+        const QGears::CameraMatrixFilePtr& camMatrix = field->getCameraMatrix();
+        const Ogre::Vector3 position = camMatrix->getPosition();
+        const Ogre::Quaternion orientation = camMatrix->getOrientation();
+        const Ogre::Degree fov = camMatrix->getFov(static_cast<float>(kPsxScreenHeight));
+
+        const QGears::TriggersFilePtr& triggers = field->getTriggers();
+        const int min_x = triggers->getCameraRange().left * kScaleUpFactor;
+        const int min_y = triggers->getCameraRange().top * kScaleUpFactor;
+        const int max_x = triggers->getCameraRange().right * kScaleUpFactor;
+        const int max_y = triggers->getCameraRange().bottom * kScaleUpFactor;
+
+        element->SetAttribute("image", field->getName() + ".png");
+        element->SetAttribute("position", Ogre::StringConverter::toString(position));
+        element->SetAttribute("orientation", Ogre::StringConverter::toString(orientation));
+        element->SetAttribute("fov", Ogre::StringConverter::toString(fov));
+        element->SetAttribute("range", std::to_string(min_x) + " " + std::to_string(min_y) + " " + std::to_string(max_x) + " " + std::to_string(max_y));
+        element->SetAttribute("clip", std::to_string(kPsxScreenWidth * kScaleUpFactor) + " " + std::to_string(kPsxScreenHeight * kScaleUpFactor));
+   
         // Write out the *_BG.XML data
-        for (auto& layer : layers)
+        auto& layers = bg->getLayers();
+        for (const auto& layer : layers)
         {
             // TODO: Should we only output tiles to construct enabled layers?
           //  if (layer.enabled)
             {
                
-                for (QGears::BackgroundFile::SpriteData& sprite : layer.sprites)
+                for (const QGears::BackgroundFile::SpriteData& sprite : layer.sprites)
                 {
                     std::unique_ptr<TiXmlElement> xmlElement(new TiXmlElement("tile"));
 
-                    // Not sure why it needs to be * 3
                     xmlElement->SetAttribute("destination",
-                        Ogre::StringConverter::toString(sprite.dst.x * 3) + " " + 
-                        Ogre::StringConverter::toString(sprite.dst.y * 3));
+                        Ogre::StringConverter::toString(sprite.dst.x * kScaleUpFactor) + " " +
+                        Ogre::StringConverter::toString(sprite.dst.y * kScaleUpFactor));
 
-                    xmlElement->SetAttribute("width", Ogre::StringConverter::toString(sprite.width * 3));
-                    xmlElement->SetAttribute("height", Ogre::StringConverter::toString(sprite.height * 3));
+                    xmlElement->SetAttribute("width", Ogre::StringConverter::toString(sprite.width * kScaleUpFactor));
+                    xmlElement->SetAttribute("height", Ogre::StringConverter::toString(sprite.height * kScaleUpFactor));
 
                     // Each tile is added to a big texture atlas with hard coded size of 1024x1024, convert UV's to the 0.0f to 1.0f range
                     const float u0 = static_cast<float>(sprite.src.x) / bgImage->getWidth();