<commit_before>#include <maya/MFnMesh.h>
#include <maya/MFnMeshData.h>
#include <maya/MEulerRotation.h>
#include <maya/MQuaternion.h>
#include <maya/MFnArrayAttrsData.h>
#include <maya/MArrayDataBuilder.h>

#include "Asset.h"
#include "AssetNode.h"
#include "OutputInstancerObject.h"
#include "util.h"

OutputInstancerObject::OutputInstancerObject(
        int assetId,
        int objectId,
        Asset* objectControl
        ) :
    OutputObject(
            assetId,
            objectId,
            objectControl
          ),
    myGeoInfo(HAPI_GeoInfo_Create())
{
    //update();
}

OutputInstancerObject::~OutputInstancerObject() {}

OutputObject::ObjectType
OutputInstancerObject::type()
{
    return OutputObject::OBJECT_TYPE_INSTANCER;
}

MStringArray
OutputInstancerObject::getAttributeStringData(HAPI_AttributeOwner owner, MString name)
{
    return Util::getAttributeStringData(myAssetId, myObjectId, 0, 0, owner, name);
}

void
OutputInstancerObject::update()
{
    OutputObject::update();

    try
    {
        HAPI_Result hstat = HAPI_RESULT_SUCCESS;
        hstat = HAPI_GetGeoInfo(myAssetId, myObjectId, 0, &myGeoInfo);
        Util::checkHAPIStatus(hstat);
    }
    catch (HAPIError& e)
    {
        cerr << e.what() << endl;
        return;
    }

    if(myNeverBuilt || myGeoInfo.hasGeoChanged)
    {
        // clear the arrays
        myInstancedObjectNames.clear();
        myInstancedObjectIndices.clear();
        myUniqueInstObjNames.clear();
        myHoudiniInstanceAttribute.clear();
        myHoudiniNameAttribute.clear();

        try
        {
            if(myGeoInfo.partCount <= 0)
                return;

            HAPI_Result hstat = HAPI_RESULT_SUCCESS;
            hstat = HAPI_GetPartInfo(myAssetId, myObjectId, 0, 0, &myPartInfo);
            Util::checkHAPIStatus(hstat);
        }
        catch (HAPIError& e)
        {
            cerr << e.what() << endl;
        }

        if(myObjectInfo.objectToInstanceId >= 0)
        {
            myInstancedObjectIndices = MIntArray(myPartInfo.pointCount, 0);
            return;
        }

        // fill array of size pointCount of instanced names
        MStringArray instanceAttrs = getAttributeStringData(HAPI_ATTROWNER_POINT, "instance");
        for(unsigned int i=0; i<instanceAttrs.length(); i++)
        {
            MStringArray splitObjName;
            instanceAttrs[i].split('/', splitObjName);
            myInstancedObjectNames.append(splitObjName[splitObjName.length()-1]);
            myHoudiniInstanceAttribute.append(instanceAttrs[i]);
        }

        MStringArray nameAttrs = getAttributeStringData(HAPI_ATTROWNER_POINT, "name");
        for(unsigned int ii = 0; ii < nameAttrs.length(); ii++)
        {
            myHoudiniNameAttribute.append(nameAttrs[ii]);
        }

        // get a list of unique instanced names, and compute the object indices that would
        // be passed to Maya instancer
        for(unsigned int i = 0; i< myInstancedObjectNames.length(); ++i)
        {
            bool duplicate = false;
            unsigned int j = 0;
            for(; j< myUniqueInstObjNames.length(); ++j)
            {
                if(myUniqueInstObjNames[j] == myInstancedObjectNames[i])
                {
                    duplicate = true;
                    break;
                }
            }
            if(!duplicate)
                myUniqueInstObjNames.append(myInstancedObjectNames[i]);
            myInstancedObjectIndices.append((int) j);
        }
    }
}

MIntArray
OutputInstancerObject::getInstancedObjIds()
{
    MIntArray ret;
    if(myObjectInfo.objectToInstanceId >= 0)
        ret.append(myObjectInfo.objectToInstanceId);
    return ret;
}

MStringArray
OutputInstancerObject::getUniqueInstObjNames()
{
    return myUniqueInstObjNames;
}

MStatus
//OutputInstancerObject::compute(const MPlug& plug, MDataBlock& data)
OutputInstancerObject::compute(
        MDataHandle& handle,
        bool &needToSyncOutputs
        )
{
    update();

    if(myGeoInfo.partCount <= 0)
        return MS::kFailure;

    if(myNeverBuilt || myGeoInfo.hasGeoChanged)
    {
        MDataHandle instancerDataHandle = handle.child(AssetNode::outputInstancerData);
        MArrayDataHandle instancedObjectNamesHandle = handle.child(AssetNode::outputInstancedObjectNames);
        MArrayDataHandle houdiniInstanceAttributeHandle = handle.child(AssetNode::outputHoudiniInstanceAttribute);
        MArrayDataHandle houdiniNameAttributeHandle = handle.child(AssetNode::outputHoudiniNameAttribute);
        MArrayDataHandle instanceTransformHandle = handle.child(AssetNode::outputInstanceTransform);

        //MDataHandle instHandle = data.outputValue(instancerDataPlug);
        MFnArrayAttrsData fnAAD;
        MObject instOutput = fnAAD.create();
        MVectorArray positions = fnAAD.vectorArray("position");
        MVectorArray rotations = fnAAD.vectorArray("rotation");
        MVectorArray scales = fnAAD.vectorArray("scale");
        MIntArray objectIndices = fnAAD.intArray("objectIndex");

        unsigned int size = myPartInfo.pointCount;
        HAPI_Transform * instTransforms = new HAPI_Transform[size];
        HAPI_GetInstanceTransforms(myAssetId, myObjectInfo.id, 0, HAPI_SRT, instTransforms, 0, size);

        MArrayDataBuilder houdiniInstanceAttributeBuilder = houdiniInstanceAttributeHandle.builder();
        MArrayDataBuilder houdiniNameAttributeBuilder = houdiniNameAttributeHandle.builder();
        MArrayDataBuilder instanceTransformBuilder = instanceTransformHandle.builder();

        for(unsigned int j=0; j<size; j++)
        {
            HAPI_Transform it = instTransforms[j];
            MVector p(it.position[0], it.position[1], it.position[2]);
            MVector r = MQuaternion(it.rotationQuaternion[0],
                    it.rotationQuaternion[1], it.rotationQuaternion[2],
                    it.rotationQuaternion[3]).asEulerRotation().asVector();
            MVector s(it.scale[0], it.scale[1], it.scale[2]);

            int objIndex = myInstancedObjectIndices[j];

            positions.append(p);
            rotations.append(r);
            scales.append(s);
            objectIndices.append(objIndex);

            if(myHoudiniInstanceAttribute.length() == size)
            {
                MDataHandle intanceAttributeHandle = houdiniInstanceAttributeBuilder.addElement(j);
                intanceAttributeHandle.set(myHoudiniInstanceAttribute[j]);
            }

            if(myHoudiniNameAttribute.length() == size)
            {
                MDataHandle nameAttributeHandle = houdiniNameAttributeBuilder.addElement(j);
                nameAttributeHandle.set(myHoudiniNameAttribute[j]);
            }

            MDataHandle transformHandle = instanceTransformBuilder.addElement(j);
            MDataHandle translateHandle = transformHandle.child(AssetNode::outputInstanceTranslate);
            MDataHandle rotateHandle = transformHandle.child(AssetNode::outputInstanceRotate);
            MDataHandle scaleHandle = transformHandle.child(AssetNode::outputInstanceScale);

            MDataHandle txHandle = translateHandle.child(AssetNode::outputInstanceTranslateX);
            txHandle.set(p.x);
            MDataHandle tyHandle = translateHandle.child(AssetNode::outputInstanceTranslateY);
            tyHandle.set(p.y);
            MDataHandle tzHandle = translateHandle.child(AssetNode::outputInstanceTranslateZ);
            tzHandle.set(p.z);

            MDataHandle rxHandle = rotateHandle.child(AssetNode::outputInstanceRotateX);
            rxHandle.set(r.x);
            MDataHandle ryHandle = rotateHandle.child(AssetNode::outputInstanceRotateY);
            ryHandle.set(r.y);
            MDataHandle rzHandle = rotateHandle.child(AssetNode::outputInstanceRotateZ);
            rzHandle.set(r.z);

            MDataHandle sxHandle = scaleHandle.child(AssetNode::outputInstanceScaleX);
            sxHandle.set(s.x);
            MDataHandle syHandle = scaleHandle.child(AssetNode::outputInstanceScaleY);
            syHandle.set(s.y);
            MDataHandle szHandle = scaleHandle.child(AssetNode::outputInstanceScaleZ);
            szHandle.set(s.z);
        }

        houdiniInstanceAttributeHandle.set(houdiniInstanceAttributeBuilder);
        houdiniInstanceAttributeHandle.setAllClean();

        houdiniNameAttributeHandle.set(houdiniNameAttributeBuilder);
        houdiniNameAttributeHandle.setAllClean();

        instanceTransformHandle.set(instanceTransformBuilder);
        instanceTransformHandle.setAllClean();

        delete[] instTransforms;

        instancerDataHandle.set(instOutput);

        MArrayDataBuilder builder = instancedObjectNamesHandle.builder();
        if(myObjectInfo.objectToInstanceId >= 0)
        {
            // instancing a single object
            OutputObject* objToInstance = myObjectControl->findObjectById(myObjectInfo.objectToInstanceId);
            MString name = objToInstance->getName();

            MDataHandle h = builder.addElement(0);
            h.set(name);
        } else
        {
            // instancing multiple objects
            for(unsigned int i=0; i< myUniqueInstObjNames.length(); i++)
            {
                MDataHandle h = builder.addElement(i);
                h.set(myUniqueInstObjNames[i]);
            }

            // clean up extra elements
            int builderSizeCheck = builder.elementCount();
            if(builderSizeCheck > (int) myUniqueInstObjNames.length())
            {
                for(int i= myUniqueInstObjNames.length(); i<builderSizeCheck; i++)
                {
                    builder.removeElement(i);
                }
            }
        }
        instancedObjectNamesHandle.set(builder);
        instancedObjectNamesHandle.setAllClean();

        handle.setClean();
        instancerDataHandle.setClean();
        //data.setClean(plug);
        //data.setClean(instancerDataPlug);

        myNeverBuilt = false;
    }

    return MS::kSuccess;
}
<commit_msg>Workaround a crash where we can't determine the object to instance<commit_after>#include <maya/MFnMesh.h>
#include <maya/MFnMeshData.h>
#include <maya/MEulerRotation.h>
#include <maya/MQuaternion.h>
#include <maya/MFnArrayAttrsData.h>
#include <maya/MArrayDataBuilder.h>

#include "Asset.h"
#include "AssetNode.h"
#include "OutputInstancerObject.h"
#include "util.h"

OutputInstancerObject::OutputInstancerObject(
        int assetId,
        int objectId,
        Asset* objectControl
        ) :
    OutputObject(
            assetId,
            objectId,
            objectControl
          ),
    myGeoInfo(HAPI_GeoInfo_Create())
{
    //update();
}

OutputInstancerObject::~OutputInstancerObject() {}

OutputObject::ObjectType
OutputInstancerObject::type()
{
    return OutputObject::OBJECT_TYPE_INSTANCER;
}

MStringArray
OutputInstancerObject::getAttributeStringData(HAPI_AttributeOwner owner, MString name)
{
    return Util::getAttributeStringData(myAssetId, myObjectId, 0, 0, owner, name);
}

void
OutputInstancerObject::update()
{
    OutputObject::update();

    try
    {
        HAPI_Result hstat = HAPI_RESULT_SUCCESS;
        hstat = HAPI_GetGeoInfo(myAssetId, myObjectId, 0, &myGeoInfo);
        Util::checkHAPIStatus(hstat);
    }
    catch (HAPIError& e)
    {
        cerr << e.what() << endl;
        return;
    }

    if(myNeverBuilt || myGeoInfo.hasGeoChanged)
    {
        // clear the arrays
        myInstancedObjectNames.clear();
        myInstancedObjectIndices.clear();
        myUniqueInstObjNames.clear();
        myHoudiniInstanceAttribute.clear();
        myHoudiniNameAttribute.clear();

        try
        {
            if(myGeoInfo.partCount <= 0)
                return;

            HAPI_Result hstat = HAPI_RESULT_SUCCESS;
            hstat = HAPI_GetPartInfo(myAssetId, myObjectId, 0, 0, &myPartInfo);
            Util::checkHAPIStatus(hstat);
        }
        catch (HAPIError& e)
        {
            cerr << e.what() << endl;
        }

        if(myObjectInfo.objectToInstanceId >= 0)
        {
            myInstancedObjectIndices = MIntArray(myPartInfo.pointCount, 0);
            return;
        }

        // fill array of size pointCount of instanced names
        MStringArray instanceAttrs = getAttributeStringData(HAPI_ATTROWNER_POINT, "instance");
        for(unsigned int i=0; i<instanceAttrs.length(); i++)
        {
            MStringArray splitObjName;
            instanceAttrs[i].split('/', splitObjName);
            myInstancedObjectNames.append(splitObjName[splitObjName.length()-1]);
            myHoudiniInstanceAttribute.append(instanceAttrs[i]);
        }

        MStringArray nameAttrs = getAttributeStringData(HAPI_ATTROWNER_POINT, "name");
        for(unsigned int ii = 0; ii < nameAttrs.length(); ii++)
        {
            myHoudiniNameAttribute.append(nameAttrs[ii]);
        }

        // get a list of unique instanced names, and compute the object indices that would
        // be passed to Maya instancer
        for(unsigned int i = 0; i< myInstancedObjectNames.length(); ++i)
        {
            bool duplicate = false;
            unsigned int j = 0;
            for(; j< myUniqueInstObjNames.length(); ++j)
            {
                if(myUniqueInstObjNames[j] == myInstancedObjectNames[i])
                {
                    duplicate = true;
                    break;
                }
            }
            if(!duplicate)
                myUniqueInstObjNames.append(myInstancedObjectNames[i]);
            myInstancedObjectIndices.append((int) j);
        }

        // Workaround a crash where we can't determine the object to instance.
        if(!myInstancedObjectNames.length())
        {
            myInstancedObjectIndices = MIntArray(myPartInfo.pointCount, -1);
        }
    }
}

MIntArray
OutputInstancerObject::getInstancedObjIds()
{
    MIntArray ret;
    if(myObjectInfo.objectToInstanceId >= 0)
        ret.append(myObjectInfo.objectToInstanceId);
    return ret;
}

MStringArray
OutputInstancerObject::getUniqueInstObjNames()
{
    return myUniqueInstObjNames;
}

MStatus
//OutputInstancerObject::compute(const MPlug& plug, MDataBlock& data)
OutputInstancerObject::compute(
        MDataHandle& handle,
        bool &needToSyncOutputs
        )
{
    update();

    if(myGeoInfo.partCount <= 0)
        return MS::kFailure;

    if(myNeverBuilt || myGeoInfo.hasGeoChanged)
    {
        MDataHandle instancerDataHandle = handle.child(AssetNode::outputInstancerData);
        MArrayDataHandle instancedObjectNamesHandle = handle.child(AssetNode::outputInstancedObjectNames);
        MArrayDataHandle houdiniInstanceAttributeHandle = handle.child(AssetNode::outputHoudiniInstanceAttribute);
        MArrayDataHandle houdiniNameAttributeHandle = handle.child(AssetNode::outputHoudiniNameAttribute);
        MArrayDataHandle instanceTransformHandle = handle.child(AssetNode::outputInstanceTransform);

        //MDataHandle instHandle = data.outputValue(instancerDataPlug);
        MFnArrayAttrsData fnAAD;
        MObject instOutput = fnAAD.create();
        MVectorArray positions = fnAAD.vectorArray("position");
        MVectorArray rotations = fnAAD.vectorArray("rotation");
        MVectorArray scales = fnAAD.vectorArray("scale");
        MIntArray objectIndices = fnAAD.intArray("objectIndex");

        unsigned int size = myPartInfo.pointCount;
        HAPI_Transform * instTransforms = new HAPI_Transform[size];
        HAPI_GetInstanceTransforms(myAssetId, myObjectInfo.id, 0, HAPI_SRT, instTransforms, 0, size);

        MArrayDataBuilder houdiniInstanceAttributeBuilder = houdiniInstanceAttributeHandle.builder();
        MArrayDataBuilder houdiniNameAttributeBuilder = houdiniNameAttributeHandle.builder();
        MArrayDataBuilder instanceTransformBuilder = instanceTransformHandle.builder();

        for(unsigned int j=0; j<size; j++)
        {
            HAPI_Transform it = instTransforms[j];
            MVector p(it.position[0], it.position[1], it.position[2]);
            MVector r = MQuaternion(it.rotationQuaternion[0],
                    it.rotationQuaternion[1], it.rotationQuaternion[2],
                    it.rotationQuaternion[3]).asEulerRotation().asVector();
            MVector s(it.scale[0], it.scale[1], it.scale[2]);

            int objIndex = myInstancedObjectIndices[j];

            positions.append(p);
            rotations.append(r);
            scales.append(s);
            objectIndices.append(objIndex);

            if(myHoudiniInstanceAttribute.length() == size)
            {
                MDataHandle intanceAttributeHandle = houdiniInstanceAttributeBuilder.addElement(j);
                intanceAttributeHandle.set(myHoudiniInstanceAttribute[j]);
            }

            if(myHoudiniNameAttribute.length() == size)
            {
                MDataHandle nameAttributeHandle = houdiniNameAttributeBuilder.addElement(j);
                nameAttributeHandle.set(myHoudiniNameAttribute[j]);
            }

            MDataHandle transformHandle = instanceTransformBuilder.addElement(j);
            MDataHandle translateHandle = transformHandle.child(AssetNode::outputInstanceTranslate);
            MDataHandle rotateHandle = transformHandle.child(AssetNode::outputInstanceRotate);
            MDataHandle scaleHandle = transformHandle.child(AssetNode::outputInstanceScale);

            MDataHandle txHandle = translateHandle.child(AssetNode::outputInstanceTranslateX);
            txHandle.set(p.x);
            MDataHandle tyHandle = translateHandle.child(AssetNode::outputInstanceTranslateY);
            tyHandle.set(p.y);
            MDataHandle tzHandle = translateHandle.child(AssetNode::outputInstanceTranslateZ);
            tzHandle.set(p.z);

            MDataHandle rxHandle = rotateHandle.child(AssetNode::outputInstanceRotateX);
            rxHandle.set(r.x);
            MDataHandle ryHandle = rotateHandle.child(AssetNode::outputInstanceRotateY);
            ryHandle.set(r.y);
            MDataHandle rzHandle = rotateHandle.child(AssetNode::outputInstanceRotateZ);
            rzHandle.set(r.z);

            MDataHandle sxHandle = scaleHandle.child(AssetNode::outputInstanceScaleX);
            sxHandle.set(s.x);
            MDataHandle syHandle = scaleHandle.child(AssetNode::outputInstanceScaleY);
            syHandle.set(s.y);
            MDataHandle szHandle = scaleHandle.child(AssetNode::outputInstanceScaleZ);
            szHandle.set(s.z);
        }

        houdiniInstanceAttributeHandle.set(houdiniInstanceAttributeBuilder);
        houdiniInstanceAttributeHandle.setAllClean();

        houdiniNameAttributeHandle.set(houdiniNameAttributeBuilder);
        houdiniNameAttributeHandle.setAllClean();

        instanceTransformHandle.set(instanceTransformBuilder);
        instanceTransformHandle.setAllClean();

        delete[] instTransforms;

        instancerDataHandle.set(instOutput);

        MArrayDataBuilder builder = instancedObjectNamesHandle.builder();
        if(myObjectInfo.objectToInstanceId >= 0)
        {
            // instancing a single object
            OutputObject* objToInstance = myObjectControl->findObjectById(myObjectInfo.objectToInstanceId);
            MString name = objToInstance->getName();

            MDataHandle h = builder.addElement(0);
            h.set(name);
        } else
        {
            // instancing multiple objects
            for(unsigned int i=0; i< myUniqueInstObjNames.length(); i++)
            {
                MDataHandle h = builder.addElement(i);
                h.set(myUniqueInstObjNames[i]);
            }

            // clean up extra elements
            int builderSizeCheck = builder.elementCount();
            if(builderSizeCheck > (int) myUniqueInstObjNames.length())
            {
                for(int i= myUniqueInstObjNames.length(); i<builderSizeCheck; i++)
                {
                    builder.removeElement(i);
                }
            }
        }
        instancedObjectNamesHandle.set(builder);
        instancedObjectNamesHandle.setAllClean();

        handle.setClean();
        instancerDataHandle.setClean();
        //data.setClean(plug);
        //data.setClean(instancerDataPlug);

        myNeverBuilt = false;
    }

    return MS::kSuccess;
}
<|endoftext|>


<commit_before>#include "sun.h"

//
// CONSTRUCTORS ////////////////////////////////////////////////////////////////
//

Sun::Sun()
    :   Planet( ":/texture/sun.jpg" )
{
    transform.setScale( 1.0f );

    planets["Mercury"] = new Mercury();
    planets["Venus"] = new Venus();
    planets["Earth"] = new Earth();
    planets["Mars"] = new Mars();
    planets["Jupiter"] = new Jupiter();
    planets["Saturn"] = new Saturn();
    planets["Uranus"] =  new Uranus();
    planets["Neptune"] = new Neptune();
    planets["Pluto"] = new Pluto();
}

//
// OVERRIDDEN FUNCTIONS
//

void Sun::initializeGL()
{
    Planet::initializeGL();

    for( QMap<QString, Planet*>::iterator iter = planets.begin();
        iter != planets.end(); iter++ )
    {
        (*iter)->initializeGL();
    }
}

void Sun::paintGL( Camera3D& camera, QMatrix4x4& projection )
{
    Planet::paintGL( camera, projection );

    // PAINT ALL PLANETS
    for( QMap<QString, Planet*>::iterator iter = planets.begin();
        iter != planets.end(); iter++ )
    {
        (*iter)->paintGL( camera, projection );
    }
}

void Sun::update()
{
    if( Planet::SCALED )
        updateScaled();
    else
        updateReal();

    // UPDATE ALL PLANETS
    for( QMap<QString, Planet*>::iterator iter = planets.begin();
        iter != planets.end(); iter++ )
    {
        (*iter)->update();
    }
}

void Sun::teardownGL()
{
    // DEALLOCATE ALL PLANETS
    for( QMap<QString, Planet*>::iterator iter = planets.begin();
        iter != planets.end(); iter++ )
    {
        (*iter)->teardownGL();
    }

    Planet::teardownGL();
}

//
// PRIVATE HELPER FUNCTIONS ////////////////////////////////////////////////////
//

void Sun::updateScaled()
{
    // SUN
    {
        transform.rotate( 1.0f, 0, 1, 0 );
    }

    // MERCURY
    {
        static float translationAngle = 0.0;
        translationAngle += .090;
        planets["Mercury"]->transform.setTranslation(
        transform.translation().x() + 3.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 3.0f * cos( translationAngle ) );
    }

    // VENUS
    {
        static float translationAngle = 0.0;
        translationAngle += .080;
        planets["Venus"]->transform.setTranslation(
        transform.translation().x() + 6.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 6.0f * cos( translationAngle ) );
    }

    // EARTH
    {
        static float translationAngle = 0.0;
        translationAngle += .070;
        planets["Earth"]->transform.setTranslation(
        transform.translation().x() + 9.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 9.0f * cos( translationAngle ) );
    }

    // MARS
    {
        static float translationAngle = 0.0;
        translationAngle += .060;
        planets["Mars"]->transform.setTranslation(
        transform.translation().x() + 12.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 12.0f * cos( translationAngle ) );
    }

    // JUPITER
    {
        static float translationAngle = 0.0;
        translationAngle += .050;
        planets["Jupiter"]->transform.setTranslation(
        transform.translation().x() + 15.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 15.0f * cos( translationAngle ) );
    }

    // SATURN
    {
        static float translationAngle = 0.0;
        translationAngle += .040;
        planets["Saturn"]->transform.setTranslation(
        transform.translation().x() + 18.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 18.0f * cos( translationAngle ) );
    }

    // URANUS
    {
        static float translationAngle = 0.0;
        translationAngle += .030;
        planets["Uranus"]->transform.setTranslation(
        transform.translation().x() + 21.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 21.0f * cos( translationAngle ) );
    }

    // NEPTUNE
    {
        static float translationAngle = 0.0;
        translationAngle += .020;
        planets["Neptune"]->transform.setTranslation(
        transform.translation().x() + 24.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 24.0f * cos( translationAngle ) );
    }

    // PLUTO
    {
        static float translationAngle = 0.0;
        translationAngle += .010;
        planets["Pluto"]->transform.setTranslation(
        transform.translation().x() + 27.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 27.0f * cos( translationAngle ) );
    }
}

void Sun::updateReal()
{

}<commit_msg>fized orbits<commit_after>#include "sun.h"

//
// CONSTRUCTORS ////////////////////////////////////////////////////////////////
//

Sun::Sun()
    :   Planet( ":/texture/sun.jpg" )
{
    transform.setScale( 1.0f );

    planets["Mercury"] = new Mercury();
    planets["Venus"] = new Venus();
    planets["Earth"] = new Earth();
    planets["Mars"] = new Mars();
    planets["Jupiter"] = new Jupiter();
    planets["Saturn"] = new Saturn();
    planets["Uranus"] =  new Uranus();
    planets["Neptune"] = new Neptune();
    planets["Pluto"] = new Pluto();
}

//
// OVERRIDDEN FUNCTIONS
//

void Sun::initializeGL()
{
    Planet::initializeGL();

    for( QMap<QString, Planet*>::iterator iter = planets.begin();
        iter != planets.end(); iter++ )
    {
        (*iter)->initializeGL();
    }
}

void Sun::paintGL( Camera3D& camera, QMatrix4x4& projection )
{
    Planet::paintGL( camera, projection );

    // PAINT ALL PLANETS
    for( QMap<QString, Planet*>::iterator iter = planets.begin();
        iter != planets.end(); iter++ )
    {
        (*iter)->paintGL( camera, projection );
    }
}

void Sun::update()
{
    if( Planet::SCALED )
        updateScaled();
    else
        updateReal();

    // UPDATE ALL PLANETS
    for( QMap<QString, Planet*>::iterator iter = planets.begin();
        iter != planets.end(); iter++ )
    {
        (*iter)->update();
    }
}

void Sun::teardownGL()
{
    // DEALLOCATE ALL PLANETS
    for( QMap<QString, Planet*>::iterator iter = planets.begin();
        iter != planets.end(); iter++ )
    {
        (*iter)->teardownGL();
    }

    Planet::teardownGL();
}

//
// PRIVATE HELPER FUNCTIONS ////////////////////////////////////////////////////
//

void Sun::updateScaled()
{
    // SUN
    {
        transform.rotate( 1.0f, 0, 1, 0 );
    }

    // MERCURY
    {
        static float translationAngle = 0.0;
        translationAngle += .0040;
        planets["Mercury"]->transform.setTranslation(
        transform.translation().x() + 3.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 3.0f * cos( translationAngle ) );
    }

    // VENUS
    {
        static float translationAngle = 0.0;
        translationAngle += .0070;
        planets["Venus"]->transform.setTranslation(
        transform.translation().x() + 6.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 6.0f * cos( translationAngle ) );
    }

    // EARTH
    {
        static float translationAngle = 0.0;
        translationAngle += .0090;
        planets["Earth"]->transform.setTranslation(
        transform.translation().x() + 9.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 9.0f * cos( translationAngle ) );
    }

    // MARS
    {
        static float translationAngle = 0.0;
        translationAngle += .00018;
        planets["Mars"]->transform.setTranslation(
        transform.translation().x() + 12.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 12.0f * cos( translationAngle ) );
    }

    // JUPITER
    {
        static float translationAngle = 0.0;
        translationAngle += .00050;
        planets["Jupiter"]->transform.setTranslation(
        transform.translation().x() + 15.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 15.0f * cos( translationAngle ) );
    }

    // SATURN
    {
        static float translationAngle = 0.0;
        translationAngle += .00070;
        planets["Saturn"]->transform.setTranslation(
        transform.translation().x() + 18.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 18.0f * cos( translationAngle ) );
    }

    // URANUS
    {
        static float translationAngle = 0.0;
        translationAngle += .00085;
        planets["Uranus"]->transform.setTranslation(
        transform.translation().x() + 21.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 21.0f * cos( translationAngle ) );
    }

    // NEPTUNE
    {
        static float translationAngle = 0.0;
        translationAngle += .00090;
        planets["Neptune"]->transform.setTranslation(
        transform.translation().x() + 24.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 24.0f * cos( translationAngle ) );
    }

    // PLUTO
    {
        static float translationAngle = 0.0;
        translationAngle += .000010;
        planets["Pluto"]->transform.setTranslation(
        transform.translation().x() + 27.0f * sin( translationAngle ),
        transform.translation().y(),
        transform.translation().z() + 27.0f * cos( translationAngle ) );
    }
}

void Sun::updateReal()
{

}<|endoftext|>


<commit_before>/*!
@file

@copyright Edouard Alligand and Joel Falcou 2015-2017
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_BRIGAND_FUNCTIONS_MISC_HPP
#define BOOST_BRIGAND_FUNCTIONS_MISC_HPP

#include <brigand/functions/misc/always.hpp>
#include <brigand/functions/misc/repeat.hpp>
#include <brigand/functions/misc/sizeof.hpp>
#endif
<commit_msg>Delete misc.hpp<commit_after><|endoftext|>


<commit_before>#include "multiVolumes.h"

namespace cura
{

void carveMultipleVolumes(std::vector<Slicer*> &volumes)
{
    //Go trough all the volumes, and remove the previous volume outlines from our own outline, so we never have overlapped areas.
    for (unsigned int volume_1_idx = 0; volume_1_idx < volumes.size(); volume_1_idx++)
    {
        Slicer& volume_1 = *volumes[volume_1_idx];
        if (volume_1.mesh->getSettingBoolean("infill_mesh"))
        {
            continue;
        }
        for (unsigned int volume_2_idx = 0; volume_2_idx < volume_1_idx; volume_2_idx++)
        {
            Slicer& volume_2 = *volumes[volume_2_idx];
            if (volume_2.mesh->getSettingBoolean("infill_mesh"))
            {
                continue;
            }
            if (!volume_1.mesh->getAABB().hit(volume_2.mesh->getAABB()))
            {
                continue;
            }
            for (unsigned int layerNr = 0; layerNr < volume_1.layers.size(); layerNr++)
            {
                SlicerLayer& layer1 = volume_1.layers[layerNr];
                SlicerLayer& layer2 = volume_2.layers[layerNr];
                layer1.polygons = layer1.polygons.difference(layer2.polygons);
            }
        }
    }
}

//Expand each layer a bit and then keep the extra overlapping parts that overlap with other volumes.
//This generates some overlap in dual extrusion, for better bonding in touching parts.
void generateMultipleVolumesOverlap(std::vector<Slicer*> &volumes)
{
    if (volumes.size() < 2)
    {
        return;
    }

    int offset_to_merge_other_merged_volumes = 20;
    for (Slicer* volume : volumes)
    {
        int overlap = volume->mesh->getSettingInMicrons("multiple_mesh_overlap");
        if (volume->mesh->getSettingBoolean("infill_mesh")
            || overlap == 0)
        {
            continue;
        }
        for (unsigned int layer_nr = 0; layer_nr < volume->layers.size(); layer_nr++)
        {
            Polygons all_other_volumes;
            for (Slicer* other_volume : volumes)
            {
                if (other_volume->mesh->getSettingBoolean("infill_mesh")
                    || !other_volume->mesh->getAABB().hit(volume->mesh->getAABB())
                )
                {
                    continue;
                }
                SlicerLayer& other_volume_layer = other_volume->layers[layer_nr];
                all_other_volumes = all_other_volumes.unionPolygons(other_volume_layer.polygons.offset(offset_to_merge_other_merged_volumes));
            }
            all_other_volumes = all_other_volumes.offset(-offset_to_merge_other_merged_volumes);

            SlicerLayer& volume_layer = volume->layers[layer_nr];
            volume_layer.polygons.unionPolygons(all_other_volumes.intersection(volume_layer.polygons.offset(overlap / 2)));
        }
    }
}

}//namespace cura
<commit_msg>fix: multiVolumesOverlap failed when two meshes are directly adjacent in the X direction (CURA-833)<commit_after>#include "multiVolumes.h"

namespace cura
{

void carveMultipleVolumes(std::vector<Slicer*> &volumes)
{
    //Go trough all the volumes, and remove the previous volume outlines from our own outline, so we never have overlapped areas.
    for (unsigned int volume_1_idx = 0; volume_1_idx < volumes.size(); volume_1_idx++)
    {
        Slicer& volume_1 = *volumes[volume_1_idx];
        if (volume_1.mesh->getSettingBoolean("infill_mesh"))
        {
            continue;
        }
        for (unsigned int volume_2_idx = 0; volume_2_idx < volume_1_idx; volume_2_idx++)
        {
            Slicer& volume_2 = *volumes[volume_2_idx];
            if (volume_2.mesh->getSettingBoolean("infill_mesh"))
            {
                continue;
            }
            if (!volume_1.mesh->getAABB().hit(volume_2.mesh->getAABB()))
            {
                continue;
            }
            for (unsigned int layerNr = 0; layerNr < volume_1.layers.size(); layerNr++)
            {
                SlicerLayer& layer1 = volume_1.layers[layerNr];
                SlicerLayer& layer2 = volume_2.layers[layerNr];
                layer1.polygons = layer1.polygons.difference(layer2.polygons);
            }
        }
    }
}

//Expand each layer a bit and then keep the extra overlapping parts that overlap with other volumes.
//This generates some overlap in dual extrusion, for better bonding in touching parts.
void generateMultipleVolumesOverlap(std::vector<Slicer*> &volumes)
{
    if (volumes.size() < 2)
    {
        return;
    }

    int offset_to_merge_other_merged_volumes = 20;
    for (Slicer* volume : volumes)
    {
        int overlap = volume->mesh->getSettingInMicrons("multiple_mesh_overlap");
        if (volume->mesh->getSettingBoolean("infill_mesh")
            || overlap == 0)
        {
            continue;
        }
        AABB3D aabb(volume->mesh->getAABB());
        aabb.expandXY(overlap); // expand to account for the case where two models and their bounding boxes are adjacent along the X or Y-direction
        for (unsigned int layer_nr = 0; layer_nr < volume->layers.size(); layer_nr++)
        {
            Polygons all_other_volumes;
            for (Slicer* other_volume : volumes)
            {
                if (other_volume->mesh->getSettingBoolean("infill_mesh")
                    || !other_volume->mesh->getAABB().hit(aabb)
                )
                {
                    continue;
                }
                SlicerLayer& other_volume_layer = other_volume->layers[layer_nr];
                all_other_volumes = all_other_volumes.unionPolygons(other_volume_layer.polygons.offset(offset_to_merge_other_merged_volumes));
            }
            all_other_volumes = all_other_volumes.offset(-offset_to_merge_other_merged_volumes);

            SlicerLayer& volume_layer = volume->layers[layer_nr];
            volume_layer.polygons.unionPolygons(all_other_volumes.intersection(volume_layer.polygons.offset(overlap / 2)));
        }
    }
}

}//namespace cura
<|endoftext|>


<commit_before>
/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkTArray.h"
#include "SkRandom.h"
#include "SkMatrix.h"
#include "SkBlurMaskFilter.h"
#include "SkGradientShader.h"
#include "SkBlurDrawLooper.h"
#include "SkRect.h"

namespace skiagm {

class OvalGM : public GM {
public:
    OvalGM() {
        this->setBGColor(0xFF000000);
        this->makePaints();
        this->makeMatrices();
    }

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return SkString("ovals");
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return make_isize(1200, 900);
    }

    void makePaints() {
        {
        // no AA
        SkPaint p;
        fPaints.push_back(p);
        }

        {
        // AA
        SkPaint p;
        p.setAntiAlias(true);
        fPaints.push_back(p);
        }

        {
        // AA with stroke style
        SkPaint p;
        p.setAntiAlias(true);
        p.setStyle(SkPaint::kStroke_Style);
        p.setStrokeWidth(SkIntToScalar(5));
        fPaints.push_back(p);
        }

        {
        // AA with stroke style, width = 0
        SkPaint p;
        p.setAntiAlias(true);
        p.setStyle(SkPaint::kStroke_Style);
        fPaints.push_back(p);
        }

        {
        // AA with stroke and fill style
        SkPaint p;
        p.setAntiAlias(true);
        p.setStyle(SkPaint::kStrokeAndFill_Style);
        p.setStrokeWidth(SkIntToScalar(3));
        fPaints.push_back(p);
        }
    }

    void makeMatrices() {
        {
        SkMatrix m;
        m.setIdentity();
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setScale(SkIntToScalar(3), SkIntToScalar(2));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setScale(SkIntToScalar(2), SkIntToScalar(2));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setScale(SkIntToScalar(1), SkIntToScalar(2));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setScale(SkIntToScalar(4), SkIntToScalar(1));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setRotate(SkIntToScalar(90));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setSkew(SkIntToScalar(2), SkIntToScalar(3));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setRotate(SkIntToScalar(60));
        fMatrices.push_back(m);
        }
    }

    SkColor genColor(SkMWCRandom* rand) {
        SkScalar hsv[3];
        hsv[0] = SkFloatToScalar(rand->nextRangeF(0.0f, 360.0f));
        hsv[1] = SkFloatToScalar(rand->nextRangeF(0.75f, 1.0f));
        hsv[2] = SkFloatToScalar(rand->nextRangeF(0.75f, 1.0f));

        return SkHSVToColor(hsv);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkMWCRandom rand(1);
        canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
        SkRect oval = SkRect::MakeLTRB(-20, -30, 20, 30);

        const SkScalar kXStart = 60.0f;
        const SkScalar kYStart = 80.0f;
        const int kXStep = 150;
        const int kYStep = 160;
        int maxX = fMatrices.count();

        SkPaint rectPaint;
        rectPaint.setAntiAlias(true);
        rectPaint.setStyle(SkPaint::kStroke_Style);
        rectPaint.setStrokeWidth(SkIntToScalar(0));
        rectPaint.setColor(SK_ColorLTGRAY);

        int testCount = 0;
        for (int i = 0; i < fPaints.count(); ++i) {
            for (int j = 0; j < fMatrices.count(); ++j) {
                canvas->save();
                SkMatrix mat = fMatrices[j];
                // position the oval, and make it at off-integer coords.
                mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) +
                                  SK_Scalar1 / 4,
                                  kYStart + SK_Scalar1 * kYStep * (testCount / maxX) +
                                  3 * SK_Scalar1 / 4);
                canvas->concat(mat);

                SkColor color = genColor(&rand);
                fPaints[i].setColor(color);

                canvas->drawRect(oval, rectPaint);
                canvas->drawOval(oval, fPaints[i]);

                canvas->restore();

                ++testCount;
            }
        }

        // special cases

        // non-scaled tall and skinny oval
        for (int i = 0; i < fPaints.count(); ++i) {
            SkRect oval = SkRect::MakeLTRB(-20, -60, 20, 60);
            canvas->save();
            // position the oval, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);

            canvas->drawRect(oval, rectPaint);
            canvas->drawOval(oval, fPaints[i]);
            canvas->restore();
        }

        // non-scaled wide and short oval
        for (int i = 0; i < fPaints.count(); ++i) {
            SkRect oval = SkRect::MakeLTRB(-80, -30, 80, 30);
            canvas->save();
            // position the oval, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);

            canvas->drawRect(oval, rectPaint);
            canvas->drawOval(oval, fPaints[i]);
            canvas->restore();
        }

        // super skinny oval
        for (int i = 0; i < fPaints.count(); ++i) {
            SkRect oval = SkRect::MakeLTRB(0, -60, 1, 60);
            canvas->save();
            // position the oval, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);

            canvas->drawOval(oval, fPaints[i]);
            canvas->restore();
        }

        // super short oval
        for (int i = 0; i < fPaints.count(); ++i) {
            SkRect oval = SkRect::MakeLTRB(-80, -1, 80, 0);
            canvas->save();
            // position the oval, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);

            canvas->drawOval(oval, fPaints[i]);
            canvas->restore();
        }

        // radial gradient
        SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
        SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
        SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
        SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(center,
                                                     SkIntToScalar(20),
                                                     colors,
                                                     pos,
                                                     SK_ARRAY_COUNT(colors),
                                                     SkShader::kClamp_TileMode));

        for (int i = 0; i < fPaints.count(); ++i) {
            canvas->save();
            // position the path, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);
            fPaints[i].setShader(shader);

            canvas->drawRect(oval, rectPaint);
            canvas->drawOval(oval, fPaints[i]);
            canvas->restore();
        }
    }

private:
    SkTArray<SkPaint> fPaints;
    SkTArray<SkMatrix> fMatrices;

    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static GM* MyFactory(void*) { return new OvalGM; }
static GMRegistry reg(MyFactory);

}
<commit_msg>Reset shader in ovals GM <commit_after>
/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkTArray.h"
#include "SkRandom.h"
#include "SkMatrix.h"
#include "SkBlurMaskFilter.h"
#include "SkGradientShader.h"
#include "SkBlurDrawLooper.h"
#include "SkRect.h"

namespace skiagm {

class OvalGM : public GM {
public:
    OvalGM() {
        this->setBGColor(0xFF000000);
        this->makePaints();
        this->makeMatrices();
    }

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return SkString("ovals");
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return make_isize(1200, 900);
    }

    void makePaints() {
        {
        // no AA
        SkPaint p;
        fPaints.push_back(p);
        }

        {
        // AA
        SkPaint p;
        p.setAntiAlias(true);
        fPaints.push_back(p);
        }

        {
        // AA with stroke style
        SkPaint p;
        p.setAntiAlias(true);
        p.setStyle(SkPaint::kStroke_Style);
        p.setStrokeWidth(SkIntToScalar(5));
        fPaints.push_back(p);
        }

        {
        // AA with stroke style, width = 0
        SkPaint p;
        p.setAntiAlias(true);
        p.setStyle(SkPaint::kStroke_Style);
        fPaints.push_back(p);
        }

        {
        // AA with stroke and fill style
        SkPaint p;
        p.setAntiAlias(true);
        p.setStyle(SkPaint::kStrokeAndFill_Style);
        p.setStrokeWidth(SkIntToScalar(3));
        fPaints.push_back(p);
        }
    }

    void makeMatrices() {
        {
        SkMatrix m;
        m.setIdentity();
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setScale(SkIntToScalar(3), SkIntToScalar(2));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setScale(SkIntToScalar(2), SkIntToScalar(2));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setScale(SkIntToScalar(1), SkIntToScalar(2));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setScale(SkIntToScalar(4), SkIntToScalar(1));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setRotate(SkIntToScalar(90));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setSkew(SkIntToScalar(2), SkIntToScalar(3));
        fMatrices.push_back(m);
        }

        {
        SkMatrix m;
        m.setRotate(SkIntToScalar(60));
        fMatrices.push_back(m);
        }
    }

    SkColor genColor(SkMWCRandom* rand) {
        SkScalar hsv[3];
        hsv[0] = SkFloatToScalar(rand->nextRangeF(0.0f, 360.0f));
        hsv[1] = SkFloatToScalar(rand->nextRangeF(0.75f, 1.0f));
        hsv[2] = SkFloatToScalar(rand->nextRangeF(0.75f, 1.0f));

        return SkHSVToColor(hsv);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkMWCRandom rand(1);
        canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
        SkRect oval = SkRect::MakeLTRB(-20, -30, 20, 30);

        const SkScalar kXStart = 60.0f;
        const SkScalar kYStart = 80.0f;
        const int kXStep = 150;
        const int kYStep = 160;
        int maxX = fMatrices.count();

        SkPaint rectPaint;
        rectPaint.setAntiAlias(true);
        rectPaint.setStyle(SkPaint::kStroke_Style);
        rectPaint.setStrokeWidth(SkIntToScalar(0));
        rectPaint.setColor(SK_ColorLTGRAY);

        int testCount = 0;
        for (int i = 0; i < fPaints.count(); ++i) {
            for (int j = 0; j < fMatrices.count(); ++j) {
                canvas->save();
                SkMatrix mat = fMatrices[j];
                // position the oval, and make it at off-integer coords.
                mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) +
                                  SK_Scalar1 / 4,
                                  kYStart + SK_Scalar1 * kYStep * (testCount / maxX) +
                                  3 * SK_Scalar1 / 4);
                canvas->concat(mat);

                SkColor color = genColor(&rand);
                fPaints[i].setColor(color);

                canvas->drawRect(oval, rectPaint);
                canvas->drawOval(oval, fPaints[i]);

                canvas->restore();

                ++testCount;
            }
        }

        // special cases

        // non-scaled tall and skinny oval
        for (int i = 0; i < fPaints.count(); ++i) {
            SkRect oval = SkRect::MakeLTRB(-20, -60, 20, 60);
            canvas->save();
            // position the oval, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);

            canvas->drawRect(oval, rectPaint);
            canvas->drawOval(oval, fPaints[i]);
            canvas->restore();
        }

        // non-scaled wide and short oval
        for (int i = 0; i < fPaints.count(); ++i) {
            SkRect oval = SkRect::MakeLTRB(-80, -30, 80, 30);
            canvas->save();
            // position the oval, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);

            canvas->drawRect(oval, rectPaint);
            canvas->drawOval(oval, fPaints[i]);
            canvas->restore();
        }

        // super skinny oval
        for (int i = 0; i < fPaints.count(); ++i) {
            SkRect oval = SkRect::MakeLTRB(0, -60, 1, 60);
            canvas->save();
            // position the oval, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);

            canvas->drawOval(oval, fPaints[i]);
            canvas->restore();
        }

        // super short oval
        for (int i = 0; i < fPaints.count(); ++i) {
            SkRect oval = SkRect::MakeLTRB(-80, -1, 80, 0);
            canvas->save();
            // position the oval, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);

            canvas->drawOval(oval, fPaints[i]);
            canvas->restore();
        }

        // radial gradient
        SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
        SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
        SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
        SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(center,
                                                     SkIntToScalar(20),
                                                     colors,
                                                     pos,
                                                     SK_ARRAY_COUNT(colors),
                                                     SkShader::kClamp_TileMode));

        for (int i = 0; i < fPaints.count(); ++i) {
            canvas->save();
            // position the path, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = genColor(&rand);
            fPaints[i].setColor(color);
            fPaints[i].setShader(shader);

            canvas->drawRect(oval, rectPaint);
            canvas->drawOval(oval, fPaints[i]);

            fPaints[i].setShader(NULL);

            canvas->restore();
        }
    }

private:
    SkTArray<SkPaint> fPaints;
    SkTArray<SkMatrix> fMatrices;

    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static GM* MyFactory(void*) { return new OvalGM; }
static GMRegistry reg(MyFactory);

}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/tools/test_shell/test_navigation_controller.h"

#include "base/logging.h"
#include "webkit/glue/webhistoryitem.h"
#include "webkit/tools/test_shell/test_shell.h"

// ----------------------------------------------------------------------------
// TestNavigationEntry

TestNavigationEntry::TestNavigationEntry()
    : page_id_(-1) {
}

TestNavigationEntry::TestNavigationEntry(int page_id,
                                         const GURL& url,
                                         const std::wstring& title,
                                         const std::wstring& target_frame)
    : page_id_(page_id),
      url_(url),
      title_(title),
      target_frame_(target_frame) {
}

TestNavigationEntry::~TestNavigationEntry() {
}

void TestNavigationEntry::SetContentState(const std::string& state) {
  cached_history_item_ = NULL;  // invalidate our cached item
  state_ = state;
}

WebHistoryItem* TestNavigationEntry::GetHistoryItem() const {
  // TODO(port): temporary hack to get a basic test shell executable going.
#if !defined(OS_LINUX)
  if (!cached_history_item_) {
    TestShellExtraRequestData* extra_data =
        new TestShellExtraRequestData(GetPageID());
    cached_history_item_ =
        WebHistoryItem::Create(GetURL(), GetTitle(), GetContentState(),
                               extra_data);
  }
#endif
  return cached_history_item_;
}

// ----------------------------------------------------------------------------
// TestNavigationController

TestNavigationController::TestNavigationController(TestShell* shell)
    : pending_entry_(NULL),
      last_committed_entry_index_(-1),
      pending_entry_index_(-1),
      shell_(shell),
      max_page_id_(-1) {
}

TestNavigationController::~TestNavigationController() {
  DiscardPendingEntry();
}

void TestNavigationController::Reset() {
  entries_.clear();
  DiscardPendingEntry();

  last_committed_entry_index_ = -1;
}

void TestNavigationController::Reload() {
  // Base the navigation on where we are now...
  int current_index = GetCurrentEntryIndex();

  // If we are no where, then we can't reload.  TODO(darin): We should add a
  // CanReload method.
  if (current_index == -1)
    return;

  DiscardPendingEntry();

  pending_entry_index_ = current_index;
  NavigateToPendingEntry(true);
}

void TestNavigationController::GoToOffset(int offset) {
  int index = last_committed_entry_index_ + offset;
  if (index < 0 || index >= GetEntryCount())
    return;

  GoToIndex(index);
}

void TestNavigationController::GoToIndex(int index) {
  DCHECK(index >= 0);
  DCHECK(index < static_cast<int>(entries_.size()));

  DiscardPendingEntry();

  pending_entry_index_ = index;
  NavigateToPendingEntry(false);
}

void TestNavigationController::LoadEntry(TestNavigationEntry* entry) {
  // When navigating to a new page, we don't know for sure if we will actually
  // end up leaving the current page.  The new page load could for example
  // result in a download or a 'no content' response (e.g., a mailto: URL).
  DiscardPendingEntry();
  pending_entry_ = entry;
  NavigateToPendingEntry(false);
}

TestNavigationEntry* TestNavigationController::GetLastCommittedEntry() const {
  if (last_committed_entry_index_ == -1)
    return NULL;
  return entries_[last_committed_entry_index_].get();
}

TestNavigationEntry* TestNavigationController::GetActiveEntry() const {
  TestNavigationEntry* entry = pending_entry_;
  if (!entry)
    entry = GetLastCommittedEntry();
  return entry;
}

int TestNavigationController::GetCurrentEntryIndex() const {
  if (pending_entry_index_ != -1)
    return pending_entry_index_;
  return last_committed_entry_index_;
}

TestNavigationEntry* TestNavigationController::GetEntryAtOffset(
    int offset) const {
  int index = last_committed_entry_index_ + offset;
  if (index < 0 || index >= GetEntryCount())
    return NULL;

  return entries_[index].get();
}

TestNavigationEntry* TestNavigationController::GetEntryWithPageID(
    int32 page_id) const {
  int index = GetEntryIndexWithPageID(page_id);
  return (index != -1) ? entries_[index].get() : NULL;
}

void TestNavigationController::DidNavigateToEntry(TestNavigationEntry* entry) {
  // If the entry is that of a page with PageID larger than any this Tab has
  // seen before, then consider it a new navigation.
  if (entry->GetPageID() > GetMaxPageID()) {
    InsertEntry(entry);
    return;
  }

  // Otherwise, we just need to update an existing entry with matching PageID.
  // If the existing entry corresponds to the entry which is pending, then we
  // must update the current entry index accordingly.  When navigating to the
  // same URL, a new PageID is not created.

  int existing_entry_index = GetEntryIndexWithPageID(entry->GetPageID());
  TestNavigationEntry* existing_entry = (existing_entry_index != -1) ?
      entries_[existing_entry_index].get() : NULL;
  if (!existing_entry) {
    // No existing entry, then simply ignore this navigation!
    DLOG(WARNING) << "ignoring navigation for page: " << entry->GetPageID();
  } else if (existing_entry == pending_entry_) {
    // The given entry might provide a new URL... e.g., navigating back to a
    // page in session history could have resulted in a new client redirect.
    existing_entry->SetURL(entry->GetURL());
    existing_entry->SetContentState(entry->GetContentState());
    last_committed_entry_index_ = pending_entry_index_;
    pending_entry_index_ = -1;
    pending_entry_ = NULL;
  } else if (pending_entry_ && pending_entry_->GetPageID() == -1 &&
             pending_entry_->GetURL() == existing_entry->GetURL()) {
    // Not a new navigation
    DiscardPendingEntry();
  } else {
    // The given entry might provide a new URL... e.g., navigating to a page
    // might result in a client redirect, which should override the URL of the
    // existing entry.
    existing_entry->SetURL(entry->GetURL());
    existing_entry->SetContentState(entry->GetContentState());

    // The navigation could have been issued by the renderer, so be sure that
    // we update our current index.
    last_committed_entry_index_ = existing_entry_index;
  }

  delete entry;
  UpdateMaxPageID();
}

void TestNavigationController::DiscardPendingEntry() {
  if (pending_entry_index_ == -1)
    delete pending_entry_;
  pending_entry_ = NULL;
  pending_entry_index_ = -1;
}

void TestNavigationController::InsertEntry(TestNavigationEntry* entry) {
  DiscardPendingEntry();

  // Prune any entry which are in front of the current entry
  int current_size = static_cast<int>(entries_.size());
  if (current_size > 0) {
    while (last_committed_entry_index_ < (current_size - 1)) {
      entries_.pop_back();
      current_size--;
    }
  }

  entries_.push_back(linked_ptr<TestNavigationEntry>(entry));
  last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1;
  UpdateMaxPageID();
}

int TestNavigationController::GetEntryIndexWithPageID(int32 page_id) const {
  for (int i = static_cast<int>(entries_.size())-1; i >= 0; --i) {
    if (entries_[i]->GetPageID() == page_id)
      return i;
  }
  return -1;
}

void TestNavigationController::NavigateToPendingEntry(bool reload) {
  // For session history navigations only the pending_entry_index_ is set.
  if (!pending_entry_) {
    DCHECK(pending_entry_index_ != -1);
    pending_entry_ = entries_[pending_entry_index_].get();
  }

  if (shell_->Navigate(*pending_entry_, reload)) {
    // Note: this is redundant if navigation completed synchronously because
    // DidNavigateToEntry call this as well.
    UpdateMaxPageID();
  } else {
    DiscardPendingEntry();
  }
}

void TestNavigationController::UpdateMaxPageID() {
  TestNavigationEntry* entry = GetActiveEntry();
  if (entry)
    max_page_id_ = std::max(max_page_id_, entry->GetPageID());
}
<commit_msg>Fix a bunch of linux test shell crashes by removing an old stub out hack.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/tools/test_shell/test_navigation_controller.h"

#include "base/logging.h"
#include "webkit/glue/webhistoryitem.h"
#include "webkit/tools/test_shell/test_shell.h"

// ----------------------------------------------------------------------------
// TestNavigationEntry

TestNavigationEntry::TestNavigationEntry()
    : page_id_(-1) {
}

TestNavigationEntry::TestNavigationEntry(int page_id,
                                         const GURL& url,
                                         const std::wstring& title,
                                         const std::wstring& target_frame)
    : page_id_(page_id),
      url_(url),
      title_(title),
      target_frame_(target_frame) {
}

TestNavigationEntry::~TestNavigationEntry() {
}

void TestNavigationEntry::SetContentState(const std::string& state) {
  cached_history_item_ = NULL;  // invalidate our cached item
  state_ = state;
}

WebHistoryItem* TestNavigationEntry::GetHistoryItem() const {
  if (!cached_history_item_) {
    TestShellExtraRequestData* extra_data =
        new TestShellExtraRequestData(GetPageID());
    cached_history_item_ =
        WebHistoryItem::Create(GetURL(), GetTitle(), GetContentState(),
                               extra_data);
  }
  return cached_history_item_;
}

// ----------------------------------------------------------------------------
// TestNavigationController

TestNavigationController::TestNavigationController(TestShell* shell)
    : pending_entry_(NULL),
      last_committed_entry_index_(-1),
      pending_entry_index_(-1),
      shell_(shell),
      max_page_id_(-1) {
}

TestNavigationController::~TestNavigationController() {
  DiscardPendingEntry();
}

void TestNavigationController::Reset() {
  entries_.clear();
  DiscardPendingEntry();

  last_committed_entry_index_ = -1;
}

void TestNavigationController::Reload() {
  // Base the navigation on where we are now...
  int current_index = GetCurrentEntryIndex();

  // If we are no where, then we can't reload.  TODO(darin): We should add a
  // CanReload method.
  if (current_index == -1)
    return;

  DiscardPendingEntry();

  pending_entry_index_ = current_index;
  NavigateToPendingEntry(true);
}

void TestNavigationController::GoToOffset(int offset) {
  int index = last_committed_entry_index_ + offset;
  if (index < 0 || index >= GetEntryCount())
    return;

  GoToIndex(index);
}

void TestNavigationController::GoToIndex(int index) {
  DCHECK(index >= 0);
  DCHECK(index < static_cast<int>(entries_.size()));

  DiscardPendingEntry();

  pending_entry_index_ = index;
  NavigateToPendingEntry(false);
}

void TestNavigationController::LoadEntry(TestNavigationEntry* entry) {
  // When navigating to a new page, we don't know for sure if we will actually
  // end up leaving the current page.  The new page load could for example
  // result in a download or a 'no content' response (e.g., a mailto: URL).
  DiscardPendingEntry();
  pending_entry_ = entry;
  NavigateToPendingEntry(false);
}

TestNavigationEntry* TestNavigationController::GetLastCommittedEntry() const {
  if (last_committed_entry_index_ == -1)
    return NULL;
  return entries_[last_committed_entry_index_].get();
}

TestNavigationEntry* TestNavigationController::GetActiveEntry() const {
  TestNavigationEntry* entry = pending_entry_;
  if (!entry)
    entry = GetLastCommittedEntry();
  return entry;
}

int TestNavigationController::GetCurrentEntryIndex() const {
  if (pending_entry_index_ != -1)
    return pending_entry_index_;
  return last_committed_entry_index_;
}

TestNavigationEntry* TestNavigationController::GetEntryAtOffset(
    int offset) const {
  int index = last_committed_entry_index_ + offset;
  if (index < 0 || index >= GetEntryCount())
    return NULL;

  return entries_[index].get();
}

TestNavigationEntry* TestNavigationController::GetEntryWithPageID(
    int32 page_id) const {
  int index = GetEntryIndexWithPageID(page_id);
  return (index != -1) ? entries_[index].get() : NULL;
}

void TestNavigationController::DidNavigateToEntry(TestNavigationEntry* entry) {
  // If the entry is that of a page with PageID larger than any this Tab has
  // seen before, then consider it a new navigation.
  if (entry->GetPageID() > GetMaxPageID()) {
    InsertEntry(entry);
    return;
  }

  // Otherwise, we just need to update an existing entry with matching PageID.
  // If the existing entry corresponds to the entry which is pending, then we
  // must update the current entry index accordingly.  When navigating to the
  // same URL, a new PageID is not created.

  int existing_entry_index = GetEntryIndexWithPageID(entry->GetPageID());
  TestNavigationEntry* existing_entry = (existing_entry_index != -1) ?
      entries_[existing_entry_index].get() : NULL;
  if (!existing_entry) {
    // No existing entry, then simply ignore this navigation!
    DLOG(WARNING) << "ignoring navigation for page: " << entry->GetPageID();
  } else if (existing_entry == pending_entry_) {
    // The given entry might provide a new URL... e.g., navigating back to a
    // page in session history could have resulted in a new client redirect.
    existing_entry->SetURL(entry->GetURL());
    existing_entry->SetContentState(entry->GetContentState());
    last_committed_entry_index_ = pending_entry_index_;
    pending_entry_index_ = -1;
    pending_entry_ = NULL;
  } else if (pending_entry_ && pending_entry_->GetPageID() == -1 &&
             pending_entry_->GetURL() == existing_entry->GetURL()) {
    // Not a new navigation
    DiscardPendingEntry();
  } else {
    // The given entry might provide a new URL... e.g., navigating to a page
    // might result in a client redirect, which should override the URL of the
    // existing entry.
    existing_entry->SetURL(entry->GetURL());
    existing_entry->SetContentState(entry->GetContentState());

    // The navigation could have been issued by the renderer, so be sure that
    // we update our current index.
    last_committed_entry_index_ = existing_entry_index;
  }

  delete entry;
  UpdateMaxPageID();
}

void TestNavigationController::DiscardPendingEntry() {
  if (pending_entry_index_ == -1)
    delete pending_entry_;
  pending_entry_ = NULL;
  pending_entry_index_ = -1;
}

void TestNavigationController::InsertEntry(TestNavigationEntry* entry) {
  DiscardPendingEntry();

  // Prune any entry which are in front of the current entry
  int current_size = static_cast<int>(entries_.size());
  if (current_size > 0) {
    while (last_committed_entry_index_ < (current_size - 1)) {
      entries_.pop_back();
      current_size--;
    }
  }

  entries_.push_back(linked_ptr<TestNavigationEntry>(entry));
  last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1;
  UpdateMaxPageID();
}

int TestNavigationController::GetEntryIndexWithPageID(int32 page_id) const {
  for (int i = static_cast<int>(entries_.size())-1; i >= 0; --i) {
    if (entries_[i]->GetPageID() == page_id)
      return i;
  }
  return -1;
}

void TestNavigationController::NavigateToPendingEntry(bool reload) {
  // For session history navigations only the pending_entry_index_ is set.
  if (!pending_entry_) {
    DCHECK(pending_entry_index_ != -1);
    pending_entry_ = entries_[pending_entry_index_].get();
  }

  if (shell_->Navigate(*pending_entry_, reload)) {
    // Note: this is redundant if navigation completed synchronously because
    // DidNavigateToEntry call this as well.
    UpdateMaxPageID();
  } else {
    DiscardPendingEntry();
  }
}

void TestNavigationController::UpdateMaxPageID() {
  TestNavigationEntry* entry = GetActiveEntry();
  if (entry)
    max_page_id_ = std::max(max_page_id_, entry->GetPageID());
}
<|endoftext|>


<commit_before>/*-------------------------------
PASA LA CALCULADORA
Autores:
Jaime Sevilla Molina
Victor Gonzalez
Fecha
2014/11
Version: 2.0
---------------------------------*/

//BIBLIOTECAS
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include <fstream>
#include <iomanip>

using namespace std;

//TIPOS PROPIOS
typedef enum tJugador
{
	Nadie,
	Jugador,
	Automata
};

//FUNCIONES
//FUNCIONES DE JUEGO

string saludar ();

//Dependiendo de quien gane, la despedida sera distinta
void despedirse (tJugador ganador, string nombre);

//Muestra un menu que permite al jugador jugar, salir, o ver las reglas del juego
int menu();

//Muestra las instrucciones del juego, siempre que su archivo no contenga errores
bool acerca();

//Actualiza las estadisticas
bool actualizar_stats(tJugador ganador);

//Muestra las estadisticas
bool stats();

//Anota el numero de partidas ganadas y perdidas del jugador
bool stats(int ganadas, int perdidas);

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora();

//Decide aleatoriamente quien empieza.
tJugador quienEmpieza();

//Devuelve true si nuevo esta en la misma fila que ultimo
bool mismaFila(int ultimo, int nuevo);

//Devuelve true si nuevo esta en la misma columna que ultimo
bool mismaColumna(int ultimo, int nuevo);

//Devuelve true si nuevo cumple las reglas del juego con respecto a ultimo
//Si ultimo == 0, este es el primer digito de la partida, y devuelve true
bool digitoValido(int ultimo, int nuevo);

//FUNCIONES DE IA NIVEL 1
//Devuelve un digito del 1 al 9
int digitoAleatorio();

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo);

//FUNCIONES DE JUGADOR
//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona();

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo);

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n);

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo);

/* Las funciones a continuacion se implementaran en un futuro
//FUNCIONES DE INFORME
//Actualiza el archivo informePC.txt con los tres argumentos. En caso de no encontrar
//el archivo, lo crea y devuelve false; en otro caso devuelve true.
bool actInforme(int jugadas, int ganadas, int abandonos);

//FUNCIONES DE DIFICULTAD AVANZADA
int botDificil(int ultimo);

-----------------------------------------------------------------------------------*/

int main()
{
	tJugador ganador;
	int opcion;

	string nombre = saludar();
	//Bucle Menu
	do
	{
		opcion = menu();
		if(opcion == 1)
		{
			ganador = pasaCalculadora();
			actualizar_stats(ganador);
			despedirse(ganador, nombre);
		}
		else if(opcion == 2) acerca();
		else if(opcion == 3) stats();
	}
	while(opcion != 0);

	cout << "Hasta la proxima " << nombre << "(pulsa enter)";
	cin;

	return 0;
}

//Saluda al jugador y le pregunta su nombre
string saludar()
{
	string nombre;
	cout << "Bienvenido a Pasa la calculadora!" << endl;
	cout << "Como te llamas? ";
	cin >> nombre;
	cout << "Hola " << nombre << endl << endl;
	return nombre;
}

//Se despide del jugador, la despedida varia segun gane el jugador, el automata o ninguno de ellos (el jugador abandone)
void despedirse(tJugador ganador, string nombre)
{
	int ganadas = 0, perdidas = 0;
	if (ganador == Nadie){
		cout << "Abandonas, " << nombre << "? Ohhh..." << endl << endl;
	}
	else if (ganador == Jugador){
		cout << "Enhorabuena " << nombre << ", has ganado!" << endl << endl;
	}
	else /*if (ganador == Automata)*/{
		cout << "Lo siento " << nombre << ", he ganado" << endl << endl;
	}
}

//Proporciona al jugador la posibilidad de jugar, ver las instrucciones del juego o salir.
int menu()
{
	int seleccionar = -1; //Error flag
	cout << "1 - Jugar" << endl;
	cout << "2 - Acerca de" << endl;
	cout << "3 - Estadísticas" << endl;
	cout << "0 - Salir" << endl;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> seleccionar;

		if(cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (seleccionar < 0 || seleccionar > 3)
		{
			cout << "Error! Introduce un digito entre 0 y 3" << endl;
			seleccionar = -1;
		}

	}
	while (seleccionar == -1);

	return seleccionar;
}

//Muestra el archivo "acerca.txt" siempre que este no contenga errores
bool acerca()
{
	bool ok;
	ifstream acerca;
	char c;

	acerca.open("acerca.txt");

	if(acerca.is_open())
	{
		acerca.get(c); //Lee el primer caracter

		while(!acerca.fail()) //Mientras la lectura no falle
		{
			cout << c;
			acerca.get(c); //Lee el siguiente caracter
		}

		ok = true;
		acerca.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'acerca.txt' no existe" << endl;
	}

	return ok;
}

//Actualiza las estadisticas
bool actualizar_stats(tJugador ganador)
{
	bool ok;
	int ganadas, perdidas, abandonadas;
	ifstream stats;
	ofstream actualizar;

	stats.open("stats.txt");
	if(stats.is_open())
	{
		stats >> ganadas;
		stats >> perdidas;
		stats >> abandonadas;

		ok = true;
	}
	else
	{
		ganadas = 0;
		perdidas = 0;
		abandonadas = 0;

		ok = false;
	}

	if(ganador == Jugador) ganadas += 1;
	else if(ganador == Automata) perdidas += 1;
	else if(ganador == Nadie) abandonadas += 1;

	stats.close();

	actualizar.open("stats.txt")

	actualizar << ganadas << endl;
	actualizar << perdidas << endl;
	actualizar << abandonadas << endl;

	actualizar.close();
	return ok;
}

//Muestra las estadisticas
void stats()
{
	ifstream stats;
	int ganadas, perdidas, abandonadas;

	stats.open("stats.txt")

	stats >> ganadas;
	stats >> perdidas;
	stats >> abandonadas;

	cout << "Partidas jugadas: " << (ganadas+perdidas+abandonadas) << endl;
	cout << "	Partidas ganadas: " << ganadas << endl;
	cout << "	Partidas perdidas: " << perdidas << endl;
	cout << "	Partidas abandonadas: " << abandonadas << endl;

	stats.close();
}

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora()
{
	//Variables
	tJugador turno;
	int total = 0, ultimoDigito = 0;
	const int META=31;
		//Inicializar partida
	srand(time(NULL));//Semilla
	turno = quienEmpieza();

	//Bucle de juego
	do
	{
		//Turno jugador
		if (turno == Jugador)
		{
			ultimoDigito = digitoPersona(ultimoDigito);
			turno = Automata;
		}
		//Turno bot
		else /*if (turno == Automata)*/
		{
			ultimoDigito = digitoAutomata(ultimoDigito);
			turno = Jugador;
		}
		total += ultimoDigito;
		cout << "Total = " << total << endl;
	}
	while ((total < META) && (ultimoDigito != 0));

	if (ultimoDigito == 0) turno = Nadie;
	//Si el jugador abandona, no gana nadie

	return turno;
}

//Decide aleatoriamente quien empieza la partida, si el automata o el jugador
tJugador quienEmpieza()
{
	if (rand() % 2)
	{
		cout << "Tu empiezas" << endl;
		return Jugador;
	}
	else
	{
		cout << "Empiezo yo" << endl;
		return Automata;
	}
}

//Define que numeros se encuentran en la misma fila que el ultimo pulsado
bool mismaFila(int ultimo, int nuevo)
{
	int filaUltimo, filaNuevo;
	filaUltimo = ((ultimo - 1)/3);
	filaNuevo = ((nuevo - 1)/3);
	return (filaUltimo) == (filaNuevo);
}

//Define que numeros se encuentran en la misma columna que el ultimo
bool mismaColumna(int ultimo, int nuevo)
{
	int columnaUltimo, columnaNuevo;
	columnaUltimo = (ultimo % 3);
	columnaNuevo = (nuevo % 3);
	return columnaUltimo == columnaNuevo;
}

//Determina que digitos se pueden pulsar en funcion de las reglas del juego
bool digitoValido(int ultimo, int nuevo)  //hay un bug
{
	if (ultimo == 0) return true;//Si es el primer turno, todos los numeros valen

	return ((mismaFila(ultimo, nuevo))||(mismaColumna(ultimo, nuevo)))&&(ultimo!=nuevo);
}

//Genera un digito aleatorio
int digitoAleatorio()
{
	return (rand() % 9) + 1;
}

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo)
{
	int digito;

	do
	{
	digito = digitoAleatorio();
	}
	while (!digitoValido(ultimo, digito));

	cout << "Elijo el numero " << digito << endl;

	return digito;
}

//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona()
{
	int digito = -1;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> digito;

		if (cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (digito < 0 || digito > 9)
		{
		cout << "Error! Introduce un digito entre 0 y 9" << endl;
		digito = -1;
		}

	}
	while (digito == -1);

	return digito;
}

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo)
{
	int digito = -1; //-1 es mi error flag

	mostrarCalculadora(ultimo);

	do
	{
		digito = digitoPersona();
		if (!digitoValido(ultimo, digito))
		{
			cout << "Error! El digito debe estar en la misma fila y columna que el ultimo" << endl;
			digito = -1;
		}
	}
	while (digito == -1);

	cout << "Has elegido el " << digito << endl;

	return digito;
}

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n)
{
	if(digitoValido(ultimo, n))
	{
		return char (n+int('0'));

	}
	else
	{
		return ' ';
	}
}

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo)
{
	for (int i = 7; i<10; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 4; i<7; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 1; i<4; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
}
<commit_msg>añadida notificacion el crear el archivo stats.txt<commit_after>/*-------------------------------
PASA LA CALCULADORA
Autores:
Jaime Sevilla Molina
Victor Gonzalez
Fecha
2014/11
Version: 2.0
---------------------------------*/

//BIBLIOTECAS
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <system>

using namespace std;

//TIPOS PROPIOS
typedef enum tJugador
{
	Nadie,
	Jugador,
	Automata
};

//FUNCIONES
//FUNCIONES DE JUEGO

string saludar ();

//Dependiendo de quien gane, la despedida sera distinta
void despedirse (tJugador ganador, string nombre);

//Muestra un menu que permite al jugador jugar, salir, o ver las reglas del juego
int menu();

//Muestra las instrucciones del juego, siempre que su archivo no contenga errores
bool acerca();

//Actualiza las estadisticas
bool actualizar_stats(tJugador ganador);

//Muestra las estadisticas
bool stats();

//Anota el numero de partidas ganadas y perdidas del jugador
bool stats(int ganadas, int perdidas);

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora();

//Decide aleatoriamente quien empieza.
tJugador quienEmpieza();

//Devuelve true si nuevo esta en la misma fila que ultimo
bool mismaFila(int ultimo, int nuevo);

//Devuelve true si nuevo esta en la misma columna que ultimo
bool mismaColumna(int ultimo, int nuevo);

//Devuelve true si nuevo cumple las reglas del juego con respecto a ultimo
//Si ultimo == 0, este es el primer digito de la partida, y devuelve true
bool digitoValido(int ultimo, int nuevo);

//FUNCIONES DE IA NIVEL 1
//Devuelve un digito del 1 al 9
int digitoAleatorio();

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo);

//FUNCIONES DE JUGADOR
//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona();

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo);

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n);

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo);

/* Las funciones a continuacion se implementaran en un futuro
//FUNCIONES DE INFORME
//Actualiza el archivo informePC.txt con los tres argumentos. En caso de no encontrar
//el archivo, lo crea y devuelve false; en otro caso devuelve true.
bool actInforme(int jugadas, int ganadas, int abandonos);

//FUNCIONES DE DIFICULTAD AVANZADA
int botDificil(int ultimo);

-----------------------------------------------------------------------------------*/

int main()
{
	tJugador ganador;
	int opcion;

	string nombre = saludar();
	//Bucle Menu
	do
	{
		opcion = menu();
		if(opcion == 1)
		{
			ganador = pasaCalculadora();
			actualizar_stats(ganador);
			despedirse(ganador, nombre);
		}
		else if(opcion == 2) acerca();
		else if(opcion == 3) stats();
	}
	while(opcion != 0);

	cout << "Hasta la proxima " << nombre << "(pulsa enter)";
	cin;

	return 0;
}

//Saluda al jugador y le pregunta su nombre
string saludar()
{
	string nombre;
	cout << "Bienvenido a Pasa la calculadora!" << endl;
	cout << "Como te llamas? ";
	cin >> nombre;
	cout << "Hola " << nombre << endl << endl;
	return nombre;
}

//Se despide del jugador, la despedida varia segun gane el jugador, el automata o ninguno de ellos (el jugador abandone)
void despedirse(tJugador ganador, string nombre)
{
	int ganadas = 0, perdidas = 0;
	if (ganador == Nadie){
		cout << "Abandonas, " << nombre << "? Ohhh..." << endl << endl;
	}
	else if (ganador == Jugador){
		cout << "Enhorabuena " << nombre << ", has ganado!" << endl << endl;
	}
	else /*if (ganador == Automata)*/{
		cout << "Lo siento " << nombre << ", he ganado" << endl << endl;
	}
}

//Proporciona al jugador la posibilidad de jugar, ver las instrucciones del juego o salir.
int menu()
{
	int seleccionar = -1; //Error flag
	cout << "1 - Jugar" << endl;
	cout << "2 - Acerca de" << endl;
	cout << "3 - Estadísticas" << endl;
	cout << "0 - Salir" << endl;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> seleccionar;

		if(cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (seleccionar < 0 || seleccionar > 3)
		{
			cout << "Error! Introduce un digito entre 0 y 3" << endl;
			seleccionar = -1;
		}

	}
	while (seleccionar == -1);

	return seleccionar;
}

//Muestra el archivo "acerca.txt" siempre que este no contenga errores
bool acerca()
{
	bool ok;
	ifstream acerca;
	char c;

	acerca.open("acerca.txt");

	if(acerca.is_open())
	{
		acerca.get(c); //Lee el primer caracter

		while(!acerca.fail()) //Mientras la lectura no falle
		{
			cout << c;
			acerca.get(c); //Lee el siguiente caracter
		}

		ok = true;
		acerca.close();

	}
	else
	{
		ok = false;
		cout << "Error, el archivo 'acerca.txt' no existe" << endl;
	}

	return ok;
}

//Actualiza las estadisticas
bool actualizar_stats(tJugador ganador)
{
	bool ok;
	int ganadas, perdidas, abandonadas;
	ifstream stats;
	ofstream actualizar;

	stats.open("stats.txt");
	if(stats.is_open())
	{
		stats >> ganadas;
		stats >> perdidas;
		stats >> abandonadas;

		ok = true;
	}
	else
	{
		ganadas = 0;
		perdidas = 0;
		abandonadas = 0;

		cout << "El archivo 'stats.txt' no se encontro, se ha creado un nuevo archivo"

		ok = false;
	}

	if(ganador == Jugador) ganadas += 1;
	else if(ganador == Automata) perdidas += 1;
	else if(ganador == Nadie) abandonadas += 1;

	stats.close();

	actualizar.open("stats.txt")

	actualizar << ganadas << endl;
	actualizar << perdidas << endl;
	actualizar << abandonadas << endl;

	actualizar.close();
	return ok;
}

//Muestra las estadisticas
void stats()
{
	ifstream stats;
	int ganadas, perdidas, abandonadas;

	stats.open("stats.txt")

	stats >> ganadas;
	stats >> perdidas;
	stats >> abandonadas;

	cout << "Partidas jugadas: " << (ganadas+perdidas+abandonadas) << endl;
	cout << "	Partidas ganadas: " << ganadas << endl;
	cout << "	Partidas perdidas: " << perdidas << endl;
	cout << "	Partidas abandonadas: " << abandonadas << endl;

	stats.close();
}

//Conduce el desarrollo del juego y devuelve el ganador.
//Si se abandona, devuelve Nadie.
tJugador pasaCalculadora()
{
	//Variables
	tJugador turno;
	int total = 0, ultimoDigito = 0;
	const int META=31;
		//Inicializar partida
	srand(time(NULL));//Semilla
	turno = quienEmpieza();

	//Bucle de juego
	do
	{
		//Turno jugador
		if (turno == Jugador)
		{
			ultimoDigito = digitoPersona(ultimoDigito);
			turno = Automata;
		}
		//Turno bot
		else /*if (turno == Automata)*/
		{
			ultimoDigito = digitoAutomata(ultimoDigito);
			turno = Jugador;
		}
		total += ultimoDigito;
		cout << "Total = " << total << endl;
	}
	while ((total < META) && (ultimoDigito != 0));

	if (ultimoDigito == 0) turno = Nadie;
	//Si el jugador abandona, no gana nadie

	return turno;
}

//Decide aleatoriamente quien empieza la partida, si el automata o el jugador
tJugador quienEmpieza()
{
	if (rand() % 2)
	{
		cout << "Tu empiezas" << endl;
		return Jugador;
	}
	else
	{
		cout << "Empiezo yo" << endl;
		return Automata;
	}
}

//Define que numeros se encuentran en la misma fila que el ultimo pulsado
bool mismaFila(int ultimo, int nuevo)
{
	int filaUltimo, filaNuevo;
	filaUltimo = ((ultimo - 1)/3);
	filaNuevo = ((nuevo - 1)/3);
	return (filaUltimo) == (filaNuevo);
}

//Define que numeros se encuentran en la misma columna que el ultimo
bool mismaColumna(int ultimo, int nuevo)
{
	int columnaUltimo, columnaNuevo;
	columnaUltimo = (ultimo % 3);
	columnaNuevo = (nuevo % 3);
	return columnaUltimo == columnaNuevo;
}

//Determina que digitos se pueden pulsar en funcion de las reglas del juego
bool digitoValido(int ultimo, int nuevo)  //hay un bug
{
	if (ultimo == 0) return true;//Si es el primer turno, todos los numeros valen

	return ((mismaFila(ultimo, nuevo))||(mismaColumna(ultimo, nuevo)))&&(ultimo!=nuevo);
}

//Genera un digito aleatorio
int digitoAleatorio()
{
	return (rand() % 9) + 1;
}

//Devuelve un digito que cumpla las reglas del juego con respecto a ultimo.
int digitoAutomata(int ultimo)
{
	int digito;

	do
	{
	digito = digitoAleatorio();
	}
	while (!digitoValido(ultimo, digito));

	cout << "Elijo el numero " << digito << endl;

	return digito;
}

//Pide un digito al jugador. Solo devolvera un valor valido (entre 0 y 9).
//Para un valor no valido, mostrara un error.
int digitoPersona()
{
	int digito = -1;

	do
	{
		cin.sync(); //Por si quedan datos basura en el buffer
		cin >> digito;

		if (cin.fail())
		{
			cout << "Error! Introduce un digito" << endl;
			cin.clear();
		}

		else if (digito < 0 || digito > 9)
		{
		cout << "Error! Introduce un digito entre 0 y 9" << endl;
		digito = -1;
		}

	}
	while (digito == -1);

	return digito;
}

//Pide un digito al jugador mostrando el teclado. Solo devolvera un valor
//que cumpla las reglas del juego o 0. Para un valor no valido, mostrara un error.
int digitoPersona(int ultimo)
{
	int digito = -1; //-1 es mi error flag

	mostrarCalculadora(ultimo);

	do
	{
		digito = digitoPersona();
		if (!digitoValido(ultimo, digito))
		{
			cout << "Error! El digito debe estar en la misma fila y columna que el ultimo" << endl;
			digito = -1;
		}
	}
	while (digito == -1);

	cout << "Has elegido el " << digito << endl;

	return digito;
}

//Determina si el numero de la calculadora se muestra o no, en funcion de si es valido
char mNumero(int ultimo, int n)
{
	if(digitoValido(ultimo, n))
	{
		return char (n+int('0'));

	}
	else
	{
		return ' ';
	}
}

//Muestra los botones de la calculadora (solo los que se pueden pulsar en cada turno)
void mostrarCalculadora(int ultimo)
{
	for (int i = 7; i<10; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 4; i<7; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
	for (int i = 1; i<4; i++)
	{
		cout << setw(3) << mNumero(ultimo, i);
	}
	cout << endl;
}
<|endoftext|>