<commit_before>/*
Copyright (c) 2014, Vlad Mesco
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdlib>
#include <cmath>
#include <iostream>
#include "core.hxx"
#include "drawing.hxx"

static bool moving = false, moving2 = false;
static float dlta = 0.1, dlta2 = 0.f;

static float jx = 0, jy = 0, jz = 0;

static float rx = 0, ry = 0;
static Point3D ppos(0, 0.5, -2);

static enum {
    FLY,
    GRAVITY
} mvmntType = FLY;

#define ngmap (10)
#define mgmap (10)
static float gmap[mgmap][ngmap] = {
    { -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -6.f, -6.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -6.f, -7.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -5.f, -6.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -5.f, -5.f, -5.f, -5.f, -6.f, -6.f, -6.f, -6.f, -6.f },
    { -4.f, -4.f, -5.f, -5.f, -6.f, -6.f, -7.f, -7.f, -7.f, -7.f },
    { -3.f, -4.f, -4.f, -5.f, -6.f, -7.f, -7.f, -8.f, -8.f, -8.f },
    { -3.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -8.f, -8.f, -8.f },
    { -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -8.f, -8.f, -8.f },
};

static void drawMap(Drawing& dwg)
{
    struct {
        float first;
        float step;
    }
    nn = { -((float)ngmap) / 2.f, 1.f },
    mm = { -((float)mgmap) / 2.f, 1.f };

    dwg.SetColor(Drawing::WHITE);
    for(size_t i = 0; i < ngmap - 1; ++i) {
        for(size_t j = 0; j < mgmap - 1; ++j) {
            dwg.MoveTo(Point3D(nn.first + i * nn.step, gmap[i][j], mm.first + j * mm.step));
            dwg.LineTo(Point3D(nn.first + i * nn.step, gmap[i][j + 1], mm.first + (j + 1) * mm.step));
            dwg.LineTo(Point3D(nn.first + (i + 1) * nn.step, gmap[i + 1][j + 1], mm.first + (j + 1) * mm.step));
            dwg.LineTo(Point3D(nn.first + (i + 1) * nn.step, gmap[i + 1][j], mm.first + j * mm.step));
            dwg.LineTo(Point3D(nn.first + i * nn.step, gmap[i][j], mm.first + j * mm.step));
        }
    }
}

static void drawScene(Drawing& dwg)
{
    dwg.MoveCamera(
        ppos,
        -ry,
        -rx);

    dwg.SetColor(Drawing::WHITE);
    dwg.SetRotations(jx, jy, jz);
    dwg.MoveTo(Point3D(0, 1, -5));
    dwg.WireCube(1);
    dwg.SetRotations(-jx, -jy, -jz);
    dwg.SetColor(Drawing::YELLOW);
    dwg.WireCube(0.5);

    dwg.SetColor(Drawing::CYAN);
    dwg.MoveTo(Point3D(-5, 0, 0));
    dwg.LineTo(Point3D(5, 0, 0));
    dwg.SetColor(Drawing::YELLOW);
    dwg.MoveTo(Point3D(0, -5, 0));
    dwg.LineTo(Point3D(0, 5, 0));
    dwg.SetColor(Drawing::CYAN);
    dwg.MoveTo(Point3D(0, 0, -5));
    dwg.LineTo(Point3D(0, 0, 5));

    dwg.MoveTo(Point3D(0, 0, 0));
    dwg.SetColor(Drawing::SEABLUE);
    dwg.SetRotations(0, 0, 45);
    dwg.Quad(1, 1);
    dwg.SetColor(Drawing::CYAN);
    dwg.WireQuad(1, 1);

    dwg.MoveTo(Point3D(0, 0, 0));
    dwg.SetColor(Drawing::SEAGREEN);
    dwg.SetRotations(90, 0, 0);
    dwg.Quad(0.7, 0.7);
    dwg.SetColor(Drawing::LIME);
    dwg.WireQuad(0.7, 0.7);

    dwg.MoveTo(Point3D(0, 0, 0));
    dwg.SetColor(Drawing::SEAYELLOW);
    dwg.SetRotations(0, 90, 0);
    dwg.Quad(0.4, 0.4);
    dwg.SetColor(Drawing::YELLOW);
    dwg.WireQuad(0.4, 0.4);

    dwg.MoveTo(Point3D(0, 0, 2));
    dwg.SetTexture(1);
    dwg.SetTextureScale(0, 0);
    dwg.SetRotations(0, 90, 90);
    dwg.TextureQuad(10, 5);

    dwg.SetTexture(0);
    dwg.MoveTo(Point3D(0, 0, 4));
    dwg.SetTextureScale(1, 1);
    dwg.SetRotations(0, 0, 0);
    dwg.TextureQuad(10, 1);
    dwg.MoveTo(Point3D(5, 0, 4));
    dwg.SetTextureScale(1, 1);
    dwg.SetRotations(0, 0, 0);
    dwg.TextureQuad(10, 1);

    dwg.SetTexture(1);
    dwg.MoveTo(Point3D(10, 0, 5.5));
    dwg.SetTextureScale(1, 1);
    dwg.SetRotations(0, 0, 0);
    dwg.TextureQuad(10, 1);
    dwg.SetColor(Drawing::WHITE);
    dwg.WireQuad(10, 1);

    dwg.MoveTo(Point3D(20, 0, 5.5));
    dwg.SetTextureScale(1, 1);
    dwg.SetRotations(0, 0, 0);
    dwg.TextureQuad(10, 1);
    dwg.SetColor(Drawing::WHITE);
    dwg.WireQuad(10, 1);

    // camera facing sprites
    dwg.MoveTo(Point3D(-10, 1, -1));
    dwg.SetTextureScale(0, 0);
    dwg.SetTexture(0);
    dwg.SpriteQuad(1, 1);

    dwg.MoveTo(Point3D(-10, 1, -3));
    dwg.SetTexture(1);
    dwg.SpriteQuad(1, 1);

    // cylindrical billboard
    dwg.MoveTo(Point3D(-10, 1, 3));
    dwg.SetTexture(0);
    dwg.SetRotations(90, 0, -ry);
    dwg.TextureQuad(1, 1);

    // in case texture's missing
    dwg.MoveTo(Point3D(-10, 1, -5));
    dwg.SetTexture(-1);
    dwg.SpriteQuad(1, 2);

    drawMap(dwg);

    if(mvmntType == GRAVITY) {
        dwg.SetRotations(0, 0, 0);
        dwg.SetColor(Drawing::LIME);
        Point3D p(-ppos.x, ppos.y - 1.f, -ppos.z);
        dwg.MoveTo(p);
        dwg.Quad(0.05, 0.05);
    }
}

static void onmousedown(int x, int y, int btn)
{
    if(btn == 1) {
    }
    if(btn == 2) {
    }
    if(btn == 3) {
    }
}

static void onmouseup(int x, int y, int btn)
{
}

static void onmousemove(int dx, int dy)
{
    ry += dx * 0.1;
    rx += dy * 0.1;
    if(rx > 90.f) rx = 90.f;
    if(rx < -90.f) rx = -90.f;
}

static bool computeZ()
{
    float x = -ppos.z;
    float y = -ppos.x;
    if(x == (float)(int)x) x += 1.e-5f;
    if(y == (float)(int)y) y += 1.e-5f;
    struct {
        int x1, x2;
        float w1, w2;
    }
    X = {
        (int)floorf(x) + 5, (int)ceilf(x) + 5,
        x - floorf(x), ceilf(x) - x
    },
    Y = {
        (int)floorf(y) + 5, (int)ceilf(y) + 5,
        y - floorf(y), ceilf(y) - y
    };

    if(X.x1 < 0 || X.x2 > 9 || Y.x1 < 0 || Y.x2 > 9) return false;

#define OP(A, B) ((1.f/A + 1.f/B) / 2.f)
    float z =
          gmap[Y.x1][X.x1] * OP(Y.w1, X.w1)
        + gmap[Y.x1][X.x2] * OP(Y.w1, X.w2)
        + gmap[Y.x2][X.x2] * OP(Y.w2, X.w2)
        + gmap[Y.x2][X.x1] * OP(Y.w2, X.w1);
    z /=
          OP(X.w1, Y.w1)
        + OP(X.w2, Y.w1)
        + OP(X.w2, Y.w2)
        + OP(X.w1, Y.w2);
#undef OP

    ppos.y = z + 2.f;

    return true;
}

static void updateScene()
{
#define ACTUAL_FRAMES_PER_ANIMATION_FRAME 30
    static size_t frameCounter = 0;

    if(moving || moving2) {
        switch(mvmntType) {
            case GRAVITY: {
                Point3D dir(dlta2, 0, dlta);
                dir = Drawing::UtilityHelpers::normalizeVector(dir);
                dir.x /= 10.f;
                dir.y /= 10.f;
                dir.z /= 10.f;
                dir = Drawing::UtilityHelpers::RotateDeltaVector(dir, -ry, 0);
                Point3D oldPpos = ppos;
                ppos = Drawing::UtilityHelpers::Translate(ppos, dir);
                if(!computeZ())
                {
                    ppos = oldPpos;
                }
                break; }
            case FLY: {
                Point3D dir(dlta2, 0, dlta);
                dir = Drawing::UtilityHelpers::normalizeVector(dir);
                dir.x /= 10.f;
                dir.y /= 10.f;
                dir.z /= 10.f;
                dir = Drawing::UtilityHelpers::RotateDeltaVector(dir, -ry, -rx);
                ppos = Drawing::UtilityHelpers::Translate(ppos, dir);
                break; }
        }
    }

    jx += 5;
    jy += 3;
    jz += 2;
    if(jx > 360) jx -= 360;
    if(jy > 360) jy -= 360;
    if(jz > 360) jz -= 360;
}

static void onkeyup(char key)
{
    if(key == 27) exit(0);
    switch(key) {
    case 'd':
    case 'a':
        moving2 = false;
        dlta2 = 0.f;
        break;
    case 'w':
    case 's':
        moving = false;
        dlta = 0.f;
        break;
    case 'm':
        if(mvmntType == GRAVITY) {
            mvmntType = FLY;
            break;
        }
        if(mvmntType == FLY &&
                ppos.x >= -((float)mgmap)/2.f &&
                ppos.x <= ((float)mgmap)/2.f &&
                ppos.z >= -((float)ngmap)/2.f &&
                ppos.z <= ((float)ngmap)/2.f)
        {
            mvmntType = GRAVITY;
            computeZ();
        }
        break;
    }
}

static void onkeydown(char key)
{
    switch(key) {
    case 'w':
        moving = true;
        dlta = 0.1;
        break;
    case 's':
        moving = true;
        dlta = -0.1;
        break;
    case 'a':
        moving2 = true;
        dlta2 = -0.1;
        break;
    case 'd':
        moving2 = true;
        dlta2 = 0.1;
    }
}

int main(int argc, char* argv[])
{
    Drawing::Init(&argc, argv);
    Drawing::SetWindowSize(728, 500);
    Drawing::SetOnMouseDown(onmousedown);
    Drawing::SetOnMouseUp(onmouseup);
    Drawing::SetOnMouseMove(onmousemove);
    Drawing::SetOnKeyUp(onkeyup);
    Drawing::SetOnKeyDown(onkeydown);

    Drawing::LoadBitmapTexture("sample.bmp");

    Drawing::LoadBitmapTexture("sample.bmp", 34 + 256 * 177 + 256 * 256 * 76);

    Drawing::Loop(updateScene, drawScene);

    return 0;
}
<commit_msg>add comment<commit_after>/*
Copyright (c) 2014, Vlad Mesco
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// DISCLAIMER: this is pretty much prototype/test code :D
#include <cstdlib>
#include <cmath>
#include <iostream>
#include "core.hxx"
#include "drawing.hxx"

static bool moving = false, moving2 = false;
static float dlta = 0.1, dlta2 = 0.f;

static float jx = 0, jy = 0, jz = 0;

static float rx = 0, ry = 0;
static Point3D ppos(0, 0.5, -2);

static enum {
    FLY,
    GRAVITY
} mvmntType = FLY;

#define ngmap (10)
#define mgmap (10)
static float gmap[mgmap][ngmap] = {
    { -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -6.f, -6.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -6.f, -7.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -5.f, -6.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f, -5.f },
    { -5.f, -5.f, -5.f, -5.f, -5.f, -6.f, -6.f, -6.f, -6.f, -6.f },
    { -4.f, -4.f, -5.f, -5.f, -6.f, -6.f, -7.f, -7.f, -7.f, -7.f },
    { -3.f, -4.f, -4.f, -5.f, -6.f, -7.f, -7.f, -8.f, -8.f, -8.f },
    { -3.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -8.f, -8.f, -8.f },
    { -2.f, -3.f, -4.f, -5.f, -6.f, -7.f, -8.f, -8.f, -8.f, -8.f },
};

static void drawMap(Drawing& dwg)
{
    struct {
        float first;
        float step;
    }
    nn = { -((float)ngmap) / 2.f, 1.f },
    mm = { -((float)mgmap) / 2.f, 1.f };

    dwg.SetColor(Drawing::WHITE);
    for(size_t i = 0; i < ngmap - 1; ++i) {
        for(size_t j = 0; j < mgmap - 1; ++j) {
            dwg.MoveTo(Point3D(nn.first + i * nn.step, gmap[i][j], mm.first + j * mm.step));
            dwg.LineTo(Point3D(nn.first + i * nn.step, gmap[i][j + 1], mm.first + (j + 1) * mm.step));
            dwg.LineTo(Point3D(nn.first + (i + 1) * nn.step, gmap[i + 1][j + 1], mm.first + (j + 1) * mm.step));
            dwg.LineTo(Point3D(nn.first + (i + 1) * nn.step, gmap[i + 1][j], mm.first + j * mm.step));
            dwg.LineTo(Point3D(nn.first + i * nn.step, gmap[i][j], mm.first + j * mm.step));
        }
    }
}

static void drawScene(Drawing& dwg)
{
    dwg.MoveCamera(
        ppos,
        -ry,
        -rx);

    dwg.SetColor(Drawing::WHITE);
    dwg.SetRotations(jx, jy, jz);
    dwg.MoveTo(Point3D(0, 1, -5));
    dwg.WireCube(1);
    dwg.SetRotations(-jx, -jy, -jz);
    dwg.SetColor(Drawing::YELLOW);
    dwg.WireCube(0.5);

    dwg.SetColor(Drawing::CYAN);
    dwg.MoveTo(Point3D(-5, 0, 0));
    dwg.LineTo(Point3D(5, 0, 0));
    dwg.SetColor(Drawing::YELLOW);
    dwg.MoveTo(Point3D(0, -5, 0));
    dwg.LineTo(Point3D(0, 5, 0));
    dwg.SetColor(Drawing::CYAN);
    dwg.MoveTo(Point3D(0, 0, -5));
    dwg.LineTo(Point3D(0, 0, 5));

    dwg.MoveTo(Point3D(0, 0, 0));
    dwg.SetColor(Drawing::SEABLUE);
    dwg.SetRotations(0, 0, 45);
    dwg.Quad(1, 1);
    dwg.SetColor(Drawing::CYAN);
    dwg.WireQuad(1, 1);

    dwg.MoveTo(Point3D(0, 0, 0));
    dwg.SetColor(Drawing::SEAGREEN);
    dwg.SetRotations(90, 0, 0);
    dwg.Quad(0.7, 0.7);
    dwg.SetColor(Drawing::LIME);
    dwg.WireQuad(0.7, 0.7);

    dwg.MoveTo(Point3D(0, 0, 0));
    dwg.SetColor(Drawing::SEAYELLOW);
    dwg.SetRotations(0, 90, 0);
    dwg.Quad(0.4, 0.4);
    dwg.SetColor(Drawing::YELLOW);
    dwg.WireQuad(0.4, 0.4);

    dwg.MoveTo(Point3D(0, 0, 2));
    dwg.SetTexture(1);
    dwg.SetTextureScale(0, 0);
    dwg.SetRotations(0, 90, 90);
    dwg.TextureQuad(10, 5);

    dwg.SetTexture(0);
    dwg.MoveTo(Point3D(0, 0, 4));
    dwg.SetTextureScale(1, 1);
    dwg.SetRotations(0, 0, 0);
    dwg.TextureQuad(10, 1);
    dwg.MoveTo(Point3D(5, 0, 4));
    dwg.SetTextureScale(1, 1);
    dwg.SetRotations(0, 0, 0);
    dwg.TextureQuad(10, 1);

    dwg.SetTexture(1);
    dwg.MoveTo(Point3D(10, 0, 5.5));
    dwg.SetTextureScale(1, 1);
    dwg.SetRotations(0, 0, 0);
    dwg.TextureQuad(10, 1);
    dwg.SetColor(Drawing::WHITE);
    dwg.WireQuad(10, 1);

    dwg.MoveTo(Point3D(20, 0, 5.5));
    dwg.SetTextureScale(1, 1);
    dwg.SetRotations(0, 0, 0);
    dwg.TextureQuad(10, 1);
    dwg.SetColor(Drawing::WHITE);
    dwg.WireQuad(10, 1);

    // camera facing sprites
    dwg.MoveTo(Point3D(-10, 1, -1));
    dwg.SetTextureScale(0, 0);
    dwg.SetTexture(0);
    dwg.SpriteQuad(1, 1);

    dwg.MoveTo(Point3D(-10, 1, -3));
    dwg.SetTexture(1);
    dwg.SpriteQuad(1, 1);

    // cylindrical billboard
    dwg.MoveTo(Point3D(-10, 1, 3));
    dwg.SetTexture(0);
    dwg.SetRotations(90, 0, -ry);
    dwg.TextureQuad(1, 1);

    // in case texture's missing
    dwg.MoveTo(Point3D(-10, 1, -5));
    dwg.SetTexture(-1);
    dwg.SpriteQuad(1, 2);

    drawMap(dwg);

    if(mvmntType == GRAVITY) {
        dwg.SetRotations(0, 0, 0);
        dwg.SetColor(Drawing::LIME);
        Point3D p(-ppos.x, ppos.y - 1.f, -ppos.z);
        dwg.MoveTo(p);
        dwg.Quad(0.05, 0.05);
    }
}

static void onmousedown(int x, int y, int btn)
{
    if(btn == 1) {
    }
    if(btn == 2) {
    }
    if(btn == 3) {
    }
}

static void onmouseup(int x, int y, int btn)
{
}

static void onmousemove(int dx, int dy)
{
    ry += dx * 0.1;
    rx += dy * 0.1;
    if(rx > 90.f) rx = 90.f;
    if(rx < -90.f) rx = -90.f;
}

static bool computeZ()
{
    float x = -ppos.z;
    float y = -ppos.x;
    if(x == (float)(int)x) x += 1.e-5f;
    if(y == (float)(int)y) y += 1.e-5f;
    struct {
        int x1, x2;
        float w1, w2;
    }
    X = {
        (int)floorf(x) + 5, (int)ceilf(x) + 5,
        x - floorf(x), ceilf(x) - x
    },
    Y = {
        (int)floorf(y) + 5, (int)ceilf(y) + 5,
        y - floorf(y), ceilf(y) - y
    };

    if(X.x1 < 0 || X.x2 > 9 || Y.x1 < 0 || Y.x2 > 9) return false;

#define OP(A, B) ((1.f/A + 1.f/B) / 2.f)
    float z =
          gmap[Y.x1][X.x1] * OP(Y.w1, X.w1)
        + gmap[Y.x1][X.x2] * OP(Y.w1, X.w2)
        + gmap[Y.x2][X.x2] * OP(Y.w2, X.w2)
        + gmap[Y.x2][X.x1] * OP(Y.w2, X.w1);
    z /=
          OP(X.w1, Y.w1)
        + OP(X.w2, Y.w1)
        + OP(X.w2, Y.w2)
        + OP(X.w1, Y.w2);
#undef OP

    ppos.y = z + 2.f;

    return true;
}

static void updateScene()
{
#define ACTUAL_FRAMES_PER_ANIMATION_FRAME 30
    static size_t frameCounter = 0;

    if(moving || moving2) {
        switch(mvmntType) {
            case GRAVITY: {
                Point3D dir(dlta2, 0, dlta);
                dir = Drawing::UtilityHelpers::normalizeVector(dir);
                dir.x /= 10.f;
                dir.y /= 10.f;
                dir.z /= 10.f;
                dir = Drawing::UtilityHelpers::RotateDeltaVector(dir, -ry, 0);
                Point3D oldPpos = ppos;
                ppos = Drawing::UtilityHelpers::Translate(ppos, dir);
                if(!computeZ())
                {
                    ppos = oldPpos;
                }
                break; }
            case FLY: {
                Point3D dir(dlta2, 0, dlta);
                dir = Drawing::UtilityHelpers::normalizeVector(dir);
                dir.x /= 10.f;
                dir.y /= 10.f;
                dir.z /= 10.f;
                dir = Drawing::UtilityHelpers::RotateDeltaVector(dir, -ry, -rx);
                ppos = Drawing::UtilityHelpers::Translate(ppos, dir);
                break; }
        }
    }

    jx += 5;
    jy += 3;
    jz += 2;
    if(jx > 360) jx -= 360;
    if(jy > 360) jy -= 360;
    if(jz > 360) jz -= 360;
}

static void onkeyup(char key)
{
    if(key == 27) exit(0);
    switch(key) {
    case 'd':
    case 'a':
        moving2 = false;
        dlta2 = 0.f;
        break;
    case 'w':
    case 's':
        moving = false;
        dlta = 0.f;
        break;
    case 'm':
        if(mvmntType == GRAVITY) {
            mvmntType = FLY;
            break;
        }
        if(mvmntType == FLY &&
                ppos.x >= -((float)mgmap)/2.f &&
                ppos.x <= ((float)mgmap)/2.f &&
                ppos.z >= -((float)ngmap)/2.f &&
                ppos.z <= ((float)ngmap)/2.f)
        {
            mvmntType = GRAVITY;
            computeZ();
        }
        break;
    }
}

static void onkeydown(char key)
{
    switch(key) {
    case 'w':
        moving = true;
        dlta = 0.1;
        break;
    case 's':
        moving = true;
        dlta = -0.1;
        break;
    case 'a':
        moving2 = true;
        dlta2 = -0.1;
        break;
    case 'd':
        moving2 = true;
        dlta2 = 0.1;
    }
}

int main(int argc, char* argv[])
{
    Drawing::Init(&argc, argv);
    Drawing::SetWindowSize(728, 500);
    Drawing::SetOnMouseDown(onmousedown);
    Drawing::SetOnMouseUp(onmouseup);
    Drawing::SetOnMouseMove(onmousemove);
    Drawing::SetOnKeyUp(onkeyup);
    Drawing::SetOnKeyDown(onkeydown);

    Drawing::LoadBitmapTexture("sample.bmp");

    Drawing::LoadBitmapTexture("sample.bmp", 34 + 256 * 177 + 256 * 256 * 76);

    Drawing::Loop(updateScene, drawScene);

    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <algorithm>
#include <regex>
#include "BinaryTreeAVL.h"
#include "NodoVocabulario.h"

void ayuda( std::string );
void leerArchivo( BinaryTreeAVL&, std::string, bool );
void insertarPalabra(BinaryTreeAVL&, std::string, bool );
int validarPalabra( std::string );
std::string voltearPalabra(std::string palabra);
int scorePalabra( BinaryTreeAVL&, std::string );

int main()
{
  BinaryTreeAVL tree;
  bool exit = false, init = false, init_inverse = false;
  std::string comando;
  do
  {
    std::cout << "$ ";
    std::getline( std::cin, comando );
    std::string aux = comando.substr( 0, comando.find( " " ) );
    if( comando.find( "ayuda" ) != std::string::npos )
    {
      ayuda( comando );
      std::cout << std::endl;
    }
    else
    {
      if( aux == "init_inverse" && !init_inverse )
      {
        //TODO funcion init_inverse
        leerArchivo( tree, comando, false);
        init_inverse = true;
        std::cout << std::endl;
      }
      else
      {
        if( aux == "score" )
        {
          std::string palabra = comando.substr( comando.find( " " ) + 1 );
          //TODO funcion score
          int scoreP = scorePalabra(tree, palabra);
          if(scoreP == -1){
            std::cout << "----------------------------------------------------" << std::endl;
            std::cout << "ERROR" << std::endl;
            std::cout << "La palabra " << palabra << " tiene caracteres invalidos." << std::endl;
            std::cout << "----------------------------------------------------" << std::endl;
          }
          else{
            if(scoreP == -2){
              std::cout << "----------------------------------------------------" << std::endl;
              std::cout << "ERROR" << std::endl;
              std::cout << "La palabra " << palabra << " no se encuentra en el diccionario." << std::endl;
              std::cout << "----------------------------------------------------" << std::endl;
            }
            else{
              std::cout << "El puntaje de la palabra " << palabra << " es: " << scoreP << std::endl;
              std::cout << std::endl;
            }
          }

        }
        else
        {
          if( aux == "init" && !init )
          {
            //TODO funcion init
            leerArchivo( tree, comando, true);
            init = true;
            std::cout << std::endl;
          }
          else
            if( aux == "exit" )
              exit = true;
            else
              if( ( aux == "init" && init ) || ( aux == "init_inverse" && init_inverse ) )
              {
                if( init )
                  std::cout << "Diccionario";
                else
                  std::cout << "Diccionario inverso";
                std::cout << " ya ha sido inicializado." << std::endl;
                std::cout << std::endl;
              }
              else
              {
                std::cout << "Error comando inexistente, teclee \"ayuda\" para ver una lista de comandos" << std::endl;
                std::cout << std::endl;
              }
        }

      }
    }
  }while( !exit );
  return 0;
}

void ayuda( std::string comando )
{
  if( comando == "ayuda init_inverse" )
  {
    std::cout << "comando: init_inverse words_file.txt." << std::endl;
    std::cout << "descripción: Inicializa el sistema a partir del archivo words_file.txt, que" << std::endl
              << "contiene un diccionario de palabras aceptadas en el idioma ingles" << std::endl
              << "(idioma original del juego). A diferencia del comando init, este comando" << std::endl
              << "almacena las palabras en sentido inverso (leidas de derecha a izquierda)" << std::endl;
  }
  else
    if( comando == "ayuda init" )
    {
      std::cout << "comando: init words_file.txt" << std::endl;
      std::cout << "descripción: Inicializa el sistema a partir del archivo words_file.txt, que" << std::endl
                << "contiene un diccionario de palabras aceptadas en el idioma ingles" << std::endl
                << "(idioma original del juego)." << std::endl << std::endl;
    }
    else
      if( comando == "ayuda score" )
      {
        std::cout << "comando: score word" << std::endl;
        std::cout << "descripción: El comando permite conocer la puntuacion que puede obtenerse con" << std::endl
                  << "una palabra dada, de acuerdo a la tabla de puntuacion de cada letra." << std::endl;
      }
      else
        if( comando == "ayuda exit" )
        {
          std::cout << "comando: exit" << std::endl;
          std::cout << "descripción: Termina la ejecucion de la aplicacion." << std::endl;
        }
        else
        {
          if( comando == "ayuda" )
          {
            std::cout << "Teclee \"ayuda <comando>\" para obtener más informacion del comando" << std::endl;
            std::cout << std::endl << "\tinit [nombre del archivo]" << std::endl;
            std::cout << "\tinit_inverse [nombre del archivo]" << std::endl;
            std::cout << "\tscore [palabra]" << std::endl;
            std::cout << "\texit" << std::endl;
          }
          else
          std::cout << "Error comando inexistente, teclee \"ayuda\" para ver una lista de comandos" << std::endl;

        }
}

void leerArchivo( BinaryTreeAVL& tree, std::string comando, bool tipo )
{
  std::string nombreArc, linea;
  nombreArc = comando.substr( comando.find( " " ) + 1 );
  std::ifstream archivo( nombreArc.c_str( ) );
  if( archivo.is_open() )
  {
    while( !archivo.eof() )
    {
      archivo >> linea;
      std::transform(linea.begin(),linea.end(),linea.begin(),::tolower);
      if(tipo == true)
        insertarPalabra(tree , linea, tipo);
      else
        insertarPalabra(tree, voltearPalabra(linea), tipo);
    }
    std::cout << std::endl << "----------------------------------------------------" << std::endl;
    std::cout << "El diccionario se inicializo." << std::endl;
    std::cout << "----------------------------------------------------" << std::endl;

  }
  else
  {
    std::cout << "----------------------------------------------------" << std::endl;
    std::cout << "ERROR" << std::endl;
    std::cout << "apertura del archivo: " << nombreArc << " fallida." << std::endl;
    std::cout << "----------------------------------------------------" << std::endl;
  }
}

void insertarPalabra(BinaryTreeAVL& tree, std::string palabra, bool tipo){
  if(validarPalabra(palabra) == 1){
    BinaryNodeAVL* nodoLetra = tree.search(palabra[0]);
    if(nodoLetra != nullptr){
      if(tipo)
        nodoLetra->getData().insertarPalabra(palabra);
      else((nodoLetra->getData().getPalabras())[palabra]);
        nodoLetra->getData().insertarPalabraInv(palabra);
    }
    else{
      NodoVocabulario* nodo = new NodoVocabulario(palabra[0]);
      tree.insert(*nodo);
      if(tipo)
        nodo->insertarPalabra(palabra);
      else
        nodo->insertarPalabraInv(palabra);
    }
  }
  else{
    std::cout << "----------------------------------------------------" << std::endl;
    std::cout << "ERROR" << std::endl;
    std::cout << "La palabra: " << palabra << " tiene caracteres invalidos." << std::endl;
    std::cout << "----------------------------------------------------" << std::endl;
  }
}

int validarPalabra( std::string palabra )
{
    int verificado = 0;
    for( unsigned int i = 0; i < palabra.size(); i++ )
    {
        char caracter = palabra[i];
        if( ( caracter >= 65 && caracter <= 90 ) || ( caracter >= 97 && caracter <= 122 ) )
            verificado = 1;
        else
        {
          verificado = 0;
          break;
        }
    }
    return verificado;
}

std::string voltearPalabra(std::string palabra)
{
    int ind = 0;
    std::string nPalabra;
    nPalabra.resize(palabra.size());
    for(std::string::reverse_iterator apun = palabra.rbegin(); apun != palabra.rend(); apun++)
    {
        nPalabra[ind]=*apun;
        ind++;
    }
    return nPalabra;
}

int scorePalabra(BinaryTreeAVL& tree, std::string palabra){
  if(validarPalabra(palabra) == 1){
    BinaryNodeAVL* nodoLetra = tree.search(palabra[0]);
    if(nodoLetra != nullptr){
      std::map<std::string, int>::iterator iterador = nodoLetra->getData().getPalabras().find(palabra);
      if(iterador != nodoLetra->getData().getPalabras().end())
        return((nodoLetra->getData().getPalabras())[palabra]);
      else{
        iterador = nodoLetra->getData().getPalabrasInv().find(palabra);
        if(iterador != nodoLetra->getData().getPalabrasInv().end())
          return ((nodoLetra->getData().getPalabrasInv())[palabra]);
        else
          return (-2);
      }
    }
    else
      return (-2);
  }
  return (-1);
}
<commit_msg>Borra una linea<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <algorithm>
#include <regex>
#include "BinaryTreeAVL.h"
#include "NodoVocabulario.h"

void ayuda( std::string );
void leerArchivo( BinaryTreeAVL&, std::string, bool );
void insertarPalabra(BinaryTreeAVL&, std::string, bool );
int validarPalabra( std::string );
std::string voltearPalabra(std::string palabra);
int scorePalabra( BinaryTreeAVL&, std::string );

int main()
{
  BinaryTreeAVL tree;
  bool exit = false, init = false, init_inverse = false;
  std::string comando;
  do
  {
    std::cout << "$ ";
    std::getline( std::cin, comando );
    std::string aux = comando.substr( 0, comando.find( " " ) );
    if( comando.find( "ayuda" ) != std::string::npos )
    {
      ayuda( comando );
      std::cout << std::endl;
    }
    else
    {
      if( aux == "init_inverse" && !init_inverse )
      {
        //TODO funcion init_inverse
        leerArchivo( tree, comando, false);
        init_inverse = true;
        std::cout << std::endl;
      }
      else
      {
        if( aux == "score" )
        {
          std::string palabra = comando.substr( comando.find( " " ) + 1 );
          //TODO funcion score
          int scoreP = scorePalabra(tree, palabra);
          if(scoreP == -1){
            std::cout << "----------------------------------------------------" << std::endl;
            std::cout << "ERROR" << std::endl;
            std::cout << "La palabra " << palabra << " tiene caracteres invalidos." << std::endl;
            std::cout << "----------------------------------------------------" << std::endl;
          }
          else{
            if(scoreP == -2){
              std::cout << "----------------------------------------------------" << std::endl;
              std::cout << "ERROR" << std::endl;
              std::cout << "La palabra " << palabra << " no se encuentra en el diccionario." << std::endl;
              std::cout << "----------------------------------------------------" << std::endl;
            }
            else{
              std::cout << "El puntaje de la palabra " << palabra << " es: " << scoreP << std::endl;
              std::cout << std::endl;
            }
          }

        }
        else
        {
          if( aux == "init" && !init )
          {
            //TODO funcion init
            leerArchivo( tree, comando, true);
            init = true;
            std::cout << std::endl;
          }
          else
            if( aux == "exit" )
              exit = true;
            else
              if( ( aux == "init" && init ) || ( aux == "init_inverse" && init_inverse ) )
              {
                if( init )
                  std::cout << "Diccionario";
                else
                  std::cout << "Diccionario inverso";
                std::cout << " ya ha sido inicializado." << std::endl;
                std::cout << std::endl;
              }
              else
              {
                std::cout << "Error comando inexistente, teclee \"ayuda\" para ver una lista de comandos" << std::endl;
                std::cout << std::endl;
              }
        }

      }
    }
  }while( !exit );
  return 0;
}

void ayuda( std::string comando )
{
  if( comando == "ayuda init_inverse" )
  {
    std::cout << "comando: init_inverse words_file.txt." << std::endl;
    std::cout << "descripción: Inicializa el sistema a partir del archivo words_file.txt, que" << std::endl
              << "contiene un diccionario de palabras aceptadas en el idioma ingles" << std::endl
              << "(idioma original del juego). A diferencia del comando init, este comando" << std::endl
              << "almacena las palabras en sentido inverso (leidas de derecha a izquierda)" << std::endl;
  }
  else
    if( comando == "ayuda init" )
    {
      std::cout << "comando: init words_file.txt" << std::endl;
      std::cout << "descripción: Inicializa el sistema a partir del archivo words_file.txt, que" << std::endl
                << "contiene un diccionario de palabras aceptadas en el idioma ingles" << std::endl
                << "(idioma original del juego)." << std::endl << std::endl;
    }
    else
      if( comando == "ayuda score" )
      {
        std::cout << "comando: score word" << std::endl;
        std::cout << "descripción: El comando permite conocer la puntuacion que puede obtenerse con" << std::endl
                  << "una palabra dada, de acuerdo a la tabla de puntuacion de cada letra." << std::endl;
      }
      else
        if( comando == "ayuda exit" )
        {
          std::cout << "comando: exit" << std::endl;
          std::cout << "descripción: Termina la ejecucion de la aplicacion." << std::endl;
        }
        else
        {
          if( comando == "ayuda" )
          {
            std::cout << "Teclee \"ayuda <comando>\" para obtener más informacion del comando" << std::endl;
            std::cout << std::endl << "\tinit [nombre del archivo]" << std::endl;
            std::cout << "\tinit_inverse [nombre del archivo]" << std::endl;
            std::cout << "\tscore [palabra]" << std::endl;
            std::cout << "\texit" << std::endl;
          }
          else
          std::cout << "Error comando inexistente, teclee \"ayuda\" para ver una lista de comandos" << std::endl;

        }
}

void leerArchivo( BinaryTreeAVL& tree, std::string comando, bool tipo )
{
  std::string nombreArc, linea;
  nombreArc = comando.substr( comando.find( " " ) + 1 );
  std::ifstream archivo( nombreArc.c_str( ) );
  if( archivo.is_open() )
  {
    while( !archivo.eof() )
    {
      archivo >> linea;
      std::transform(linea.begin(),linea.end(),linea.begin(),::tolower);
      if(tipo == true)
        insertarPalabra(tree , linea, tipo);
      else
        insertarPalabra(tree, voltearPalabra(linea), tipo);
    }
    std::cout << std::endl << "----------------------------------------------------" << std::endl;
    std::cout << "El diccionario se inicializo." << std::endl;
    std::cout << "----------------------------------------------------" << std::endl;

  }
  else
  {
    std::cout << "----------------------------------------------------" << std::endl;
    std::cout << "ERROR" << std::endl;
    std::cout << "apertura del archivo: " << nombreArc << " fallida." << std::endl;
    std::cout << "----------------------------------------------------" << std::endl;
  }
}

void insertarPalabra(BinaryTreeAVL& tree, std::string palabra, bool tipo){
  if(validarPalabra(palabra) == 1){
    BinaryNodeAVL* nodoLetra = tree.search(palabra[0]);
    if(nodoLetra != nullptr){
      if(tipo)
        nodoLetra->getData().insertarPalabra(palabra);
      else
        nodoLetra->getData().insertarPalabraInv(palabra);
    }
    else{
      NodoVocabulario* nodo = new NodoVocabulario(palabra[0]);
      tree.insert(*nodo);
      if(tipo)
        nodo->insertarPalabra(palabra);
      else
        nodo->insertarPalabraInv(palabra);
    }
  }
  else{
    std::cout << "----------------------------------------------------" << std::endl;
    std::cout << "ERROR" << std::endl;
    std::cout << "La palabra: " << palabra << " tiene caracteres invalidos." << std::endl;
    std::cout << "----------------------------------------------------" << std::endl;
  }
}

int validarPalabra( std::string palabra )
{
    int verificado = 0;
    for( unsigned int i = 0; i < palabra.size(); i++ )
    {
        char caracter = palabra[i];
        if( ( caracter >= 65 && caracter <= 90 ) || ( caracter >= 97 && caracter <= 122 ) )
            verificado = 1;
        else
        {
          verificado = 0;
          break;
        }
    }
    return verificado;
}

std::string voltearPalabra(std::string palabra)
{
    int ind = 0;
    std::string nPalabra;
    nPalabra.resize(palabra.size());
    for(std::string::reverse_iterator apun = palabra.rbegin(); apun != palabra.rend(); apun++)
    {
        nPalabra[ind]=*apun;
        ind++;
    }
    return nPalabra;
}

int scorePalabra(BinaryTreeAVL& tree, std::string palabra){
  if(validarPalabra(palabra) == 1){
    BinaryNodeAVL* nodoLetra = tree.search(palabra[0]);
    if(nodoLetra != nullptr){
      std::map<std::string, int>::iterator iterador = nodoLetra->getData().getPalabras().find(palabra);
      if(iterador != nodoLetra->getData().getPalabras().end())
        return((nodoLetra->getData().getPalabras())[palabra]);
      else{
        iterador = nodoLetra->getData().getPalabrasInv().find(palabra);
        if(iterador != nodoLetra->getData().getPalabrasInv().end())
          return ((nodoLetra->getData().getPalabrasInv())[palabra]);
        else
          return (-2);
      }
    }
    else
      return (-2);
  }
  return (-1);
}
<|endoftext|>


<commit_before>#ifndef MAYBE_HH
#define MAYBE_HH

#include <cassert>
#include <initializer_list>
#include <new>
#include <memory>
#include <type_traits>

template<typename T>
struct maybe {
  maybe() noexcept : is_init(false) {}

  template<typename ...Args>
  maybe(Args &&...args) : is_init(false) {
    new(&memory) T(std::forward<Args>(args)...);
    is_init = true;
  }

  template<typename U,
           typename = typename std::enable_if<std::is_constructible<T, std::initializer_list<U>>::value>::type>
  maybe(std::initializer_list<U> init) : is_init(false) {
    new(&memory) T(std::forward<std::initializer_list<U>>(init));
    is_init = true;
  }

  maybe(const maybe &other) noexcept(std::is_nothrow_copy_constructible<T>::value) : is_init(false) {
    if (other.is_init) {
      new (&memory) T(*other);
      is_init = true;
    }
  }

  maybe(maybe &&other) noexcept(std::is_nothrow_move_constructible<T>::value) : is_init(false) {
    if (other.is_init) {
      new (&memory) T(std::move(*other));
      is_init = true;
    }
  }

  maybe &operator=(const maybe &other) {
    if (this != &other && other.is_init) {
      if (is_init) {
        *as_ptr() = *other;
      } else {
        new (&memory) T(*other);
        is_init = true;
      }
    } else {
      clear();
    }
    return *this;
  }

  maybe &operator=(maybe &&other) {
    assert(this != &other);
    if (other.is_init) {
      if (is_init) {
        *as_ptr() = std::move(*other);
      } else {
        new (&memory) T(std::move(*other));
        is_init = true;
      }
    } else {
      clear();
    }
    return *this;
  }

  ~maybe() {
    if (is_init) {
      as_ptr()->~T();
    }
  }

  explicit operator bool() const noexcept {
    return is_init;
  }

  T &operator*() noexcept {
    assert(is_init);
    return *as_ptr();
  }

  const T &operator*() const noexcept {
    assert(is_init);
    return *as_ptr();
  }

  T *operator->() noexcept {
    assert(is_init);
    return as_ptr();
  }

  const T *operator->() const noexcept {
    assert(is_init);
    return as_ptr();
  }

  T *get() noexcept {
    return is_init ? as_ptr() : nullptr;
  }

  const T *get() const noexcept {
    return is_init ? as_ptr() : nullptr;
  }

  T const &get_value_or(T const &v) const noexcept {
    return is_init ? *as_ptr() : v;
  }

  void clear() {
    if (is_init) {
      as_ptr()->~T();
      is_init = false;
    }
  }

  template<typename ...Args>
  void emplace(Args &&...args) {
    clear();
    new(&memory) T(std::forward<Args>(args)...);
    is_init = true;
  }

private:
  T *as_ptr() { return reinterpret_cast<T *>(&memory); }
  const T *as_ptr() const { return reinterpret_cast<const T *>(&memory); }

  typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type memory;
  bool is_init;
};

#endif
<commit_msg>maybe.hh: just use an unrestricted union<commit_after>#ifndef MAYBE_HH
#define MAYBE_HH

#include <cassert>
#include <initializer_list>
#include <new>
#include <type_traits>
#include <utility>

template<typename T>
struct maybe {
  maybe() noexcept : is_init(false) {}

  template<typename ...Args>
  maybe(Args &&...args) : is_init(false) {
    new(&memory) T(std::forward<Args>(args)...);
    is_init = true;
  }

  template<typename U,
           typename = typename std::enable_if<std::is_constructible<T, std::initializer_list<U>>::value>::type>
  maybe(std::initializer_list<U> init) : is_init(false) {
    new(&memory) T(std::forward<std::initializer_list<U>>(init));
    is_init = true;
  }

  maybe(const maybe &other) noexcept(std::is_nothrow_copy_constructible<T>::value) : is_init(false) {
    if (other.is_init) {
      new (&memory) T(*other);
      is_init = true;
    }
  }

  maybe(maybe &&other) noexcept(std::is_nothrow_move_constructible<T>::value) : is_init(false) {
    if (other.is_init) {
      new (&memory) T(std::move(*other));
      is_init = true;
    }
  }

  maybe &operator=(const maybe &other) {
    if (this != &other && other.is_init) {
      if (is_init) {
        memory = *other;
      } else {
        new (&memory) T(*other);
        is_init = true;
      }
    } else {
      clear();
    }
    return *this;
  }

  maybe &operator=(maybe &&other) {
    assert(this != &other);
    if (other.is_init) {
      if (is_init) {
        memory = std::move(*other);
      } else {
        new (&memory) T(std::move(*other));
        is_init = true;
      }
    } else {
      clear();
    }
    return *this;
  }

  ~maybe() {
    if (is_init) {
      memory.~T();
    }
  }

  explicit operator bool() const noexcept {
    return is_init;
  }

  T &operator*() noexcept {
    assert(is_init);
    return memory;
  }

  const T &operator*() const noexcept {
    assert(is_init);
    return memory;
  }

  T *operator->() noexcept {
    assert(is_init);
    return &memory;
  }

  const T *operator->() const noexcept {
    assert(is_init);
    return &memory;
  }

  T *get() noexcept {
    return is_init ? &memory : nullptr;
  }

  const T *get() const noexcept {
    return is_init ? &memory : nullptr;
  }

  T const &get_value_or(T const &v) const noexcept {
    return is_init ? memory : v;
  }

  void clear() {
    if (is_init) {
      memory.~T();
      is_init = false;
    }
  }

  template<typename ...Args>
  void emplace(Args &&...args) {
    clear();
    new(&memory) T(std::forward<Args>(args)...);
    is_init = true;
  }

private:
  union { T memory; };
  bool is_init;
};

#endif
<|endoftext|>


<commit_before>#pragma once
#include <cassert>
#include <cstring>
#include <cwchar>
#include <stack>
#include <deque>
#include <atomic>
#include <thread>

//! 32bitの4文字チャンクを生成
#define MAKECHUNK(c0,c1,c2,c3) ((c3<<24) | (c2<<16) | (c1<<8) | c0)

namespace spn {
	//! スピンロックによるmutex
	class Synchro {
		private:
			using AThID = std::atomic<std::thread::id>;

			std::atomic_bool	_abLock;	//!< 誰かロックしてるか
			AThID				_idTh;		//!< ロック中のスレッド番号
			int					_iLockNum;	//!< 再帰的なロック用カウンタ

			template <bool Block>
			bool _lock() {
				auto thid = std::this_thread::get_id();
				do {
					bool b = false;
					if(_abLock.compare_exchange_weak(b, true, std::memory_order_acquire)) {
						_iLockNum = 1;
						_idTh.store(thid, std::memory_order_relaxed);
						return true;
					}
					if(_idTh.compare_exchange_weak(thid, thid, std::memory_order_acquire)) {
						++_iLockNum;
						return true;
					}
				} while(Block);
				return false;
			}
		public:
			Synchro(): _abLock(false) {}

			void lock() { _lock<true>(); }
			bool try_lock() { return _lock<false>(); }
			void unlock() {
				if(--_iLockNum == 0)
					_abLock.store(false, std::memory_order_relaxed);
			}
	};

	//! 何もしないダミーmutex
	class PseudoSynch {
		public:
			void lock() {}
			bool try_lock() { return true; }
			void unlock() {}
	};

	//! 4つの8bit値から32bitチャンクを生成
	inline static long MakeChunk(uint8_t c0, uint8_t c1, uint8_t c2, uint8_t c3) {
		return (c3 << 24) | (c2 << 16) | (c1 << 8) | c0; }

	inline uint64_t U64FromU32(uint32_t hv, uint32_t lv) {
		uint64_t ret(hv);
		ret <<= 32;
		ret |= lv;
		return ret;
	}

	struct Text {
		// エンコードタイプ
		enum class CODETYPE {
			UTF_8,
			UTF_16LE,
			UTF_16BE,
			UTF_32LE,
			UTF_32BE,
			ANSI
		};
		//! SJISコードか判定する
		static bool sjis_isMBChar(char c);
		//! SJISコードにおける文字数判定
		static int sjis_strlen(const char* str);
		//! エンコードタイプと判定に使った文字数を返す
		static std::pair<CODETYPE, int> GetEncodeType(const void* ptr);
		//! 文字列の先頭4文字から32bitチャンクを生成
		inline static long MakeChunk(const char* str) {
			return ::spn::MakeChunk(str[0], str[1], str[2], str[3]); }
	};

	//! フリーリストでオブジェクト管理
	template <class T>
	class FreeList {
		private:
			T		_maxV, _curV;
			std::stack<T,std::deque<T>>	_stk;
		public:
			FreeList(T maxV, T startV): _maxV(maxV), _curV(startV) {}
			FreeList(FreeList&& fl): _maxV(fl._maxV), _curV(fl._curV), _stk(fl._stk) {}

			T get() {
				if(_stk.empty()) {
					int ret = _curV++;
					assert(_curV != _maxV);
					return ret;
				}
				T val = _stk.top();
				_stk.pop();
				return val;
			}
			void put(T val) {
				_stk.push(val);
			}
			void swap(FreeList& f) noexcept {
				std::swap(_maxV, f._maxV);
				std::swap(_curV, f._curV);
				std::swap(_stk, f._stk);
			}
	};
	//! ポインタ読み替え変換
	template <class T0, class T1>
	inline T1 RePret(const T0& val) {
		static_assert(sizeof(T0) == sizeof(T1), "invalid reinterpret value");
		return *reinterpret_cast<const T1*>(&val);
	}

	//! 値飽和
	template <class T>
	T Saturate(const T& val, const T& minV, const T& maxV) {
		if(val > maxV)
			return maxV;
		if(val < minV)
			return minV;
		return val;
	}
	template <class T>
	T Saturate(const T& val, const T& range) {
		return Saturate(val, -range, range);
	}
	//! 値補間
	template <class T>
	T Lerp(const T& v0, const T& v1, float r) {
		return (v1-v0)*r + v0;
	}
	//! 値が範囲内に入っているか
	template <class T>
	bool IsInRange(const T& val, const T& vMin, const T& vMax) {
		return val>=vMin && val<=vMax;
	}
	template <class T>
	bool IsInRange(const T& val, const T& vMin, const T& vMax, const T& vEps) {
		return IsInRange(val, vMin-vEps, vMax+vEps);
	}
	//! aがbより大きかったらaからsizeを引いた値を返す
	inline int CndSub(int a, int b, int size) {
		return a - (size & ((b - a) >> 31));
	}
	//! aがbより大きかったらaからbを引いた値を返す
	inline int CndSub(int a, int b) {
		return CndSub(a, b, b);
	}
	//! aがbより小さかったらaにsizeを足した値を返す
	inline int CndAdd(int a, int b, int size) {
		return a + (size & ((a - b) >> 31));
	}
	//! aが0より小さかったらaにsizeを足した値を返す
	inline int CndAdd(int a, int size) {
		return CndAdd(a, 0, size);
	}
	//! aがlowerより小さかったらsizeを足し、upperより大きかったらsizeを引く
	inline int CndRange(int a, int lower, int upper, int size) {
		return a + (size & ((a - lower) >> 31))
					- (size & ((upper - a) >> 31));
	}
	//! aが0より小さかったらsizeを足し、sizeより大きかったらsizeを引く
	inline int CndRange(int a, int size) {
		return CndRange(a, 0, size, size);
	}

	//! 値が近いか
	/*! \param[in] val value to check
		\param[in] vExcept target value
		\param[in] vEps value threshold */
	template <class T>
	bool IsNear(const T& val, const T& vExcept, const T& vEps) {
		return IsInRange(val, vExcept-vEps, vExcept+vEps);
	}

	//! 汎用シングルトン
	template <typename T>
	class Singleton {
		private:
			static T* ms_singleton;
		public:
			Singleton() {
				assert(!ms_singleton || !"initializing error - already initialized");
				int offset = (int)(T*)1 - (int)(Singleton<T>*)(T*)1;
				ms_singleton = (T*)((int)this + offset);
			}
			virtual ~Singleton() {
				assert(ms_singleton || !"destructor error");
				ms_singleton = 0;
			}
			static T& _ref() {
				assert(ms_singleton || !"reference error");
				return *ms_singleton;
			}
	};
	template <typename T>
	T* Singleton<T>::ms_singleton = nullptr;

	//! 固定長文字列
	template <class CT>
	struct FixStrF;
	template <>
	struct FixStrF<char> {
		static void copy(char* dst, int n, const char* src) {
			std::strncpy(dst, src, n);
		}
		static int cmp(const char* v0, const char* v1) {
			return std::strcmp(v0, v1);
		}
	};
	template <>
	struct FixStrF<wchar_t> {
		static void copy(wchar_t* dst, int n, const wchar_t* src) {
			std::wcsncpy(dst, src, n);
		}
		static int cmp(const wchar_t* v0, const wchar_t* v1) {
			return std::wcscmp(v0, v1);
		}
	};
	template <class CT, int N>
	struct FixStr {
		typedef FixStrF<CT> FS;
		typedef CT value_type;
		enum {length=N};
		CT	str[N];

		FixStr(const CT* src=(const CT*)L"") {
			FS::copy(str, N, src);
		}
		FixStr(const CT* src_b, const CT* src_e) {
			int nC = src_e-src_b;
			assert(nC <= sizeof(CT)*(N-1));
			std::memcpy(str, src_b, nC);
			str[nC] = '\0';
		}
		operator const CT* () const {
			return str;
		}
		bool operator < (const CT* s) const {
			return FS::cmp(str, s) < 0;
		}
		bool operator == (const CT* s) const {
			return !FS::cmp(str, s);
		}
		bool operator != (const CT* s) const {
			return !(*this == s);
		}
		FixStr& operator = (const FixStr& s) {
			FS::copy(str, N, s);
			return *this;
		}
		CT& operator [] (int n) {
			return str[n];
		}
		bool operator < (const FixStr& s) const {
			return FS::cmp(str, s) < 0;
		}
		bool operator == (const FixStr& s) const {
			return !FS::cmp(str, s);
		}
		bool operator != (const FixStr& s) const {
			return !(*this == s);
		}
		bool empty() const {
			return str[0] == '\0';
		}
		void clear() {
			str[0] = '\0';
		}
	};
}
<commit_msg>ポインタや値の読み替え関数を追加<commit_after>#pragma once
#include <cassert>
#include <cstring>
#include <cwchar>
#include <stack>
#include <deque>
#include <atomic>
#include <thread>

//! 32bitの4文字チャンクを生成
#define MAKECHUNK(c0,c1,c2,c3) ((c3<<24) | (c2<<16) | (c1<<8) | c0)

namespace spn {
	//! スピンロックによるmutex
	class Synchro {
		private:
			using AThID = std::atomic<std::thread::id>;

			std::atomic_bool	_abLock;	//!< 誰かロックしてるか
			AThID				_idTh;		//!< ロック中のスレッド番号
			int					_iLockNum;	//!< 再帰的なロック用カウンタ

			template <bool Block>
			bool _lock() {
				auto thid = std::this_thread::get_id();
				do {
					bool b = false;
					if(_abLock.compare_exchange_weak(b, true, std::memory_order_acquire)) {
						_iLockNum = 1;
						_idTh.store(thid, std::memory_order_relaxed);
						return true;
					}
					if(_idTh.compare_exchange_weak(thid, thid, std::memory_order_acquire)) {
						++_iLockNum;
						return true;
					}
				} while(Block);
				return false;
			}
		public:
			Synchro(): _abLock(false) {}

			void lock() { _lock<true>(); }
			bool try_lock() { return _lock<false>(); }
			void unlock() {
				if(--_iLockNum == 0)
					_abLock.store(false, std::memory_order_relaxed);
			}
	};

	//! 何もしないダミーmutex
	class PseudoSynch {
		public:
			void lock() {}
			bool try_lock() { return true; }
			void unlock() {}
	};

	//! 4つの8bit値から32bitチャンクを生成
	inline static long MakeChunk(uint8_t c0, uint8_t c1, uint8_t c2, uint8_t c3) {
		return (c3 << 24) | (c2 << 16) | (c1 << 8) | c0; }

	inline uint64_t U64FromU32(uint32_t hv, uint32_t lv) {
		uint64_t ret(hv);
		ret <<= 32;
		ret |= lv;
		return ret;
	}

	struct Text {
		// エンコードタイプ
		enum class CODETYPE {
			UTF_8,
			UTF_16LE,
			UTF_16BE,
			UTF_32LE,
			UTF_32BE,
			ANSI
		};
		//! SJISコードか判定する
		static bool sjis_isMBChar(char c);
		//! SJISコードにおける文字数判定
		static int sjis_strlen(const char* str);
		//! エンコードタイプと判定に使った文字数を返す
		static std::pair<CODETYPE, int> GetEncodeType(const void* ptr);
		//! 文字列の先頭4文字から32bitチャンクを生成
		inline static long MakeChunk(const char* str) {
			return ::spn::MakeChunk(str[0], str[1], str[2], str[3]); }
	};

	//! フリーリストでオブジェクト管理
	template <class T>
	class FreeList {
		private:
			T		_maxV, _curV;
			std::stack<T,std::deque<T>>	_stk;
		public:
			FreeList(T maxV, T startV): _maxV(maxV), _curV(startV) {}
			FreeList(FreeList&& fl): _maxV(fl._maxV), _curV(fl._curV), _stk(fl._stk) {}

			T get() {
				if(_stk.empty()) {
					int ret = _curV++;
					assert(_curV != _maxV);
					return ret;
				}
				T val = _stk.top();
				_stk.pop();
				return val;
			}
			void put(T val) {
				_stk.push(val);
			}
			void swap(FreeList& f) noexcept {
				std::swap(_maxV, f._maxV);
				std::swap(_curV, f._curV);
				std::swap(_stk, f._stk);
			}
	};
	//! ポインタ読み替え変換
	template <class T0, class T1>
	inline T1 RePret(const T0& val) {
		static_assert(sizeof(T0) == sizeof(T1), "invalid reinterpret value");
		return *reinterpret_cast<const T1*>(&val);
	}

	//! 値飽和
	template <class T>
	T Saturate(const T& val, const T& minV, const T& maxV) {
		if(val > maxV)
			return maxV;
		if(val < minV)
			return minV;
		return val;
	}
	template <class T>
	T Saturate(const T& val, const T& range) {
		return Saturate(val, -range, range);
	}
	//! 値補間
	template <class T>
	T Lerp(const T& v0, const T& v1, float r) {
		return (v1-v0)*r + v0;
	}
	//! 値が範囲内に入っているか
	template <class T>
	bool IsInRange(const T& val, const T& vMin, const T& vMax) {
		return val>=vMin && val<=vMax;
	}
	template <class T>
	bool IsInRange(const T& val, const T& vMin, const T& vMax, const T& vEps) {
		return IsInRange(val, vMin-vEps, vMax+vEps);
	}
	//! aがbより大きかったらaからsizeを引いた値を返す
	inline int CndSub(int a, int b, int size) {
		return a - (size & ((b - a) >> 31));
	}
	//! aがbより大きかったらaからbを引いた値を返す
	inline int CndSub(int a, int b) {
		return CndSub(a, b, b);
	}
	//! aがbより小さかったらaにsizeを足した値を返す
	inline int CndAdd(int a, int b, int size) {
		return a + (size & ((a - b) >> 31));
	}
	//! aが0より小さかったらaにsizeを足した値を返す
	inline int CndAdd(int a, int size) {
		return CndAdd(a, 0, size);
	}
	//! aがlowerより小さかったらsizeを足し、upperより大きかったらsizeを引く
	inline int CndRange(int a, int lower, int upper, int size) {
		return a + (size & ((a - lower) >> 31))
					- (size & ((upper - a) >> 31));
	}
	//! aが0より小さかったらsizeを足し、sizeより大きかったらsizeを引く
	inline int CndRange(int a, int size) {
		return CndRange(a, 0, size, size);
	}
	//! ポインタの読み替え
	template <class T, class T2>
	T* ReinterpretPtr(T2* ptr) {
		using TD = typename std::decay<T2>::type;
		static_assert(std::is_integral<TD>::value || std::is_floating_point<TD>::value, "typename T must number");
		return reinterpret_cast<T*>(ptr);
	}
	//! リファレンスの読み替え
	template <class T, class T2>
	T& ReinterpretRef(T2& val) {
		return *reinterpret_cast<T*>(&val);
	}
	//! 値の読み替え
	template <class T, class T2>
	T ReinterpretValue(const T2& val) {
		return *reinterpret_cast<const T*>(&val);
	}

	//! 値が近いか
	/*! \param[in] val value to check
		\param[in] vExcept target value
		\param[in] vEps value threshold */
	template <class T>
	bool IsNear(const T& val, const T& vExcept, const T& vEps) {
		return IsInRange(val, vExcept-vEps, vExcept+vEps);
	}

	//! 汎用シングルトン
	template <typename T>
	class Singleton {
		private:
			static T* ms_singleton;
		public:
			Singleton() {
				assert(!ms_singleton || !"initializing error - already initialized");
				int offset = (int)(T*)1 - (int)(Singleton<T>*)(T*)1;
				ms_singleton = (T*)((int)this + offset);
			}
			virtual ~Singleton() {
				assert(ms_singleton || !"destructor error");
				ms_singleton = 0;
			}
			static T& _ref() {
				assert(ms_singleton || !"reference error");
				return *ms_singleton;
			}
	};
	template <typename T>
	T* Singleton<T>::ms_singleton = nullptr;

	//! 固定長文字列
	template <class CT>
	struct FixStrF;
	template <>
	struct FixStrF<char> {
		static void copy(char* dst, int n, const char* src) {
			std::strncpy(dst, src, n);
		}
		static int cmp(const char* v0, const char* v1) {
			return std::strcmp(v0, v1);
		}
	};
	template <>
	struct FixStrF<wchar_t> {
		static void copy(wchar_t* dst, int n, const wchar_t* src) {
			std::wcsncpy(dst, src, n);
		}
		static int cmp(const wchar_t* v0, const wchar_t* v1) {
			return std::wcscmp(v0, v1);
		}
	};
	template <class CT, int N>
	struct FixStr {
		typedef FixStrF<CT> FS;
		typedef CT value_type;
		enum {length=N};
		CT	str[N];

		FixStr(const CT* src=(const CT*)L"") {
			FS::copy(str, N, src);
		}
		FixStr(const CT* src_b, const CT* src_e) {
			int nC = src_e-src_b;
			assert(nC <= sizeof(CT)*(N-1));
			std::memcpy(str, src_b, nC);
			str[nC] = '\0';
		}
		operator const CT* () const {
			return str;
		}
		bool operator < (const CT* s) const {
			return FS::cmp(str, s) < 0;
		}
		bool operator == (const CT* s) const {
			return !FS::cmp(str, s);
		}
		bool operator != (const CT* s) const {
			return !(*this == s);
		}
		FixStr& operator = (const FixStr& s) {
			FS::copy(str, N, s);
			return *this;
		}
		CT& operator [] (int n) {
			return str[n];
		}
		bool operator < (const FixStr& s) const {
			return FS::cmp(str, s) < 0;
		}
		bool operator == (const FixStr& s) const {
			return !FS::cmp(str, s);
		}
		bool operator != (const FixStr& s) const {
			return !(*this == s);
		}
		bool empty() const {
			return str[0] == '\0';
		}
		void clear() {
			str[0] = '\0';
		}
	};
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreSceneManagerEnumerator.h"

#include "OgreDynLibManager.h"
#include "OgreDynLib.h"
#include "OgreConfigFile.h"
#include "OgreMaterial.h"
#include "OgreException.h"
#include "OgreRoot.h"
#include "OgreLogManager.h"

namespace Ogre {

    //-----------------------------------------------------------------------
    template<> SceneManagerEnumerator* Singleton<SceneManagerEnumerator>::ms_Singleton = 0;
    SceneManagerEnumerator* SceneManagerEnumerator::getSingletonPtr(void)
    {
        return ms_Singleton;
    }
    SceneManagerEnumerator& SceneManagerEnumerator::getSingleton(void)
    {
        assert( ms_Singleton );  return ( *ms_Singleton );
    }

    //-----------------------------------------------------------------------
    SceneManagerEnumerator::SceneManagerEnumerator()
		: mInstanceCreateCount(0), mCurrentRenderSystem(0)
    {
        addFactory(&mDefaultFactory);

    }
    //-----------------------------------------------------------------------
    SceneManagerEnumerator::~SceneManagerEnumerator()
    {
		// Destroy all remaining instances
		// Really should have shutdown and unregistered by now, but catch here in case
		for (Instances::iterator i = mInstances.begin(); i != mInstances.end(); ++i)
		{
			// destroy instances
			for(Factories::iterator f = mFactories.begin(); f != mFactories.end(); ++f)
			{
				if ((*f)->getMetaData().typeName == i->second->getTypeName())
				{
					(*f)->destroyInstance(i->second);
					break;
				}
			}

		}
		mInstances.clear();

    }
	//-----------------------------------------------------------------------
	void SceneManagerEnumerator::addFactory(SceneManagerFactory* fact)
	{
		mFactories.push_back(fact);
		// add to metadata
		mMetaDataList.push_back(&fact->getMetaData());
		// Log
		LogManager::getSingleton().logMessage("SceneManagerFactory for type '" +
			fact->getMetaData().typeName + "' registered.");
	}
	//-----------------------------------------------------------------------
	void SceneManagerEnumerator::removeFactory(SceneManagerFactory* fact)
	{
		// destroy all instances for this factory
		for (Instances::iterator i = mInstances.begin(); i != mInstances.end(); )
		{
			SceneManager* instance = i->second;
			if (instance->getTypeName() == fact->getMetaData().typeName)
			{
				fact->destroyInstance(instance);
				Instances::iterator deli = i++;
				mInstances.erase(deli);
			}
			else
			{
				++i;
			}
		}
		// remove from metadata
		for (MetaDataList::iterator m = mMetaDataList.begin(); m != mMetaDataList.end(); ++m)
		{
			if(*m == &(fact->getMetaData()))
			{
				mMetaDataList.erase(m);
				break;
			}
		}
		mFactories.remove(fact);
	}
	//-----------------------------------------------------------------------
	const SceneManagerMetaData* SceneManagerEnumerator::getMetaData(const String& typeName) const
	{
		for (MetaDataList::const_iterator i = mMetaDataList.begin();
			i != mMetaDataList.end(); ++i)
		{
			if (typeName == (*i)->typeName)
			{
				return *i;
			}
		}

	    OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
		    "No metadata found for scene manager of type '" + typeName + "'",
		    "SceneManagerEnumerator::createSceneManager");

	}
	//-----------------------------------------------------------------------
	SceneManagerEnumerator::MetaDataIterator
	SceneManagerEnumerator::getMetaDataIterator(void) const
	{
		return MetaDataIterator(mMetaDataList.begin(), mMetaDataList.end());

	}
	//-----------------------------------------------------------------------
	SceneManager* SceneManagerEnumerator::createSceneManager(
		const String& typeName, const String& instanceName)
	{
		if (mInstances.find(instanceName) != mInstances.end())
		{
			OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
				"SceneManager instance called '" + instanceName + "' already exists",
				"SceneManagerEnumerator::createSceneManager");
		}

		SceneManager* inst = 0;
		for(Factories::iterator i = mFactories.begin(); i != mFactories.end(); ++i)
		{
			if ((*i)->getMetaData().typeName == typeName)
			{
				if (instanceName.empty())
				{
					// generate a name
					StringUtil::StrStreamType s;
					s << "SceneManagerInstance" << ++mInstanceCreateCount;
					inst = (*i)->createInstance(s.str());
				}
				else
				{
					inst = (*i)->createInstance(instanceName);
				}
				break;
			}
		}

		if (!inst)
		{
			// Error!
			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
				"No factory found for scene manager of type '" + typeName + "'",
				"SceneManagerEnumerator::createSceneManager");
		}

		/// assign rs if already configured
		if (mCurrentRenderSystem)
			inst->_setDestinationRenderSystem(mCurrentRenderSystem);

		mInstances[inst->getName()] = inst;

		return inst;

	}
	//-----------------------------------------------------------------------
	SceneManager* SceneManagerEnumerator::createSceneManager(
		SceneTypeMask typeMask, const String& instanceName)
	{
		if (mInstances.find(instanceName) != mInstances.end())
		{
			OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
				"SceneManager instance called '" + instanceName + "' already exists",
				"SceneManagerEnumerator::createSceneManager");
		}

		SceneManager* inst = 0;
		String name = instanceName;
		if (name.empty())
		{
			// generate a name
			StringUtil::StrStreamType s;
			s << "SceneManagerInstance" << ++mInstanceCreateCount;
			name = s.str();
		}

		// Iterate backwards to find the matching factory registered last
		for(Factories::reverse_iterator i = mFactories.rbegin(); i != mFactories.rend(); ++i)
		{
			if ((*i)->getMetaData().sceneTypeMask & typeMask)
			{
				inst = (*i)->createInstance(name);
				break;
			}
		}

		// use default factory if none
		if (!inst)
			inst = mDefaultFactory.createInstance(name);

		/// assign rs if already configured
		if (mCurrentRenderSystem)
			inst->_setDestinationRenderSystem(mCurrentRenderSystem);

		mInstances[inst->getName()] = inst;

		return inst;

	}
	//-----------------------------------------------------------------------
	void SceneManagerEnumerator::destroySceneManager(SceneManager* sm)
	{
		// Erase instance from map
		mInstances.erase(sm->getName());

		// Find factory to destroy
		for(Factories::iterator i = mFactories.begin(); i != mFactories.end(); ++i)
		{
			if ((*i)->getMetaData().typeName == sm->getTypeName())
			{
				(*i)->destroyInstance(sm);
				break;
			}
		}

	}
	//-----------------------------------------------------------------------
	SceneManager* SceneManagerEnumerator::getSceneManager(const String& instanceName) const
	{
		Instances::const_iterator i = mInstances.find(instanceName);
		if(i != mInstances.end())
		{
			return i->second;
		}
		else
		{
			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
				"SceneManager instance with name '" + instanceName + "' not found.",
				"SceneManagerEnumerator::getSceneManager");
		}

	}
	//---------------------------------------------------------------------
	bool SceneManagerEnumerator::hasSceneManager(const String& instanceName) const
	{
		return mInstances.find(instanceName) != mInstances.end();
	}
	//-----------------------------------------------------------------------
	SceneManagerEnumerator::SceneManagerIterator
	SceneManagerEnumerator::getSceneManagerIterator(void)
	{
		return SceneManagerIterator(mInstances.begin(), mInstances.end());

	}
	//-----------------------------------------------------------------------
    void SceneManagerEnumerator::setRenderSystem(RenderSystem* rs)
    {
		mCurrentRenderSystem = rs;

		for (Instances::iterator i = mInstances.begin(); i != mInstances.end(); ++i)
		{
            i->second->_setDestinationRenderSystem(rs);
        }

    }
    //-----------------------------------------------------------------------
    void SceneManagerEnumerator::shutdownAll(void)
    {
		for (Instances::iterator i = mInstances.begin(); i != mInstances.end(); ++i)
		{
			// shutdown instances (clear scene)
			i->second->clearScene();
        }

    }
    //-----------------------------------------------------------------------
	const String DefaultSceneManagerFactory::FACTORY_TYPE_NAME = "DefaultSceneManager";
    //-----------------------------------------------------------------------
	void DefaultSceneManagerFactory::initMetaData(void) const
	{
		mMetaData.typeName = FACTORY_TYPE_NAME;
		mMetaData.description = "The default scene manager";
		mMetaData.sceneTypeMask = ST_GENERIC;
		mMetaData.worldGeometrySupported = false;
	}
    //-----------------------------------------------------------------------
	SceneManager* DefaultSceneManagerFactory::createInstance(
		const String& instanceName)
	{
		return OGRE_NEW DefaultSceneManager(instanceName);
	}
    //-----------------------------------------------------------------------
	void DefaultSceneManagerFactory::destroyInstance(SceneManager* instance)
	{
		OGRE_DELETE instance;
	}
    //-----------------------------------------------------------------------
    //-----------------------------------------------------------------------
	DefaultSceneManager::DefaultSceneManager(const String& name)
		: SceneManager(name)
	{
	}
    //-----------------------------------------------------------------------
	DefaultSceneManager::~DefaultSceneManager()
	{
	}
    //-----------------------------------------------------------------------
	const String& DefaultSceneManager::getTypeName(void) const
	{
		return DefaultSceneManagerFactory::FACTORY_TYPE_NAME;
	}
    //-----------------------------------------------------------------------

}
<commit_msg>Fixed crash when deleting deleted SceneManagers from list as they are being deleted<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreSceneManagerEnumerator.h"

#include "OgreDynLibManager.h"
#include "OgreDynLib.h"
#include "OgreConfigFile.h"
#include "OgreMaterial.h"
#include "OgreException.h"
#include "OgreRoot.h"
#include "OgreLogManager.h"

namespace Ogre {

    //-----------------------------------------------------------------------
    template<> SceneManagerEnumerator* Singleton<SceneManagerEnumerator>::ms_Singleton = 0;
    SceneManagerEnumerator* SceneManagerEnumerator::getSingletonPtr(void)
    {
        return ms_Singleton;
    }
    SceneManagerEnumerator& SceneManagerEnumerator::getSingleton(void)
    {
        assert( ms_Singleton );  return ( *ms_Singleton );
    }

    //-----------------------------------------------------------------------
    SceneManagerEnumerator::SceneManagerEnumerator()
		: mInstanceCreateCount(0), mCurrentRenderSystem(0)
    {
        addFactory(&mDefaultFactory);

    }
    //-----------------------------------------------------------------------
    SceneManagerEnumerator::~SceneManagerEnumerator()
    {
		// Destroy all remaining instances
		// Really should have shutdown and unregistered by now, but catch here in case
		Instances instancesCopy = mInstances;
		for (Instances::iterator i = instancesCopy.begin(); i != instancesCopy.end(); ++i)
		{
			// destroy instances
			for(Factories::iterator f = mFactories.begin(); f != mFactories.end(); ++f)
			{
				if ((*f)->getMetaData().typeName == i->second->getTypeName())
				{
					(*f)->destroyInstance(i->second);
					mInstances.erase(i->first);
					break;
				}
			}

		}
		mInstances.clear();

    }
	//-----------------------------------------------------------------------
	void SceneManagerEnumerator::addFactory(SceneManagerFactory* fact)
	{
		mFactories.push_back(fact);
		// add to metadata
		mMetaDataList.push_back(&fact->getMetaData());
		// Log
		LogManager::getSingleton().logMessage("SceneManagerFactory for type '" +
			fact->getMetaData().typeName + "' registered.");
	}
	//-----------------------------------------------------------------------
	void SceneManagerEnumerator::removeFactory(SceneManagerFactory* fact)
	{
		// destroy all instances for this factory
		for (Instances::iterator i = mInstances.begin(); i != mInstances.end(); )
		{
			SceneManager* instance = i->second;
			if (instance->getTypeName() == fact->getMetaData().typeName)
			{
				fact->destroyInstance(instance);
				Instances::iterator deli = i++;
				mInstances.erase(deli);
			}
			else
			{
				++i;
			}
		}
		// remove from metadata
		for (MetaDataList::iterator m = mMetaDataList.begin(); m != mMetaDataList.end(); ++m)
		{
			if(*m == &(fact->getMetaData()))
			{
				mMetaDataList.erase(m);
				break;
			}
		}
		mFactories.remove(fact);
	}
	//-----------------------------------------------------------------------
	const SceneManagerMetaData* SceneManagerEnumerator::getMetaData(const String& typeName) const
	{
		for (MetaDataList::const_iterator i = mMetaDataList.begin();
			i != mMetaDataList.end(); ++i)
		{
			if (typeName == (*i)->typeName)
			{
				return *i;
			}
		}

	    OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
		    "No metadata found for scene manager of type '" + typeName + "'",
		    "SceneManagerEnumerator::createSceneManager");

	}
	//-----------------------------------------------------------------------
	SceneManagerEnumerator::MetaDataIterator
	SceneManagerEnumerator::getMetaDataIterator(void) const
	{
		return MetaDataIterator(mMetaDataList.begin(), mMetaDataList.end());

	}
	//-----------------------------------------------------------------------
	SceneManager* SceneManagerEnumerator::createSceneManager(
		const String& typeName, const String& instanceName)
	{
		if (mInstances.find(instanceName) != mInstances.end())
		{
			OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
				"SceneManager instance called '" + instanceName + "' already exists",
				"SceneManagerEnumerator::createSceneManager");
		}

		SceneManager* inst = 0;
		for(Factories::iterator i = mFactories.begin(); i != mFactories.end(); ++i)
		{
			if ((*i)->getMetaData().typeName == typeName)
			{
				if (instanceName.empty())
				{
					// generate a name
					StringUtil::StrStreamType s;
					s << "SceneManagerInstance" << ++mInstanceCreateCount;
					inst = (*i)->createInstance(s.str());
				}
				else
				{
					inst = (*i)->createInstance(instanceName);
				}
				break;
			}
		}

		if (!inst)
		{
			// Error!
			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
				"No factory found for scene manager of type '" + typeName + "'",
				"SceneManagerEnumerator::createSceneManager");
		}

		/// assign rs if already configured
		if (mCurrentRenderSystem)
			inst->_setDestinationRenderSystem(mCurrentRenderSystem);

		mInstances[inst->getName()] = inst;

		return inst;

	}
	//-----------------------------------------------------------------------
	SceneManager* SceneManagerEnumerator::createSceneManager(
		SceneTypeMask typeMask, const String& instanceName)
	{
		if (mInstances.find(instanceName) != mInstances.end())
		{
			OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
				"SceneManager instance called '" + instanceName + "' already exists",
				"SceneManagerEnumerator::createSceneManager");
		}

		SceneManager* inst = 0;
		String name = instanceName;
		if (name.empty())
		{
			// generate a name
			StringUtil::StrStreamType s;
			s << "SceneManagerInstance" << ++mInstanceCreateCount;
			name = s.str();
		}

		// Iterate backwards to find the matching factory registered last
		for(Factories::reverse_iterator i = mFactories.rbegin(); i != mFactories.rend(); ++i)
		{
			if ((*i)->getMetaData().sceneTypeMask & typeMask)
			{
				inst = (*i)->createInstance(name);
				break;
			}
		}

		// use default factory if none
		if (!inst)
			inst = mDefaultFactory.createInstance(name);

		/// assign rs if already configured
		if (mCurrentRenderSystem)
			inst->_setDestinationRenderSystem(mCurrentRenderSystem);

		mInstances[inst->getName()] = inst;

		return inst;

	}
	//-----------------------------------------------------------------------
	void SceneManagerEnumerator::destroySceneManager(SceneManager* sm)
	{
		// Erase instance from map
		mInstances.erase(sm->getName());

		// Find factory to destroy
		for(Factories::iterator i = mFactories.begin(); i != mFactories.end(); ++i)
		{
			if ((*i)->getMetaData().typeName == sm->getTypeName())
			{
				(*i)->destroyInstance(sm);
				break;
			}
		}

	}
	//-----------------------------------------------------------------------
	SceneManager* SceneManagerEnumerator::getSceneManager(const String& instanceName) const
	{
		Instances::const_iterator i = mInstances.find(instanceName);
		if(i != mInstances.end())
		{
			return i->second;
		}
		else
		{
			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
				"SceneManager instance with name '" + instanceName + "' not found.",
				"SceneManagerEnumerator::getSceneManager");
		}

	}
	//---------------------------------------------------------------------
	bool SceneManagerEnumerator::hasSceneManager(const String& instanceName) const
	{
		return mInstances.find(instanceName) != mInstances.end();
	}
	//-----------------------------------------------------------------------
	SceneManagerEnumerator::SceneManagerIterator
	SceneManagerEnumerator::getSceneManagerIterator(void)
	{
		return SceneManagerIterator(mInstances.begin(), mInstances.end());

	}
	//-----------------------------------------------------------------------
    void SceneManagerEnumerator::setRenderSystem(RenderSystem* rs)
    {
		mCurrentRenderSystem = rs;

		for (Instances::iterator i = mInstances.begin(); i != mInstances.end(); ++i)
		{
            i->second->_setDestinationRenderSystem(rs);
        }

    }
    //-----------------------------------------------------------------------
    void SceneManagerEnumerator::shutdownAll(void)
    {
		for (Instances::iterator i = mInstances.begin(); i != mInstances.end(); ++i)
		{
			// shutdown instances (clear scene)
			i->second->clearScene();
        }

    }
    //-----------------------------------------------------------------------
	const String DefaultSceneManagerFactory::FACTORY_TYPE_NAME = "DefaultSceneManager";
    //-----------------------------------------------------------------------
	void DefaultSceneManagerFactory::initMetaData(void) const
	{
		mMetaData.typeName = FACTORY_TYPE_NAME;
		mMetaData.description = "The default scene manager";
		mMetaData.sceneTypeMask = ST_GENERIC;
		mMetaData.worldGeometrySupported = false;
	}
    //-----------------------------------------------------------------------
	SceneManager* DefaultSceneManagerFactory::createInstance(
		const String& instanceName)
	{
		return OGRE_NEW DefaultSceneManager(instanceName);
	}
    //-----------------------------------------------------------------------
	void DefaultSceneManagerFactory::destroyInstance(SceneManager* instance)
	{
		OGRE_DELETE instance;
	}
    //-----------------------------------------------------------------------
    //-----------------------------------------------------------------------
	DefaultSceneManager::DefaultSceneManager(const String& name)
		: SceneManager(name)
	{
	}
    //-----------------------------------------------------------------------
	DefaultSceneManager::~DefaultSceneManager()
	{
	}
    //-----------------------------------------------------------------------
	const String& DefaultSceneManager::getTypeName(void) const
	{
		return DefaultSceneManagerFactory::FACTORY_TYPE_NAME;
	}
    //-----------------------------------------------------------------------

}
<|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 "printing/emf_win.h"

// For quick access.
#include <wingdi.h>

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// This test is automatically disabled if no printer named "UnitTest Printer" is
// available.
class EmfPrintingTest : public testing::Test {
 public:
  typedef testing::Test Parent;
  static bool IsTestCaseDisabled() {
    // It is assumed this printer is a HP Color LaserJet 4550 PCL or 4700.
    HDC hdc = CreateDC(L"WINSPOOL", L"UnitTest Printer", NULL, NULL);
    if (!hdc)
      return true;
    DeleteDC(hdc);
    return false;
  }
};

}  // namespace

TEST(EmfTest, DC) {
  static const int EMF_HEADER_SIZE = 128;

  // Simplest use case.
  printing::Emf emf;
  RECT rect = {100, 100, 200, 200};
  HDC hdc = CreateCompatibleDC(NULL);
  EXPECT_TRUE(hdc != NULL);
  EXPECT_TRUE(emf.CreateDc(hdc, &rect));
  EXPECT_TRUE(emf.hdc() != NULL);
  // In theory, you'd use the HDC with GDI functions here.
  EXPECT_TRUE(emf.CloseDc());
  unsigned size = emf.GetDataSize();
  EXPECT_EQ(size, EMF_HEADER_SIZE);
  std::vector<BYTE> data;
  EXPECT_TRUE(emf.GetData(&data));
  EXPECT_EQ(data.size(), size);
  emf.CloseEmf();
  EXPECT_TRUE(DeleteDC(hdc));

  // Playback the data.
  hdc = CreateCompatibleDC(NULL);
  EXPECT_TRUE(hdc);
  EXPECT_TRUE(emf.CreateFromData(&data.front(), size));
  RECT output_rect = {0, 0, 10, 10};
  EXPECT_TRUE(emf.Playback(hdc, &output_rect));
  EXPECT_TRUE(DeleteDC(hdc));
}

// TODO(sverrir): Re-enable after win_printing_context has been moved here.
/*
#include "chrome/browser/printing/win_printing_context.h"
#include "chrome/common/chrome_paths.h"

// Disabled if no "UnitTest printer" exist. Useful to reproduce bug 1186598.
TEST_F(EmfPrintingTest, Enumerate) {
  if (IsTestCaseDisabled())
    return;

  printing::PrintSettings settings;

  // My test case is a HP Color LaserJet 4550 PCL.
  settings.set_device_name(L"UnitTest Printer");

  // Initialize it.
  printing::PrintingContext context;
  EXPECT_EQ(context.InitWithSettings(settings), printing::PrintingContext::OK);

  std::wstring test_file;
  PathService::Get(chrome::DIR_TEST_DATA, &test_file);

  // Load any EMF with an image.
  printing::Emf emf;
  file_util::AppendToPath(&test_file, L"printing");
  file_util::AppendToPath(&test_file, L"test4.emf");
  std::string emf_data;
  file_util::ReadFileToString(test_file, &emf_data);
  ASSERT_TRUE(emf_data.size());
  EXPECT_TRUE(emf.CreateFromData(&emf_data[0], emf_data.size()));

  // This will print to file. The reason is that when running inside a
  // unit_test, printing::PrintingContext automatically dumps its files to the
  // current directory.
  // TODO(maruel):  Clean the .PRN file generated in current directory.
  context.NewDocument(L"EmfTest.Enumerate");
  context.NewPage();
  // Process one at a time.
  printing::Emf::Enumerator emf_enum(emf, context.context(),
                                &emf.GetBounds().ToRECT());
  for (printing::Emf::Enumerator::const_iterator itr = emf_enum.begin();
       itr != emf_enum.end();
       ++itr) {
    // To help debugging.
    ptrdiff_t index = itr - emf_enum.begin();
    // If you get this assert, you need to lookup iType in wingdi.h. It starts
    // with EMR_HEADER.
    EMR_HEADER;
    EXPECT_TRUE(itr->SafePlayback(NULL)) <<
        " index: " << index << " type: " << itr->record()->iType;
  }
  context.PageDone();
  context.DocumentDone();
}
*/
<commit_msg>Fix deps failure (include file was in a multi line comment).<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 "printing/emf_win.h"

// For quick access.
#include <wingdi.h>

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// This test is automatically disabled if no printer named "UnitTest Printer" is
// available.
class EmfPrintingTest : public testing::Test {
 public:
  typedef testing::Test Parent;
  static bool IsTestCaseDisabled() {
    // It is assumed this printer is a HP Color LaserJet 4550 PCL or 4700.
    HDC hdc = CreateDC(L"WINSPOOL", L"UnitTest Printer", NULL, NULL);
    if (!hdc)
      return true;
    DeleteDC(hdc);
    return false;
  }
};

}  // namespace

TEST(EmfTest, DC) {
  static const int EMF_HEADER_SIZE = 128;

  // Simplest use case.
  printing::Emf emf;
  RECT rect = {100, 100, 200, 200};
  HDC hdc = CreateCompatibleDC(NULL);
  EXPECT_TRUE(hdc != NULL);
  EXPECT_TRUE(emf.CreateDc(hdc, &rect));
  EXPECT_TRUE(emf.hdc() != NULL);
  // In theory, you'd use the HDC with GDI functions here.
  EXPECT_TRUE(emf.CloseDc());
  unsigned size = emf.GetDataSize();
  EXPECT_EQ(size, EMF_HEADER_SIZE);
  std::vector<BYTE> data;
  EXPECT_TRUE(emf.GetData(&data));
  EXPECT_EQ(data.size(), size);
  emf.CloseEmf();
  EXPECT_TRUE(DeleteDC(hdc));

  // Playback the data.
  hdc = CreateCompatibleDC(NULL);
  EXPECT_TRUE(hdc);
  EXPECT_TRUE(emf.CreateFromData(&data.front(), size));
  RECT output_rect = {0, 0, 10, 10};
  EXPECT_TRUE(emf.Playback(hdc, &output_rect));
  EXPECT_TRUE(DeleteDC(hdc));
}

// TODO(sverrir): Re-enable after win_printing_context has been moved here.
/*

// DEPS check fails even if include is in a multi line comment:
// #include "chrome/browser/printing/win_printing_context.h"
// #include "chrome/common/chrome_paths.h"

// Disabled if no "UnitTest printer" exist. Useful to reproduce bug 1186598.
TEST_F(EmfPrintingTest, Enumerate) {
  if (IsTestCaseDisabled())
    return;

  printing::PrintSettings settings;

  // My test case is a HP Color LaserJet 4550 PCL.
  settings.set_device_name(L"UnitTest Printer");

  // Initialize it.
  printing::PrintingContext context;
  EXPECT_EQ(context.InitWithSettings(settings), printing::PrintingContext::OK);

  std::wstring test_file;
  PathService::Get(chrome::DIR_TEST_DATA, &test_file);

  // Load any EMF with an image.
  printing::Emf emf;
  file_util::AppendToPath(&test_file, L"printing");
  file_util::AppendToPath(&test_file, L"test4.emf");
  std::string emf_data;
  file_util::ReadFileToString(test_file, &emf_data);
  ASSERT_TRUE(emf_data.size());
  EXPECT_TRUE(emf.CreateFromData(&emf_data[0], emf_data.size()));

  // This will print to file. The reason is that when running inside a
  // unit_test, printing::PrintingContext automatically dumps its files to the
  // current directory.
  // TODO(maruel):  Clean the .PRN file generated in current directory.
  context.NewDocument(L"EmfTest.Enumerate");
  context.NewPage();
  // Process one at a time.
  printing::Emf::Enumerator emf_enum(emf, context.context(),
                                &emf.GetBounds().ToRECT());
  for (printing::Emf::Enumerator::const_iterator itr = emf_enum.begin();
       itr != emf_enum.end();
       ++itr) {
    // To help debugging.
    ptrdiff_t index = itr - emf_enum.begin();
    // If you get this assert, you need to lookup iType in wingdi.h. It starts
    // with EMR_HEADER.
    EMR_HEADER;
    EXPECT_TRUE(itr->SafePlayback(NULL)) <<
        " index: " << index << " type: " << itr->record()->iType;
  }
  context.PageDone();
  context.DocumentDone();
}
*/
<|endoftext|>


<commit_before>// Copyright  2010-2013 The CefSharp Project. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "Stdafx.h"

#include "BrowserCore.h"

namespace CefSharp
{
    void BrowserCore::CheckBrowserInitialization()
    {
        if (!_isBrowserInitialized)
        {
            throw gcnew InvalidOperationException("Browser is not initialized");
        }
    }

    void BrowserCore::RegisterJsObject(String^ name, Object^ objectToBind)
    {
        _boundObjects[name] = objectToBind;
    }

    IDictionary<String^, Object^>^ BrowserCore::GetBoundObjects()
    {
        return _boundObjects;
    }

    void BrowserCore::SetNavState(bool isLoading, bool canGoBack, bool canGoForward)
    {
        if(isLoading != _isLoading)
        {
            _isLoading = isLoading;
            PropertyChanged(this, gcnew PropertyChangedEventArgs(L"IsLoading"));
        }

        if(canGoBack != _canGoBack)
        {
            _canGoBack = canGoBack;
            PropertyChanged(this, gcnew PropertyChangedEventArgs(L"CanGoBack"));
        }

        if(canGoForward != _canGoForward)
        {
            _canGoForward = canGoForward;
            PropertyChanged(this, gcnew PropertyChangedEventArgs(L"CanGoForward"));
        }
    }

    void BrowserCore::OnInitialized()
    {
        _isBrowserInitialized = true;
        PropertyChanged(this, gcnew PropertyChangedEventArgs(L"IsBrowserInitialized"));
    }

    void BrowserCore::OnLoad()
    {
        _loadCompleted->Reset();
    }

    void BrowserCore::OnFrameLoadStart()
    {
        _loadCompleted->AddCount();
    }

    void BrowserCore::OnFrameLoadEnd()
    {
        _loadCompleted->Signal();
    }
}<commit_msg>Whitespace etc.<commit_after>// Copyright  2010-2013 The CefSharp Project. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "Stdafx.h"
#include "BrowserCore.h"

namespace CefSharp
{
    void BrowserCore::CheckBrowserInitialization()
    {
        if (!_isBrowserInitialized)
        {
            throw gcnew InvalidOperationException("Browser is not initialized");
        }
    }

    void BrowserCore::RegisterJsObject(String^ name, Object^ objectToBind)
    {
        _boundObjects[name] = objectToBind;
    }

    IDictionary<String^, Object^>^ BrowserCore::GetBoundObjects()
    {
        return _boundObjects;
    }

    void BrowserCore::SetNavState(bool isLoading, bool canGoBack, bool canGoForward)
    {
        if (isLoading != _isLoading)
        {
            _isLoading = isLoading;
            PropertyChanged(this, gcnew PropertyChangedEventArgs(L"IsLoading"));
        }

        if (canGoBack != _canGoBack)
        {
            _canGoBack = canGoBack;
            PropertyChanged(this, gcnew PropertyChangedEventArgs(L"CanGoBack"));
        }

        if (canGoForward != _canGoForward)
        {
            _canGoForward = canGoForward;
            PropertyChanged(this, gcnew PropertyChangedEventArgs(L"CanGoForward"));
        }
    }

    void BrowserCore::OnInitialized()
    {
        _isBrowserInitialized = true;
        PropertyChanged(this, gcnew PropertyChangedEventArgs(L"IsBrowserInitialized"));
    }

    void BrowserCore::OnLoad()
    {
        _loadCompleted->Reset();
    }

    void BrowserCore::OnFrameLoadStart()
    {
        _loadCompleted->AddCount();
    }

    void BrowserCore::OnFrameLoadEnd()
    {
        _loadCompleted->Signal();
    }
}<|endoftext|>