Jigsaw.h

// Jigsaw.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2010

@import "lxOperation.h"
#include "Ceda/cxUtils/IsaacRandom.h"

namespace jsns
{

// Identifies a piece on the jigsaw as they are positioned in rows and columns, assuming 
// row major order
typedef ceda::ssize_t PieceIndex;


///////////////////////////////////////////////////////////////////////////////////////////////////
// MPoint2d

$model+ MPoint2d
{
    ceda::int32 X;
    ceda::int32 Y;
};


///////////////////////////////////////////////////////////////////////////////////////////////////
// MColour

$model+ MColour
{
    ceda::uint8 R;
    ceda::uint8 G;
    ceda::uint8 B;
};


///////////////////////////////////////////////////////////////////////////////////////////////////
// JigsawPiece

$model+ MJigsawPiece
{
    assignable<MPoint2d> Position;
    bool JoinedOnRight;
    bool JoinedOnBottom;
};


///////////////////////////////////////////////////////////////////////////////////////////////////
// MUser

$struct+ MUser isa ceda::IPersistable :
    model
    {
        assignable<string16> Name;
        ceda::int32 PieceIndexBeingMoved;
        ceda::int32 NumPiecesConnected;
    }
{
    void Init(const ceda::char16* name)
    {
        Name = name;
        PieceIndexBeingMoved = -1;
        NumPiecesConnected = 0;
    }
};


///////////////////////////////////////////////////////////////////////////////////////////////////
// JpegImageX

$class+ JpegImageX isa ceda::IPersistable //: public ceda::JpegImage
{
public:
    JpegImageX() : m_haveImage(false) {}

    bool operator==(const JpegImageX& rhs) const
    {
        return m_haveImage == rhs.m_haveImage;// && m_buffer == rhs.m_buffer;
    }
    bool operator!=(const JpegImageX& rhs) const
    {
        return !operator==(rhs);
    }
    bool operator<(const JpegImageX& rhs) const
    {
        return m_haveImage < rhs.m_haveImage;
    }

    void LoadAnImage(ceda::IsaacRandomNumberGen& isaac)
    {
        ceda::PagedBufferToOutputStreamAdapter dst(m_buffer);
        {
            ceda::Archive ar(&dst);
            ceda::ssize_t n = isaac.GetUniformDistInteger(0,1000);
            for (ceda::ssize_t i=0 ; i < n ; ++i)
            {
                ar << (ceda::octet_t) isaac.GetUniformDistInteger(0,256);
            }
        }
        m_haveImage = true;
        //MarkAsDirtyWithoutTrace();
    }

    static const ceda::schema_t JpegImageX_SCHEMA = 1;

    void Serialise(ceda::Archive& ar) const
    {
        ceda::SerialiseSchema(ar, JpegImageX_SCHEMA);
        ar << m_haveImage;
        if (m_haveImage)
        {
            ar << m_buffer;
        }
    }

    void Deserialise(ceda::InputArchive& ar)
    {
        ceda::schema_t schema;
        ceda::DeserialiseSchema(ar,JpegImageX_SCHEMA,schema);
        ar >> m_haveImage;
        if (m_haveImage)
        {
            ar >> m_buffer;
        }
    }

private:
    ceda::PagedBuffer m_buffer;
    bool m_haveImage;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// MJigsaw

$struct+ MJigsaw isa ceda::IPersistable :
    model
    {
        MColour BackdropColour;
        MPoint2d DeskTopSize;               // In pixels
        
        // Ptr to a non-model for the image
        ceda::cref<JpegImageX> Image;
        
        // Provides distance in pixels for which user needs to position two pieces in order
        // that they are assumed to have been connected.
        ceda::float64 PixelTolerance;     // range: 1,10000

        // Governs the extent to which internal positions may be randomly shifted in order 
        // to vary their shape.
        // m_geometryFactor = 0 eliminates random variation.
        // m_geometryFactor = 50 provides substantial random variation.
        // A value of about 25 is reasonable.
        ceda::float64 GeometryFactor;     // range(0,50)

        // Seed for random number generator used to calculate random geometry
        ceda::int32 RandomNumberSeed;
        
        ceda::int32 NumRows;
        ceda::int32 NumCols;

        // Defines the positions and connectivity of the pieces, indexed by PieceIndex
        // in row major order
        MJigsawPiece Pieces[];
        
        ceda::xvector<ceda::movable<ceda::cref<MUser> > > Users;
        
        $$() : 
            BackdropColour(70,50,50),
            DeskTopSize(1024,1024),
            PixelTolerance(20),
            GeometryFactor(25),
            RandomNumberSeed(0),
            NumRows(3),
            NumCols(4)
        {
        }
    }
{
};

} // namespace jsns