<commit_before>/*
 * Copyright (c) 2017, Ubiquity Robotics
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. 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 OWNER 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.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of the FreeBSD Project.
 *
 */

#include <ros/ros.h>
#include <tf/transform_datatypes.h>
#include <tf2/LinearMath/Transform.h>
#include <tf2_ros/buffer.h>
#include <tf2_ros/transform_listener.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>

#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/Twist.h>
#include <nav_msgs/Path.h>
#include <sensor_msgs/LaserScan.h>

#include <actionlib/server/simple_action_server.h>
#include <move_base_msgs/MoveBaseAction.h>

#include <string>

typedef actionlib::SimpleActionServer<move_base_msgs::MoveBaseAction> MoveBaseActionServer;

class MoveBasic {
  private:
    ros::Subscriber goalSub;
    ros::Subscriber scanSub;

    ros::Publisher goalPub;
    ros::Publisher cmdPub;
    ros::Publisher pathPub;

    std::unique_ptr<MoveBaseActionServer> actionServer;

    tf2_ros::Buffer tfBuffer;
    tf2_ros::TransformListener listener;

    double maxAngularVelocity;
    double minAngularVelocity;
    double angularAcceleration;
    double angularTolerance;

    double minLinearVelocity;
    double maxLinearVelocity;
    double linearAcceleration;
    double linearTolerance;

    double robotWidth;

    tf2::Transform goalOdom;
    bool obstacleDetected;

    void abortGoal(const std::string msg);

    void scanCallback(const sensor_msgs::LaserScan::ConstPtr &msg);

    void goalCallback(const geometry_msgs::PoseStamped::ConstPtr &msg);

    void executeAction(const move_base_msgs::MoveBaseGoalConstPtr& goal);

    void sendCmd(double angular, double linear);

    bool getTransform(const std::string& from, const std::string& to,
                      tf2::Transform& tf);

    bool handleRotation();
    bool handleLinear();

  public:
    MoveBasic();

    void run();

    bool moveLinear(double requestedDistance);
    bool rotateAbs(double requestedYaw);
    bool rotateRel(double yaw);
};

// Radians to degrees

static double rad2deg(double rad)
{
    return rad * 180.0 / M_PI;
}

// Get the sign of a number

static int sign(double n)
{
    return (n <0 ? -1 : 1);
}

// Adjust angle to be between -PI and PI

static void normalizeAngle(double& angle)
{
    if (angle < -M_PI) {
         angle += 2 * M_PI;
    }
    if (angle > M_PI) {
        angle -= 2 * M_PI;
    }
}

// retreive the 3 DOF we are interested in from a Transform

static void getPose(const tf2::Transform& tf, double& x, double& y, double& yaw)
{
    tf2::Vector3 trans = tf.getOrigin();
    x = trans.x();
    y = trans.y();

    double roll, pitch;
    tf.getBasis().getRPY(roll, pitch, yaw);
}

// Constructor

MoveBasic::MoveBasic(): tfBuffer(ros::Duration(30.0)),
                        listener(tfBuffer), obstacleDetected(false)
{
    ros::NodeHandle nh("~");

    nh.param<double>("min_angular_velocity", minAngularVelocity, 0.05);
    nh.param<double>("max_angular_velocity", maxAngularVelocity, 1.0);
    nh.param<double>("angular_acceleration", angularAcceleration, 0.3);
    nh.param<double>("angular_tolerance", angularTolerance, 0.01);

    nh.param<double>("min_linear_velocity", minLinearVelocity, 0.1);
    nh.param<double>("max_linear_velocity", maxLinearVelocity, 0.5);
    nh.param<double>("linear_acceleration", linearAcceleration, 0.5);
    nh.param<double>("linear_tolerance", linearTolerance, 0.01);

    nh.param<double>("robot_width", robotWidth, 0.35);

    cmdPub = ros::Publisher(nh.advertise<geometry_msgs::Twist>("/cmd_vel", 1));

    pathPub = ros::Publisher(nh.advertise<nav_msgs::Path>("/plan", 1));

    scanSub = nh.subscribe("/scan", 1, &MoveBasic::scanCallback, this);

    goalSub = nh.subscribe("/move_base_simple/goal", 1,
                            &MoveBasic::goalCallback, this);

    ros::NodeHandle actionNh("");
    actionServer.reset(new MoveBaseActionServer(actionNh,
        "move_base", boost::bind(&MoveBasic::executeAction, this, _1), false));

    actionServer->start();
    goalPub = actionNh.advertise<move_base_msgs::MoveBaseActionGoal>(
      "/move_base/goal", 1);

    ROS_INFO("Move Basic ready");
}

// Lookup the specified transform, returns true on success

bool MoveBasic::getTransform(const std::string& from, const std::string& to,
                             tf2::Transform& tf)
{
    try {
        geometry_msgs::TransformStamped tfs =
            tfBuffer.lookupTransform(to, from, ros::Time(0));
        tf2::fromMsg(tfs.transform, tf);
        return true;
    }
    catch (tf2::TransformException &ex) {
         ROS_WARN("%s", ex.what());
         return false;
    }
}

// Called when a laser scan is received assumes laser scanner is
// mounted at around base_link. Sets obstacleDetected

void MoveBasic::scanCallback(const sensor_msgs::LaserScan::ConstPtr &msg)
{
    double angle = msg->angle_min;
    double increment = msg->angle_increment;
    double width_2 = robotWidth / 2.0;
    double rangeMin = msg->range_min;
    double minDist = msg->range_max;

    for (int i=0; i<msg->ranges.size(); i++) {
        angle += increment;

        double r = msg->ranges[i];

        // ignore bogus samples
        if (r < rangeMin) {
            continue;
        }

        double y = r * sin(angle);

        // ignore anything outside width of robot
        if (std::abs(y) > width_2) {
            continue;
        }

        double x = r * cos(angle);

        // ignore anything behind center of lidar
        if (x < 0) {
            continue;
        }

        if (x < minDist) {
            minDist = x;
        }
    }
    // assume error condition if there is an obstacle within a
    // distance that robot could travel in half a second
    obstacleDetected = minDist < maxLinearVelocity / 2.0;
}

// Called when a simple goal message is received

void MoveBasic::goalCallback(const geometry_msgs::PoseStamped::ConstPtr &msg)
{
    ROS_INFO("Received simple goal");
    // send the goal to the action server
    move_base_msgs::MoveBaseActionGoal actionGoal;
    actionGoal.header.stamp = ros::Time::now();
    actionGoal.goal.target_pose = *msg;

    goalPub.publish(actionGoal);
}

// Abort goal and print message
void MoveBasic::abortGoal(const std::string msg)
{
    actionServer->setAborted(move_base_msgs::MoveBaseResult(), msg);
    ROS_ERROR("%s", msg.c_str());
}

// Called when an action goal is received

void MoveBasic::executeAction(const move_base_msgs::MoveBaseGoalConstPtr& msg)
{
    tf2::Transform goal;
    tf2::fromMsg(msg->target_pose.pose, goal);
    std::string frameId = msg->target_pose.header.frame_id;

    // Needed for RobotCommander
    if (frameId[0] == '/')
        frameId = frameId.substr(1);

    double x, y, yaw;
    getPose(goal, x, y, yaw);
    ROS_INFO("Received goal %f %f %f", x, y, rad2deg(yaw));

    tf2::Transform tfMapOdom;
    if (!getTransform(frameId, "odom", tfMapOdom)) {
        abortGoal("Cannot determine robot pose");
        return;
    }
    goalOdom = tfMapOdom * goal;

    getPose(goalOdom, x, y, yaw);
    ROS_INFO("Goal in odom  %f %f %f", x, y, rad2deg(yaw));

    nav_msgs::Path path;
    geometry_msgs::PoseStamped p0, p1;
    path.header.frame_id = "odom";
    p0.pose.position.x = x;
    p0.pose.position.y = y;
    path.poses.push_back(p0);

    tf2::Transform poseOdom;
    if (!getTransform("base_link", "odom", poseOdom)) {
         abortGoal("Cannot determine robot pose");
         return;
    }
    getPose(poseOdom, x, y, yaw);
    p1.pose.position.x = x;
    p1.pose.position.y = y;
    path.poses.push_back(p1);

    pathPub.publish(path);

    if (!handleRotation()) {
        return;
    }
    if (!handleLinear()) {
        return;
    }
    getPose(goalOdom, x, y, yaw);
    rotateAbs(yaw);

    actionServer->setSucceeded();
}

// Send a motion command

void MoveBasic::sendCmd(double angular, double linear)
{
   geometry_msgs::Twist msg;
   msg.angular.z = angular;
   msg.linear.x = linear;

   cmdPub.publish(msg);
}

// Main loop

void MoveBasic::run()
{
    ros::Rate r(20);
    while (ros::ok()) {
        ros::spinOnce();
        r.sleep();
    }
}

// Do angular part of goal

bool MoveBasic::handleRotation()
{
    tf2::Transform poseOdom;
    if (!getTransform("base_link", "odom", poseOdom)) {
         ROS_WARN("Cannot determine robot pose for rotation");
         return false;
    }

    tf2::Vector3 linear = goalOdom.getOrigin() - poseOdom.getOrigin();
    // don't do initial rotation if there is no translation
    if (linear.length() == 0) {
        return true;
    }
    double requestedYaw = atan2(linear.y(), linear.x());

    if (requestedYaw == 0) {
        return true;
    }
    return rotateAbs(requestedYaw);
}

// Rotate relative to current orientation

bool MoveBasic::rotateRel(double yaw)
{
    tf2::Transform poseOdom;
    if (!getTransform("base_link", "odom", poseOdom)) {
         abortGoal("Cannot determine robot pose for rotation");
         return false;
    }

    double x, y, currentYaw;
    getPose(poseOdom, x, y, currentYaw);
    double requestedYaw = currentYaw + yaw;
    normalizeAngle(requestedYaw);

    return rotateAbs(requestedYaw);
}

// Rotate to specified orientation (in radians)

bool MoveBasic::rotateAbs(double requestedYaw)
{
    bool done = false;
    ros::Rate r(50);

    int oscillations = 0;
    double prevAngleRemaining = 0;

    while (!done && ros::ok()) {
        ros::spinOnce();
        r.sleep();

        double x, y, currentYaw;
        tf2::Transform poseOdom;
        if (!getTransform("base_link", "odom", poseOdom)) {
            abortGoal("Cannot determine robot pose for rotation");
            return false;
        }
        getPose(poseOdom, x, y, currentYaw);

        double angleRemaining = requestedYaw - currentYaw;
        normalizeAngle(angleRemaining);

        double speed = std::max(minAngularVelocity,
            std::min(maxAngularVelocity,
              std::sqrt(2.0 * angularAcceleration *
                (std::abs(angleRemaining) - angularTolerance))));

        double velocity = 0;

        if (angleRemaining < 0) {
            velocity = -speed;
        }
        else {
            velocity = speed;
        }

        if (sign(prevAngleRemaining) != sign(angleRemaining)) {
            oscillations++;
        }
        prevAngleRemaining = angleRemaining;

        if (actionServer->isNewGoalAvailable()) {
            ROS_INFO("Stopping rotation due to new goal");
            done = true;
            velocity = 0;
        }

        //ROS_INFO("%f %f %f", rad2deg(angleRemaining), angleRemaining, velocity);

        if (std::abs(angleRemaining) < angularTolerance || oscillations > 2) {
            velocity = 0;
            done = true;
            ROS_INFO("Done rotation, error %f degrees", rad2deg(angleRemaining));
        }
        sendCmd(velocity, 0);
    }
    return done;
}

// Do linear part of goal

bool MoveBasic::handleLinear()
{
    bool done = false;

    tf2::Transform poseOdomInitial;
    if (!getTransform("base_link", "odom", poseOdomInitial)) {
         ROS_WARN("Cannot determine robot pose for linear");
         return false;
    }

    tf2::Vector3 linear = goalOdom.getOrigin() - poseOdomInitial.getOrigin();
    double requestedDistance = linear.length();;
    ROS_INFO("Requested distance %f", requestedDistance);

    return moveLinear(requestedDistance);
}

// Move forward specified distance

bool MoveBasic::moveLinear(double requestedDistance)
{
    bool done = false;
    ros::Rate r(50);

    tf2::Transform poseOdomInitial;
    if (!getTransform("base_link", "odom", poseOdomInitial)) {
         abortGoal("Cannot determine robot pose for linear");
         return false;
    }

    while (!done && ros::ok()) {
        ros::spinOnce();
        r.sleep();

        tf2::Transform poseOdom;
        if (!getTransform("base_link", "odom", poseOdom)) {
             ROS_WARN("Cannot determine robot pose for linear");
             continue;
        }

        if (obstacleDetected) {
            abortGoal("Obstacle detected");
            return false;
        }

        tf2::Vector3 travelled = poseOdomInitial.getOrigin() - poseOdom.getOrigin();
        double distTravelled = travelled.length();;

        double distRemaining = requestedDistance - distTravelled;

        double velocity = std::max(minLinearVelocity,
            std::min(maxLinearVelocity, std::min(
              std::sqrt(2.0 * linearAcceleration * std::abs(distTravelled)),
              std::sqrt(2.0 * linearAcceleration * std::abs(distRemaining)))));

        if (actionServer->isNewGoalAvailable()) {
            ROS_INFO("Stopping rotation due to new goal");
            done = true;
            velocity = 0;
        }

        //ROS_INFO("%f %f %f", distTravelled, distRemaining, velocity);

        if (distTravelled > requestedDistance - linearTolerance) {
            velocity = 0;
            done = true;
            ROS_INFO("Done linear, error %f meters", distRemaining);
        }
        sendCmd(0, velocity);
    }
    return done;
}

int main(int argc, char ** argv) {
    ros::init(argc, argv, "move_basic");
    MoveBasic mb_node;
    mb_node.run();

    return 0;
}
<commit_msg>Use floats for range computation. Pause for obstacles instead of aborting<commit_after>/*
 * Copyright (c) 2017, Ubiquity Robotics
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. 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 OWNER 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.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of the FreeBSD Project.
 *
 */

#include <ros/ros.h>
#include <tf/transform_datatypes.h>
#include <tf2/LinearMath/Transform.h>
#include <tf2_ros/buffer.h>
#include <tf2_ros/transform_listener.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>

#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/Twist.h>
#include <nav_msgs/Path.h>
#include <sensor_msgs/LaserScan.h>

#include <actionlib/server/simple_action_server.h>
#include <move_base_msgs/MoveBaseAction.h>

#include <string>

typedef actionlib::SimpleActionServer<move_base_msgs::MoveBaseAction> MoveBaseActionServer;

class MoveBasic {
  private:
    ros::Subscriber goalSub;
    ros::Subscriber scanSub;

    ros::Publisher goalPub;
    ros::Publisher cmdPub;
    ros::Publisher pathPub;

    std::unique_ptr<MoveBaseActionServer> actionServer;

    tf2_ros::Buffer tfBuffer;
    tf2_ros::TransformListener listener;

    double maxAngularVelocity;
    double minAngularVelocity;
    double angularAcceleration;
    double angularTolerance;

    double minLinearVelocity;
    double maxLinearVelocity;
    double linearAcceleration;
    double linearTolerance;

    double robotWidth;
    double obstacleWaitLimit;

    tf2::Transform goalOdom;
    bool obstacleDetected;

    void abortGoal(const std::string msg);

    void scanCallback(const sensor_msgs::LaserScan::ConstPtr &msg);

    void goalCallback(const geometry_msgs::PoseStamped::ConstPtr &msg);

    void executeAction(const move_base_msgs::MoveBaseGoalConstPtr& goal);

    void sendCmd(double angular, double linear);

    bool getTransform(const std::string& from, const std::string& to,
                      tf2::Transform& tf);

    bool handleRotation();
    bool handleLinear();

  public:
    MoveBasic();

    void run();

    bool moveLinear(double requestedDistance);
    bool rotateAbs(double requestedYaw);
    bool rotateRel(double yaw);
};

// Radians to degrees

static double rad2deg(double rad)
{
    return rad * 180.0 / M_PI;
}

// Get the sign of a number

static int sign(double n)
{
    return (n <0 ? -1 : 1);
}

// Adjust angle to be between -PI and PI

static void normalizeAngle(double& angle)
{
    if (angle < -M_PI) {
         angle += 2 * M_PI;
    }
    if (angle > M_PI) {
        angle -= 2 * M_PI;
    }
}

// retreive the 3 DOF we are interested in from a Transform

static void getPose(const tf2::Transform& tf, double& x, double& y, double& yaw)
{
    tf2::Vector3 trans = tf.getOrigin();
    x = trans.x();
    y = trans.y();

    double roll, pitch;
    tf.getBasis().getRPY(roll, pitch, yaw);
}

// Constructor

MoveBasic::MoveBasic(): tfBuffer(ros::Duration(30.0)),
                        listener(tfBuffer), obstacleDetected(false)
{
    ros::NodeHandle nh("~");

    nh.param<double>("min_angular_velocity", minAngularVelocity, 0.05);
    nh.param<double>("max_angular_velocity", maxAngularVelocity, 1.0);
    nh.param<double>("angular_acceleration", angularAcceleration, 0.3);
    nh.param<double>("angular_tolerance", angularTolerance, 0.01);

    nh.param<double>("min_linear_velocity", minLinearVelocity, 0.1);
    nh.param<double>("max_linear_velocity", maxLinearVelocity, 0.5);
    nh.param<double>("linear_acceleration", linearAcceleration, 0.5);
    nh.param<double>("linear_tolerance", linearTolerance, 0.01);

    nh.param<double>("robot_width", robotWidth, 0.35);
    nh.param<double>("obstacle_wait_limit", obstacleWaitLimit, 10.0);

    cmdPub = ros::Publisher(nh.advertise<geometry_msgs::Twist>("/cmd_vel", 1));

    pathPub = ros::Publisher(nh.advertise<nav_msgs::Path>("/plan", 1));

    scanSub = nh.subscribe("/scan", 1, &MoveBasic::scanCallback, this);

    goalSub = nh.subscribe("/move_base_simple/goal", 1,
                            &MoveBasic::goalCallback, this);

    ros::NodeHandle actionNh("");
    actionServer.reset(new MoveBaseActionServer(actionNh,
        "move_base", boost::bind(&MoveBasic::executeAction, this, _1), false));

    actionServer->start();
    goalPub = actionNh.advertise<move_base_msgs::MoveBaseActionGoal>(
      "/move_base/goal", 1);

    ROS_INFO("Move Basic ready");
}

// Lookup the specified transform, returns true on success

bool MoveBasic::getTransform(const std::string& from, const std::string& to,
                             tf2::Transform& tf)
{
    try {
        geometry_msgs::TransformStamped tfs =
            tfBuffer.lookupTransform(to, from, ros::Time(0));
        tf2::fromMsg(tfs.transform, tf);
        return true;
    }
    catch (tf2::TransformException &ex) {
         ROS_WARN("%s", ex.what());
         return false;
    }
}

// Called when a laser scan is received assumes laser scanner is
// mounted at around base_link. Sets obstacleDetected

void MoveBasic::scanCallback(const sensor_msgs::LaserScan::ConstPtr &msg)
{
    float angle = msg->angle_min;
    float increment = msg->angle_increment;
    float width_2 = robotWidth / 2.0;
    float rangeMin = msg->range_min;
    float minDist = msg->range_max;

    for (int i=0; i<msg->ranges.size(); i++) {
        angle += increment;

        float r = msg->ranges[i];

        // ignore bogus samples
        if (std::isnan(r) || r < rangeMin) {
            continue;
        }

        float y = r * sin(angle);

        // ignore anything outside width of robot
        if (std::abs(y) > width_2) {
            continue;
        }

        float x = r * cos(angle);

        // ignore anything behind center of lidar
        if (x < 0) {
            continue;
        }

        if (x < minDist) {
            minDist = x;
        }
    }
    // assume error condition if there is an obstacle within a
    // distance that robot could travel in half a second
    obstacleDetected = minDist < maxLinearVelocity / 2.0;
}

// Called when a simple goal message is received

void MoveBasic::goalCallback(const geometry_msgs::PoseStamped::ConstPtr &msg)
{
    ROS_INFO("Received simple goal");
    // send the goal to the action server
    move_base_msgs::MoveBaseActionGoal actionGoal;
    actionGoal.header.stamp = ros::Time::now();
    actionGoal.goal.target_pose = *msg;

    goalPub.publish(actionGoal);
}

// Abort goal and print message
void MoveBasic::abortGoal(const std::string msg)
{
    actionServer->setAborted(move_base_msgs::MoveBaseResult(), msg);
    ROS_ERROR("%s", msg.c_str());
}

// Called when an action goal is received

void MoveBasic::executeAction(const move_base_msgs::MoveBaseGoalConstPtr& msg)
{
    tf2::Transform goal;
    tf2::fromMsg(msg->target_pose.pose, goal);
    std::string frameId = msg->target_pose.header.frame_id;

    // Needed for RobotCommander
    if (frameId[0] == '/')
        frameId = frameId.substr(1);

    double x, y, yaw;
    getPose(goal, x, y, yaw);
    ROS_INFO("Received goal %f %f %f", x, y, rad2deg(yaw));

    tf2::Transform tfMapOdom;
    if (!getTransform(frameId, "odom", tfMapOdom)) {
        abortGoal("Cannot determine robot pose");
        return;
    }
    goalOdom = tfMapOdom * goal;

    getPose(goalOdom, x, y, yaw);
    ROS_INFO("Goal in odom  %f %f %f", x, y, rad2deg(yaw));

    nav_msgs::Path path;
    geometry_msgs::PoseStamped p0, p1;
    path.header.frame_id = "odom";
    p0.pose.position.x = x;
    p0.pose.position.y = y;
    path.poses.push_back(p0);

    tf2::Transform poseOdom;
    if (!getTransform("base_link", "odom", poseOdom)) {
         abortGoal("Cannot determine robot pose");
         return;
    }
    getPose(poseOdom, x, y, yaw);
    p1.pose.position.x = x;
    p1.pose.position.y = y;
    path.poses.push_back(p1);

    pathPub.publish(path);

    if (!handleRotation()) {
        return;
    }
    if (!handleLinear()) {
        return;
    }
    getPose(goalOdom, x, y, yaw);
    rotateAbs(yaw);

    actionServer->setSucceeded();
}

// Send a motion command

void MoveBasic::sendCmd(double angular, double linear)
{
   geometry_msgs::Twist msg;
   msg.angular.z = angular;
   msg.linear.x = linear;

   cmdPub.publish(msg);
}

// Main loop

void MoveBasic::run()
{
    ros::Rate r(20);
    while (ros::ok()) {
        ros::spinOnce();
        r.sleep();
    }
}

// Do angular part of goal

bool MoveBasic::handleRotation()
{
    tf2::Transform poseOdom;
    if (!getTransform("base_link", "odom", poseOdom)) {
         ROS_WARN("Cannot determine robot pose for rotation");
         return false;
    }

    tf2::Vector3 linear = goalOdom.getOrigin() - poseOdom.getOrigin();
    // don't do initial rotation if there is no translation
    if (linear.length() == 0) {
        return true;
    }
    double requestedYaw = atan2(linear.y(), linear.x());

    if (requestedYaw == 0) {
        return true;
    }
    return rotateAbs(requestedYaw);
}

// Rotate relative to current orientation

bool MoveBasic::rotateRel(double yaw)
{
    tf2::Transform poseOdom;
    if (!getTransform("base_link", "odom", poseOdom)) {
         abortGoal("Cannot determine robot pose for rotation");
         return false;
    }

    double x, y, currentYaw;
    getPose(poseOdom, x, y, currentYaw);
    double requestedYaw = currentYaw + yaw;
    normalizeAngle(requestedYaw);

    return rotateAbs(requestedYaw);
}

// Rotate to specified orientation (in radians)

bool MoveBasic::rotateAbs(double requestedYaw)
{
    bool done = false;
    ros::Rate r(50);

    int oscillations = 0;
    double prevAngleRemaining = 0;

    while (!done && ros::ok()) {
        ros::spinOnce();
        r.sleep();

        double x, y, currentYaw;
        tf2::Transform poseOdom;
        if (!getTransform("base_link", "odom", poseOdom)) {
            abortGoal("Cannot determine robot pose for rotation");
            return false;
        }
        getPose(poseOdom, x, y, currentYaw);

        double angleRemaining = requestedYaw - currentYaw;
        normalizeAngle(angleRemaining);

        double speed = std::max(minAngularVelocity,
            std::min(maxAngularVelocity,
              std::sqrt(2.0 * angularAcceleration *
                (std::abs(angleRemaining) - angularTolerance))));

        double velocity = 0;

        if (angleRemaining < 0) {
            velocity = -speed;
        }
        else {
            velocity = speed;
        }

        if (sign(prevAngleRemaining) != sign(angleRemaining)) {
            oscillations++;
        }
        prevAngleRemaining = angleRemaining;

        if (actionServer->isNewGoalAvailable()) {
            ROS_INFO("Stopping rotation due to new goal");
            done = true;
            velocity = 0;
        }

        //ROS_INFO("%f %f %f", rad2deg(angleRemaining), angleRemaining, velocity);

        if (std::abs(angleRemaining) < angularTolerance || oscillations > 2) {
            velocity = 0;
            done = true;
            ROS_INFO("Done rotation, error %f degrees", rad2deg(angleRemaining));
        }
        sendCmd(velocity, 0);
    }
    return done;
}

// Do linear part of goal

bool MoveBasic::handleLinear()
{
    bool done = false;

    tf2::Transform poseOdomInitial;
    if (!getTransform("base_link", "odom", poseOdomInitial)) {
         ROS_WARN("Cannot determine robot pose for linear");
         return false;
    }

    tf2::Vector3 linear = goalOdom.getOrigin() - poseOdomInitial.getOrigin();
    double requestedDistance = linear.length();;
    ROS_INFO("Requested distance %f", requestedDistance);

    return moveLinear(requestedDistance);
}

// Move forward specified distance

bool MoveBasic::moveLinear(double requestedDistance)
{
    bool done = false;
    ros::Rate r(50);

    bool waitingForObstacle = false;
    ros::Time obstacleTime;

    tf2::Transform poseOdomInitial;
    if (!getTransform("base_link", "odom", poseOdomInitial)) {
         abortGoal("Cannot determine robot pose for linear");
         return false;
    }

    while (!done && ros::ok()) {
        ros::spinOnce();
        r.sleep();

        tf2::Transform poseOdom;
        if (!getTransform("base_link", "odom", poseOdom)) {
             ROS_WARN("Cannot determine robot pose for linear");
             continue;
        }

        tf2::Vector3 travelled = poseOdomInitial.getOrigin() - poseOdom.getOrigin();
        double distTravelled = travelled.length();;

        double distRemaining = requestedDistance - distTravelled;

        double velocity = std::max(minLinearVelocity,
            std::min(maxLinearVelocity, std::min(
              std::sqrt(2.0 * linearAcceleration * std::abs(distTravelled)),
              std::sqrt(2.0 * linearAcceleration * std::abs(distRemaining)))));

        if (obstacleDetected) {
            velocity = 0;
            if (!waitingForObstacle) {
                ROS_INFO("Pausing for obstacle");
                obstacleTime = ros::Time::now();
                waitingForObstacle = true;
            }
            else {
                ros::Duration waitTime = ros::Time::now() - obstacleTime;
                if (waitTime.toSec() > obstacleWaitLimit) {
                    abortGoal("Aborting after obstacle wait time limit reached");
                    return false;
                }
            }
        }

        if (waitingForObstacle && ! obstacleDetected) {
            ROS_INFO("Resuming after obstacle has gone");
            waitingForObstacle = false;
        }

        if (actionServer->isNewGoalAvailable()) {
            ROS_INFO("Stopping rotation due to new goal");
            done = true;
            velocity = 0;
        }

        //ROS_INFO("%f %f %f", distTravelled, distRemaining, velocity);

        if (distTravelled > requestedDistance - linearTolerance) {
            velocity = 0;
            done = true;
            ROS_INFO("Done linear, error %f meters", distRemaining);
        }
        sendCmd(0, velocity);
    }
    return done;
}

int main(int argc, char ** argv) {
    ros::init(argc, argv, "move_basic");
    MoveBasic mb_node;
    mb_node.run();

    return 0;
}
<|endoftext|>


<commit_before>#include <allegro.h>
#include <cstring>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <vector>
#include <map>

#include "globals.h"
#include "mugen_reader.h"
#include "mugen_section.h"
#include "mugen_item_content.h"
#include "mugen_item.h"
#include "mugen_character.h"
#include "mugen_animation.h"
#include "mugen_sprite.h"

#include "util/bitmap.h"
#include "util/funcs.h"

#include "factory/font_render.h"

#include "gui/keyinput_manager.h"

using namespace std;

static void showCollision( const std::vector< MugenArea > &vec, Bitmap &bmp, int x, int y, int color, int &start ){
    int next = start;
    for( unsigned int i = 0; i < vec.size(); ++i ){
	bmp.rectangle( x + vec[i].x1, y + vec[i].y1, x + vec[i].x2, y + vec[i].y2, color );
	Font::getDefaultFont().printf( 15, 310 + next, color, bmp, "CLSN: x1(%i),y1(%i),x2(%i),y2(%i)",0, vec[i].x1,vec[i].y1,vec[i].x2,vec[i].y2 );
	next+=10;
    }
    start = next;
}

static bool isArg( const char * s1, const char * s2 ){
	return strcasecmp( s1, s2 ) == 0;
}

static void showOptions(){
    Global::debug(0) << "M.U.G.E.N. Config Reader:" << endl;
    Global::debug(0) << "-f <file>: Load a M.U.G.E.N. config file and output to screen." << endl;
    Global::debug(0) << "-c <name>: Load a M.U.G.E.N. character and output some data about it.\n         ie: 'data/mugen/chars/name' only pass name." << endl;
    Global::debug(0) << endl;
}

/* testing testing 1 2 3 */
void testPCX(){
    unsigned char data[1 << 18];
    FILE * f = fopen("x.pcx", "r");
    int length;
    length = fread(data, sizeof(char), 1<<18, f);
    Global::debug(0) << "Size is " << length << endl;
    fclose(f);
    Bitmap b = Bitmap::memoryPCX(data, length);
    // Bitmap b("x.pcx");
    if (b.getError()){
        Global::debug(0) << "what the hell" << endl;
    }
    Bitmap work(640, 480);
    work.circleFill(40, 40, 100, Bitmap::makeColor(255, 0, 0));
    b.draw(0, 0, work);
    Global::debug(0) << "Width " << b.getWidth() << " Height " << b.getHeight() << endl;
    work.BlitToScreen();
    Util::rest(3000);
}

void showCharacter(const string & ourFile){
    Global::debug(0) << "Trying to load character: " << ourFile << "..." << endl;
    MugenCharacter character( ourFile );
    character.load();
    /*
       for (map<int,MugenAnimation*>::const_iterator it = character.getAnimations().begin(); it != character.getAnimations().end(); it++){
       Global::debug(0) << "Animation " << it->first << endl;
       const vector<MugenFrame*> & frames = it->second->getFrames();
       for (vector<MugenFrame*>::const_iterator frame = frames.begin(); frame != frames.end(); frame++){
       MugenSprite * sprite = (*frame)->sprite;
       if (sprite == 0){
       continue;
       }
       Bitmap b = new Bitmap(sffLoadPcxFromMemory( (char*) sprite->pcx ));;//Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
       b.BlitToScreen();
       Util::rest(1000);
       }
       }
       */
    Global::debug(0) << "Loaded character: \"" << character.getName() << "\" successfully." << endl;
    bool quit = false;
    bool animate = false;
    bool showClsn1 = false;
    bool showClsn2 = false;
    bool moveImage = false;
    int ticks = 0;
    int loop = 0;

    map<int,MugenAnimation*>::const_iterator it = character.getAnimations().begin();
    unsigned int currentAnim = 0;
    unsigned int lastAnim = character.getAnimations().size() -1;
    unsigned int currentFrame = 0;
    unsigned int lastFrame = it->second->getFrames().size() -1;

    if (it->second->getFrames().size() == 0){
        Global::debug(0) << "No frames!" << endl;
        exit(0);
    }

    MugenSprite * sprite = it->second->getFrames()[currentFrame]->sprite;

    Bitmap b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);

    Bitmap work( 640, 480 );

    int xaxis = 260;
    int yaxis = 230;

    while( !quit ){
        work.clear();
        keyInputManager::update();
        ++ticks;
        // Since -1 is to stop the animation completely, we'll give it a pause of 150 ticks, because we want to see the loop
        const int time = it->second->getFrames()[currentFrame]->time == -1 ? 150 : it->second->getFrames()[currentFrame]->time;
        if(animate && ticks >= 15 + time){
            ticks = 0;
            if( it->second->getFrames()[currentFrame]->loopstart ) loop = currentFrame;
            if( currentFrame < lastFrame )currentFrame++;
            else currentFrame = loop;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }

        if( keyInputManager::keyState(keys::UP, true) ){
            if( currentAnim < lastAnim ){
                currentAnim++;
                it++;
            }
            loop = 0;
            currentFrame = 0;
            lastFrame = it->second->getFrames().size()-1;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }
        else if( keyInputManager::keyState(keys::DOWN, true) ){
            if( currentAnim > 0 ){
                currentAnim--;
                it--;
            }
            loop = 0;
            currentFrame = 0;
            lastFrame = it->second->getFrames().size()-1;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }
        else if( keyInputManager::keyState(keys::LEFT, true) && !animate){
            if( currentFrame > 0 )currentFrame--;
            else currentFrame = lastFrame;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }
        else if( keyInputManager::keyState(keys::RIGHT, true) && !animate){
            if( currentFrame < lastFrame )currentFrame++;
            else currentFrame = 0;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }
        else if( keyInputManager::keyState(keys::SPACE, true) ){
            animate = !animate;
        }
        else if( keyInputManager::keyState('a', true) ){
            showClsn1 = !showClsn1;
        }
        else if( keyInputManager::keyState('d', true) ){
            showClsn2 = !showClsn2;
        }

	if( mouse_b & 1 )moveImage = true;
	else if( !(mouse_b & 1) )moveImage = false;

        quit |= keyInputManager::keyState(keys::ESC, true );

	if( sprite!= 0 ){
	    // Figure out the correct placement according to axis
	    if( moveImage ){ xaxis=mouse_x; yaxis =mouse_y; }
	    const int placex = (xaxis - sprite->x ) + it->second->getFrames()[currentFrame]->xoffset;
	    const int placey = (yaxis - sprite->y ) + it->second->getFrames()[currentFrame]->yoffset;

	    if( it->second->getFrames()[currentFrame]->flipHorizontal && ! it->second->getFrames()[currentFrame]->flipVertical ){
		b.drawHFlip(placex, placey, work);
	    }
	    else if( it->second->getFrames()[currentFrame]->flipVertical && ! it->second->getFrames()[currentFrame]->flipHorizontal ){
		b.drawVFlip(placex, placey, work);
	    }
	    else if( it->second->getFrames()[currentFrame]->flipVertical && it->second->getFrames()[currentFrame]->flipHorizontal ){
		b.drawRotate(placex, placey, 180, work);
	    }
	    else b.draw(placex, placey, work);

	    int start = 10;
	     if( showClsn2 )showCollision( it->second->getFrames()[currentFrame]->defenseCollision, work, xaxis, yaxis, Bitmap::makeColor( 0,255,0 ), start  );
	     if( showClsn1 )showCollision( it->second->getFrames()[currentFrame]->attackCollision, work, xaxis, yaxis,  Bitmap::makeColor( 255,0,0 ), start  );
	}
        Font::getDefaultFont().printf( 15, 250, Bitmap::makeColor( 255, 255, 255 ), work, "Current Animation: %i (%s), Frame: %i, xoffset: %i, yoffset: %i", 0, it->first, MugenAnimation::getName(MugenAnimationType(it->first)).c_str() ,currentFrame, it->second->getFrames()[currentFrame]->xoffset, it->second->getFrames()[currentFrame]->yoffset );
        if(sprite!=0)Font::getDefaultFont().printf( 15, 270, Bitmap::makeColor( 255, 255, 255 ), work, "Length: %d | x-axis: %d | y-axis: %d | Group: %d | Image: %d",0, sprite->length, sprite->x, sprite->y, sprite->groupNumber, sprite->imageNumber);
        Font::getDefaultFont().printf( 15, 280, Bitmap::makeColor( 255, 255, 255 ), work, "Bitmap info - Width: %i Height: %i",0, b.getWidth(), b.getHeight() );
        Font::getDefaultFont().printf( 15, 290, Bitmap::makeColor( 255, 255, 255 ), work, "(space) Animation enabled:            %i",0, animate );
        Font::getDefaultFont().printf( 15, 300, Bitmap::makeColor( 255, 255, 255 ), work, "(d)     Show Defense enabled (green): %i",0, showClsn2 );
        Font::getDefaultFont().printf( 15, 310, Bitmap::makeColor( 255, 255, 255 ), work, "(a)     Show Attack enabled (red):    %i",0, showClsn1 );

        work.BlitToScreen();
        Util::rest(1);
    }

}

int main( int argc, char ** argv ){

	if(argc <= 1){
	    showOptions();
	    return 0;
	}

	const char * FILE_ARG = "-f";
	const char * LOC_ARG = "-c";
        const char * DEBUG_ARG = "-l";
	std::string ourFile;
	bool configLoaded = false;

        allegro_init();
        install_timer();
	install_keyboard();
	install_mouse();
        set_color_depth(16);
        Bitmap::setGfxModeWindowed(640, 480);

	for ( int q = 1; q < argc; q++ ){
		if ( isArg( argv[ q ], FILE_ARG ) ){
			q += 1;
			if ( q < argc ){
				ourFile = std::string( argv[ q ] );
				configLoaded = !configLoaded;
			}
			else{
                            Global::debug(0) << "Error no file given!" << endl;
			  showOptions();
			  return 0;
			}
		} else if ( isArg( argv[ q ], LOC_ARG ) ){
			q += 1;
			if ( q < argc ){
				ourFile = std::string( argv[ q ] );
			}
			else{
                            Global::debug(0) << "Error no file given!" << endl;
			  showOptions();
			  return 0;
			}
		} else if (isArg(argv[q], DEBUG_ARG)){
                    q += 1;
                    if (q < argc){
                        istringstream i( argv[ q ] );
                        int f;
                        i >> f;
                        Global::setDebug( f );
                    } else {
                        Global::debug(0) << "No number given for " << DEBUG_ARG << endl;
                    }
                } else {
		    // WHAT?
		    showOptions();
		    return 0;
		}
	}

	if( configLoaded ){
	    MugenReader reader( ourFile );

	    std::vector< MugenSection * > collection;

	    try{
		collection = reader.getCollection();
                Global::debug(0) << endl << "---------------------------------------------------------" << endl;
		for( unsigned int i = 0; i < collection.size(); ++i ){
                    Global::debug(0) << collection[i]->getHeader() << endl;
                    Global::debug(0) << "---------------------------------------------------------" << endl;
		    while( collection[i]->hasItems() ){
			MugenItemContent *content = collection[i]->getNext();
                        while( content->hasItems() ){
                            Global::debug(0) << content->getNext()->query();
                            if( content->hasItems() ) Global::debug(0) << ",";
                        }
                        Global::debug(0) << endl;
		    }
                    Global::debug(0) << "---------------------------------------------------------" << endl;
		}
                Global::debug(0) << endl;
	    }
	    catch( MugenException &ex){
                Global::debug(0) << "Problem loading file, error was: " << ex.getReason() << endl;
		return 1;
	    }
	}
	else{
	    try{
                showCharacter(ourFile);
            } catch( MugenException &ex){
                Global::debug(0) << "Problem loading file, error was: " << ex.getReason() << endl;
		return 1;
	    } catch(...){
		Global::debug(0) << "Unknown problem loading file" << endl;
		return 1;
	    }
	}

	return 0;
}
<commit_msg>Minor changes to test<commit_after>#include <allegro.h>
#include <cstring>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <vector>
#include <map>

#include "globals.h"
#include "mugen_reader.h"
#include "mugen_section.h"
#include "mugen_item_content.h"
#include "mugen_item.h"
#include "mugen_character.h"
#include "mugen_animation.h"
#include "mugen_sprite.h"

#include "util/bitmap.h"
#include "util/funcs.h"

#include "factory/font_render.h"

#include "gui/keyinput_manager.h"

using namespace std;

static void showCollision( const std::vector< MugenArea > &vec, Bitmap &bmp, int x, int y, int color, int &start ){
    int next = start;
    for( unsigned int i = 0; i < vec.size(); ++i ){
	bmp.rectangle( x + vec[i].x1, y + vec[i].y1, x + vec[i].x2, y + vec[i].y2, color );
	Font::getDefaultFont().printf( 15, 310 + next, color, bmp, "CLSN: x1(%i),y1(%i),x2(%i),y2(%i)",0, vec[i].x1,vec[i].y1,vec[i].x2,vec[i].y2 );
	next+=10;
    }
    start = next;
}

static bool isArg( const char * s1, const char * s2 ){
	return strcasecmp( s1, s2 ) == 0;
}

static void showOptions(){
    Global::debug(0) << "M.U.G.E.N. Config Reader:" << endl;
    Global::debug(0) << "-f <file>: Load a M.U.G.E.N. config file and output to screen." << endl;
    Global::debug(0) << "-c <name>: Load a M.U.G.E.N. character and output some data about it.\n         ie: 'data/mugen/chars/name' only pass name." << endl;
    Global::debug(0) << endl;
}

/* testing testing 1 2 3 */
void testPCX(){
    unsigned char data[1 << 18];
    FILE * f = fopen("x.pcx", "r");
    int length;
    length = fread(data, sizeof(char), 1<<18, f);
    Global::debug(0) << "Size is " << length << endl;
    fclose(f);
    Bitmap b = Bitmap::memoryPCX(data, length);
    // Bitmap b("x.pcx");
    if (b.getError()){
        Global::debug(0) << "what the hell" << endl;
    }
    Bitmap work(640, 480);
    work.circleFill(40, 40, 100, Bitmap::makeColor(255, 0, 0));
    b.draw(0, 0, work);
    Global::debug(0) << "Width " << b.getWidth() << " Height " << b.getHeight() << endl;
    work.BlitToScreen();
    Util::rest(3000);
}

void showCharacter(const string & ourFile){
    set_color_depth(16);
    Bitmap::setGfxModeWindowed(640, 480);
    Global::debug(0) << "Trying to load character: " << ourFile << "..." << endl;
    MugenCharacter character( ourFile );
    character.load();
    /*
       for (map<int,MugenAnimation*>::const_iterator it = character.getAnimations().begin(); it != character.getAnimations().end(); it++){
       Global::debug(0) << "Animation " << it->first << endl;
       const vector<MugenFrame*> & frames = it->second->getFrames();
       for (vector<MugenFrame*>::const_iterator frame = frames.begin(); frame != frames.end(); frame++){
       MugenSprite * sprite = (*frame)->sprite;
       if (sprite == 0){
       continue;
       }
       Bitmap b = new Bitmap(sffLoadPcxFromMemory( (char*) sprite->pcx ));;//Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
       b.BlitToScreen();
       Util::rest(1000);
       }
       }
       */
    Global::debug(0) << "Loaded character: \"" << character.getName() << "\" successfully." << endl;
    bool quit = false;
    bool animate = false;
    bool showClsn1 = false;
    bool showClsn2 = false;
    bool moveImage = false;
    int ticks = 0;
    int loop = 0;

    map<int,MugenAnimation*>::const_iterator it = character.getAnimations().begin();
    unsigned int currentAnim = 0;
    unsigned int lastAnim = character.getAnimations().size() -1;
    unsigned int currentFrame = 0;
    unsigned int lastFrame = it->second->getFrames().size() -1;

    if (it->second->getFrames().size() == 0){
        Global::debug(0) << "No frames!" << endl;
        exit(0);
    }

    MugenSprite * sprite = it->second->getFrames()[currentFrame]->sprite;

    Bitmap b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);

    Bitmap work( 640, 480 );

    int xaxis = 260;
    int yaxis = 230;

    while( !quit ){
        work.clear();
        keyInputManager::update();
        ++ticks;
        // Since -1 is to stop the animation completely, we'll give it a pause of 150 ticks, because we want to see the loop
        const int time = it->second->getFrames()[currentFrame]->time == -1 ? 150 : it->second->getFrames()[currentFrame]->time;
        if(animate && ticks >= 15 + time){
            ticks = 0;
            if( it->second->getFrames()[currentFrame]->loopstart ) loop = currentFrame;
            if( currentFrame < lastFrame )currentFrame++;
            else currentFrame = loop;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }

        if( keyInputManager::keyState(keys::UP, true) ){
            if( currentAnim < lastAnim ){
                currentAnim++;
                it++;
            }
            loop = 0;
            currentFrame = 0;
            lastFrame = it->second->getFrames().size()-1;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }
        else if( keyInputManager::keyState(keys::DOWN, true) ){
            if( currentAnim > 0 ){
                currentAnim--;
                it--;
            }
            loop = 0;
            currentFrame = 0;
            lastFrame = it->second->getFrames().size()-1;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }
        else if( keyInputManager::keyState(keys::LEFT, true) && !animate){
            if( currentFrame > 0 )currentFrame--;
            else currentFrame = lastFrame;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }
        else if( keyInputManager::keyState(keys::RIGHT, true) && !animate){
            if( currentFrame < lastFrame )currentFrame++;
            else currentFrame = 0;
            sprite = it->second->getFrames()[currentFrame]->sprite;
            if (sprite != 0){
                b = Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength);
            }
        }
        else if( keyInputManager::keyState(keys::SPACE, true) ){
            animate = !animate;
        }
        else if( keyInputManager::keyState('a', true) ){
            showClsn1 = !showClsn1;
        }
        else if( keyInputManager::keyState('d', true) ){
            showClsn2 = !showClsn2;
        }

	if( mouse_b & 1 )moveImage = true;
	else if( !(mouse_b & 1) )moveImage = false;

        quit |= keyInputManager::keyState(keys::ESC, true );

	if( sprite!= 0 ){
	    // Figure out the correct placement according to axis
	    if( moveImage ){ xaxis=mouse_x; yaxis =mouse_y; }
	    const int placex = (xaxis - sprite->x ) + it->second->getFrames()[currentFrame]->xoffset;
	    const int placey = (yaxis - sprite->y ) + it->second->getFrames()[currentFrame]->yoffset;

	    if( it->second->getFrames()[currentFrame]->flipHorizontal && ! it->second->getFrames()[currentFrame]->flipVertical ){
		b.drawHFlip(placex, placey, work);
	    }
	    else if( it->second->getFrames()[currentFrame]->flipVertical && ! it->second->getFrames()[currentFrame]->flipHorizontal ){
		b.drawVFlip(placex, placey, work);
	    }
	    else if( it->second->getFrames()[currentFrame]->flipVertical && it->second->getFrames()[currentFrame]->flipHorizontal ){
		b.drawRotate(placex, placey, 180, work);
	    }
	    else b.draw(placex, placey, work);

	    int start = 10;
	     if( showClsn2 )showCollision( it->second->getFrames()[currentFrame]->defenseCollision, work, xaxis, yaxis, Bitmap::makeColor( 0,255,0 ), start  );
	     if( showClsn1 )showCollision( it->second->getFrames()[currentFrame]->attackCollision, work, xaxis, yaxis,  Bitmap::makeColor( 255,0,0 ), start  );
	}
        Font::getDefaultFont().printf( 15, 250, Bitmap::makeColor( 255, 255, 255 ), work, "Current Animation: %i (%s), Frame: %i, xoffset: %i, yoffset: %i", 0, it->first, MugenAnimation::getName(MugenAnimationType(it->first)).c_str() ,currentFrame, it->second->getFrames()[currentFrame]->xoffset, it->second->getFrames()[currentFrame]->yoffset );
        if(sprite!=0)Font::getDefaultFont().printf( 15, 270, Bitmap::makeColor( 255, 255, 255 ), work, "Length: %d | x-axis: %d | y-axis: %d | Group: %d | Image: %d",0, sprite->length, sprite->x, sprite->y, sprite->groupNumber, sprite->imageNumber);
        Font::getDefaultFont().printf( 15, 280, Bitmap::makeColor( 255, 255, 255 ), work, "Bitmap info - Width: %i Height: %i",0, b.getWidth(), b.getHeight() );
        Font::getDefaultFont().printf( 15, 290, Bitmap::makeColor( 255, 255, 255 ), work, "(space) Animation enabled:            %i",0, animate );
        Font::getDefaultFont().printf( 15, 300, Bitmap::makeColor( 255, 255, 255 ), work, "(d)     Show Defense enabled (green): %i",0, showClsn2 );
        Font::getDefaultFont().printf( 15, 310, Bitmap::makeColor( 255, 255, 255 ), work, "(a)     Show Attack enabled (red):    %i",0, showClsn1 );

	show_mouse(work.getBitmap());

        work.BlitToScreen();
        Util::rest(1);
    }

}

int main( int argc, char ** argv ){

	if(argc <= 1){
	    showOptions();
	    return 0;
	}

	const char * FILE_ARG = "-f";
	const char * LOC_ARG = "-c";
        const char * DEBUG_ARG = "-l";
	std::string ourFile;
	bool configLoaded = false;

        allegro_init();
        install_timer();
	install_keyboard();
	install_mouse();

	for ( int q = 1; q < argc; q++ ){
		if ( isArg( argv[ q ], FILE_ARG ) ){
			q += 1;
			if ( q < argc ){
				ourFile = std::string( argv[ q ] );
				configLoaded = !configLoaded;
			}
			else{
                            Global::debug(0) << "Error no file given!" << endl;
			  showOptions();
			  return 0;
			}
		} else if ( isArg( argv[ q ], LOC_ARG ) ){
			q += 1;
			if ( q < argc ){
				ourFile = std::string( argv[ q ] );
			}
			else{
                            Global::debug(0) << "Error no file given!" << endl;
			  showOptions();
			  return 0;
			}
		} else if (isArg(argv[q], DEBUG_ARG)){
                    q += 1;
                    if (q < argc){
                        istringstream i( argv[ q ] );
                        int f;
                        i >> f;
                        Global::setDebug( f );
                    } else {
                        Global::debug(0) << "No number given for " << DEBUG_ARG << endl;
                    }
                } else {
		    // WHAT?
		    showOptions();
		    return 0;
		}
	}

	if( configLoaded ){
	    MugenReader reader( ourFile );

	    std::vector< MugenSection * > collection;

	    try{
		collection = reader.getCollection();
                Global::debug(0) << endl << "---------------------------------------------------------" << endl;
		for( unsigned int i = 0; i < collection.size(); ++i ){
                    Global::debug(0) << collection[i]->getHeader() << endl;
                    Global::debug(0) << "---------------------------------------------------------" << endl;
		    while( collection[i]->hasItems() ){
			MugenItemContent *content = collection[i]->getNext();
                        while( content->hasItems() ){
                            Global::debug(0) << content->getNext()->query();
                            if( content->hasItems() ) Global::debug(0) << ",";
                        }
                        Global::debug(0) << endl;
		    }
                    Global::debug(0) << "---------------------------------------------------------" << endl;
		}
                Global::debug(0) << endl;
	    }
	    catch( MugenException &ex){
                Global::debug(0) << "Problem loading file, error was: " << ex.getReason() << endl;
		return 1;
	    }
	}
	else{
	    try{
                showCharacter(ourFile);
            } catch( MugenException &ex){
                Global::debug(0) << "Problem loading file, error was: " << ex.getReason() << endl;
		return 1;
	    } catch(...){
		Global::debug(0) << "Unknown problem loading file" << endl;
		return 1;
	    }
	}

	return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: authfld.hxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 07:56:06 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _AUTHFLD_HXX
#define _AUTHFLD_HXX

#ifndef INCLUDED_SWDLLAPI_H
#include "swdllapi.h"
#endif

#ifndef _FLDBAS_HXX
#include <fldbas.hxx>
#endif

#ifndef _TOXE_HXX
#include <toxe.hxx>
#endif

#define _SVSTDARR_LONGS
#include <svtools/svstdarr.hxx>

class SwAuthDataArr;
/* -----------------21.09.99 13:32-------------------

 --------------------------------------------------*/
class SwAuthEntry
{
    String      aAuthFields[AUTH_FIELD_END];
    USHORT      nRefCount;
public:
    SwAuthEntry() : nRefCount(0){}
    SwAuthEntry( const SwAuthEntry& rCopy );
    BOOL            operator==(const SwAuthEntry& rComp);

    inline const String&    GetAuthorField(ToxAuthorityField ePos)const;
    inline void             SetAuthorField(ToxAuthorityField ePos,
                                            const String& rField);

    void            AddRef()                { ++nRefCount; }
    void            RemoveRef()             { --nRefCount; }
    USHORT          GetRefCount()           { return nRefCount; }
};
/* -----------------20.10.99 16:49-------------------

 --------------------------------------------------*/
struct SwTOXSortKey
{
    ToxAuthorityField   eField;
    BOOL                bSortAscending;
    SwTOXSortKey() :
        eField(AUTH_FIELD_END),
        bSortAscending(TRUE){}
};

/* -----------------14.09.99 16:15-------------------

 --------------------------------------------------*/
class SwAuthorityField;
class SortKeyArr;

class SW_DLLPUBLIC SwAuthorityFieldType : public SwFieldType
{
    SwDoc*          m_pDoc;
    SwAuthDataArr*  m_pDataArr;
    SvLongs*        m_pSequArr;
    SortKeyArr*     m_pSortKeyArr;
    sal_Unicode     m_cPrefix;
    sal_Unicode     m_cSuffix;
    BOOL            m_bIsSequence :1;
    BOOL            m_bSortByDocument :1;
    LanguageType    m_eLanguage;
    String          m_sSortAlgorithm;

    // @@@ private copy assignment, but public copy ctor? @@@
    const SwAuthorityFieldType& operator=( const SwAuthorityFieldType& );

public:
    SwAuthorityFieldType(SwDoc* pDoc);
    SwAuthorityFieldType( const SwAuthorityFieldType& );
    ~SwAuthorityFieldType();

    virtual SwFieldType* Copy()    const;
    virtual void        Modify( SfxPoolItem *pOld, SfxPoolItem *pNew );

    virtual BOOL        QueryValue( com::sun::star::uno::Any& rVal, USHORT nWhichId ) const;
    virtual BOOL        PutValue( const com::sun::star::uno::Any& rVal, USHORT nWhichId );

    inline void     SetDoc(SwDoc* pNewDoc)              { m_pDoc = pNewDoc; }

    void                RemoveField(long nHandle);
    long                AddField(const String& rFieldContents);
    BOOL                AddField(long nHandle);
    void                DelSequenceArray()
                        {
                            m_pSequArr->Remove(0, m_pSequArr->Count());
                        }

    const SwAuthEntry*  GetEntryByHandle(long nHandle) const;

    void                GetAllEntryIdentifiers( SvStringsDtor& rToFill )const;
    const SwAuthEntry*  GetEntryByIdentifier(const String& rIdentifier)const;

    void                ChangeEntryContent(const SwAuthEntry* pNewEntry);
    // import interface
    USHORT              AppendField(const SwAuthEntry& rInsert);
    long                GetHandle(USHORT nPos);

    USHORT              GetSequencePos(long nHandle);

    BOOL                IsSequence() const      {return m_bIsSequence;}
    void                SetSequence(BOOL bSet)
                            {
                                DelSequenceArray();
                                m_bIsSequence = bSet;
                            }

    void                SetPreSuffix( sal_Unicode cPre, sal_Unicode cSuf)
                            {
                                m_cPrefix = cPre;
                                m_cSuffix = cSuf;
                            }
    sal_Unicode         GetPrefix() const { return m_cPrefix;}
    sal_Unicode         GetSuffix() const { return m_cSuffix;}

    BOOL                IsSortByDocument() const {return m_bSortByDocument;}
    void                SetSortByDocument(BOOL bSet)
                            {
                                DelSequenceArray();
                                m_bSortByDocument = bSet;
                            }

    USHORT              GetSortKeyCount() const ;
    const SwTOXSortKey* GetSortKey(USHORT nIdx) const ;
    void                SetSortKeys(USHORT nKeyCount, SwTOXSortKey nKeys[]);

    //initui.cxx
    static const String&    GetAuthFieldName(ToxAuthorityField eType);
    static const String&    GetAuthTypeName(ToxAuthorityType eType);

    LanguageType    GetLanguage() const {return m_eLanguage;}
    void            SetLanguage(LanguageType nLang)  {m_eLanguage = nLang;}

    const String&   GetSortAlgorithm()const {return m_sSortAlgorithm;}
    void            SetSortAlgorithm(const String& rSet) {m_sSortAlgorithm = rSet;}

};
/* -----------------14.09.99 16:15-------------------

 --------------------------------------------------*/
class SwAuthorityField : public SwField
{
    long    nHandle;

public:
    SwAuthorityField(SwAuthorityFieldType* pType, const String& rFieldContents);
    SwAuthorityField(SwAuthorityFieldType* pType, long nHandle);
    ~SwAuthorityField();

    const String&       GetFieldText(ToxAuthorityField eField) const;

    virtual String      Expand() const;
    virtual SwField*    Copy() const;
    virtual void        SetPar1(const String& rStr);
    virtual SwFieldType* ChgTyp( SwFieldType* );

    virtual BOOL        QueryValue( com::sun::star::uno::Any& rVal, USHORT nWhichId ) const;
    virtual BOOL        PutValue( const com::sun::star::uno::Any& rVal, USHORT nWhichId );

    long                GetHandle() const       { return nHandle; }

    virtual String GetDescription() const;
};

// --- inlines -----------------------------------------------------------
inline const String&    SwAuthEntry::GetAuthorField(ToxAuthorityField ePos)const
{
    DBG_ASSERT(AUTH_FIELD_END > ePos, "wrong index")
    return aAuthFields[ePos];
}
inline void SwAuthEntry::SetAuthorField(ToxAuthorityField ePos, const String& rField)
{
    DBG_ASSERT(AUTH_FIELD_END > ePos, "wrong index")
    if(AUTH_FIELD_END > ePos)
        aAuthFields[ePos] = rField;
}

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.13.242); FILE MERGED 2008/04/01 12:53:26 thb 1.13.242.2: #i85898# Stripping all external header guards 2008/03/31 16:52:34 rt 1.13.242.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: authfld.hxx,v $
 * $Revision: 1.14 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _AUTHFLD_HXX
#define _AUTHFLD_HXX

#include "swdllapi.h"
#include <fldbas.hxx>
#include <toxe.hxx>

#define _SVSTDARR_LONGS
#include <svtools/svstdarr.hxx>

class SwAuthDataArr;
/* -----------------21.09.99 13:32-------------------

 --------------------------------------------------*/
class SwAuthEntry
{
    String      aAuthFields[AUTH_FIELD_END];
    USHORT      nRefCount;
public:
    SwAuthEntry() : nRefCount(0){}
    SwAuthEntry( const SwAuthEntry& rCopy );
    BOOL            operator==(const SwAuthEntry& rComp);

    inline const String&    GetAuthorField(ToxAuthorityField ePos)const;
    inline void             SetAuthorField(ToxAuthorityField ePos,
                                            const String& rField);

    void            AddRef()                { ++nRefCount; }
    void            RemoveRef()             { --nRefCount; }
    USHORT          GetRefCount()           { return nRefCount; }
};
/* -----------------20.10.99 16:49-------------------

 --------------------------------------------------*/
struct SwTOXSortKey
{
    ToxAuthorityField   eField;
    BOOL                bSortAscending;
    SwTOXSortKey() :
        eField(AUTH_FIELD_END),
        bSortAscending(TRUE){}
};

/* -----------------14.09.99 16:15-------------------

 --------------------------------------------------*/
class SwAuthorityField;
class SortKeyArr;

class SW_DLLPUBLIC SwAuthorityFieldType : public SwFieldType
{
    SwDoc*          m_pDoc;
    SwAuthDataArr*  m_pDataArr;
    SvLongs*        m_pSequArr;
    SortKeyArr*     m_pSortKeyArr;
    sal_Unicode     m_cPrefix;
    sal_Unicode     m_cSuffix;
    BOOL            m_bIsSequence :1;
    BOOL            m_bSortByDocument :1;
    LanguageType    m_eLanguage;
    String          m_sSortAlgorithm;

    // @@@ private copy assignment, but public copy ctor? @@@
    const SwAuthorityFieldType& operator=( const SwAuthorityFieldType& );

public:
    SwAuthorityFieldType(SwDoc* pDoc);
    SwAuthorityFieldType( const SwAuthorityFieldType& );
    ~SwAuthorityFieldType();

    virtual SwFieldType* Copy()    const;
    virtual void        Modify( SfxPoolItem *pOld, SfxPoolItem *pNew );

    virtual BOOL        QueryValue( com::sun::star::uno::Any& rVal, USHORT nWhichId ) const;
    virtual BOOL        PutValue( const com::sun::star::uno::Any& rVal, USHORT nWhichId );

    inline void     SetDoc(SwDoc* pNewDoc)              { m_pDoc = pNewDoc; }

    void                RemoveField(long nHandle);
    long                AddField(const String& rFieldContents);
    BOOL                AddField(long nHandle);
    void                DelSequenceArray()
                        {
                            m_pSequArr->Remove(0, m_pSequArr->Count());
                        }

    const SwAuthEntry*  GetEntryByHandle(long nHandle) const;

    void                GetAllEntryIdentifiers( SvStringsDtor& rToFill )const;
    const SwAuthEntry*  GetEntryByIdentifier(const String& rIdentifier)const;

    void                ChangeEntryContent(const SwAuthEntry* pNewEntry);
    // import interface
    USHORT              AppendField(const SwAuthEntry& rInsert);
    long                GetHandle(USHORT nPos);

    USHORT              GetSequencePos(long nHandle);

    BOOL                IsSequence() const      {return m_bIsSequence;}
    void                SetSequence(BOOL bSet)
                            {
                                DelSequenceArray();
                                m_bIsSequence = bSet;
                            }

    void                SetPreSuffix( sal_Unicode cPre, sal_Unicode cSuf)
                            {
                                m_cPrefix = cPre;
                                m_cSuffix = cSuf;
                            }
    sal_Unicode         GetPrefix() const { return m_cPrefix;}
    sal_Unicode         GetSuffix() const { return m_cSuffix;}

    BOOL                IsSortByDocument() const {return m_bSortByDocument;}
    void                SetSortByDocument(BOOL bSet)
                            {
                                DelSequenceArray();
                                m_bSortByDocument = bSet;
                            }

    USHORT              GetSortKeyCount() const ;
    const SwTOXSortKey* GetSortKey(USHORT nIdx) const ;
    void                SetSortKeys(USHORT nKeyCount, SwTOXSortKey nKeys[]);

    //initui.cxx
    static const String&    GetAuthFieldName(ToxAuthorityField eType);
    static const String&    GetAuthTypeName(ToxAuthorityType eType);

    LanguageType    GetLanguage() const {return m_eLanguage;}
    void            SetLanguage(LanguageType nLang)  {m_eLanguage = nLang;}

    const String&   GetSortAlgorithm()const {return m_sSortAlgorithm;}
    void            SetSortAlgorithm(const String& rSet) {m_sSortAlgorithm = rSet;}

};
/* -----------------14.09.99 16:15-------------------

 --------------------------------------------------*/
class SwAuthorityField : public SwField
{
    long    nHandle;

public:
    SwAuthorityField(SwAuthorityFieldType* pType, const String& rFieldContents);
    SwAuthorityField(SwAuthorityFieldType* pType, long nHandle);
    ~SwAuthorityField();

    const String&       GetFieldText(ToxAuthorityField eField) const;

    virtual String      Expand() const;
    virtual SwField*    Copy() const;
    virtual void        SetPar1(const String& rStr);
    virtual SwFieldType* ChgTyp( SwFieldType* );

    virtual BOOL        QueryValue( com::sun::star::uno::Any& rVal, USHORT nWhichId ) const;
    virtual BOOL        PutValue( const com::sun::star::uno::Any& rVal, USHORT nWhichId );

    long                GetHandle() const       { return nHandle; }

    virtual String GetDescription() const;
};

// --- inlines -----------------------------------------------------------
inline const String&    SwAuthEntry::GetAuthorField(ToxAuthorityField ePos)const
{
    DBG_ASSERT(AUTH_FIELD_END > ePos, "wrong index")
    return aAuthFields[ePos];
}
inline void SwAuthEntry::SetAuthorField(ToxAuthorityField ePos, const String& rField)
{
    DBG_ASSERT(AUTH_FIELD_END > ePos, "wrong index")
    if(AUTH_FIELD_END > ePos)
        aAuthFields[ePos] = rField;
}

#endif

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: swacorr.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-01-11 12:17:31 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SWACORR_HXX
#define _SWACORR_HXX

#ifndef _MySVXACORR_HXX //autogen
#include <svx/svxacorr.hxx>
#endif

#include <com/sun/star/uno/Reference.h>

#ifndef _COM_SUN_STAR_EMBED_XSTORAGE_HPP_
#include <com/sun/star/embed/XStorage.hpp>
#endif

class SwAutoCorrect : public SvxAutoCorrect
{
protected:
    //  - return den Ersetzungstext (nur fuer SWG-Format, alle anderen
    //      koennen aus der Wortliste herausgeholt werden!)
    //      rShort ist der Stream-Name - gecryptet!
    virtual BOOL GetLongText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& , const String& rFileName, const String& rShort, String& rLong );
    //  - Text mit Attributierung (kann nur der SWG - SWG-Format!)
    //      rShort ist der Stream-Name - gecryptet!
    virtual BOOL PutText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >&, const String& rFileName, const String& rShort, SfxObjectShell& ,
                            String& );

public:
    TYPEINFO();

    SwAutoCorrect( const SvxAutoCorrect& rACorr );
    virtual ~SwAutoCorrect();
};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.5.386); FILE MERGED 2005/09/05 13:36:30 rt 1.5.386.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swacorr.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 02:11:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _SWACORR_HXX
#define _SWACORR_HXX

#ifndef _MySVXACORR_HXX //autogen
#include <svx/svxacorr.hxx>
#endif

#include <com/sun/star/uno/Reference.h>

#ifndef _COM_SUN_STAR_EMBED_XSTORAGE_HPP_
#include <com/sun/star/embed/XStorage.hpp>
#endif

class SwAutoCorrect : public SvxAutoCorrect
{
protected:
    //  - return den Ersetzungstext (nur fuer SWG-Format, alle anderen
    //      koennen aus der Wortliste herausgeholt werden!)
    //      rShort ist der Stream-Name - gecryptet!
    virtual BOOL GetLongText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& , const String& rFileName, const String& rShort, String& rLong );
    //  - Text mit Attributierung (kann nur der SWG - SWG-Format!)
    //      rShort ist der Stream-Name - gecryptet!
    virtual BOOL PutText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >&, const String& rFileName, const String& rShort, SfxObjectShell& ,
                            String& );

public:
    TYPEINFO();

    SwAutoCorrect( const SvxAutoCorrect& rACorr );
    virtual ~SwAutoCorrect();
};

#endif

<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// Copyright (c) YEAR AUTHOR
//
// 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 <cstdio>

#include "STB/ConsoleApp.h"

`#'define  PROGRAM         "APPLICATION"
`#'define  `DESCRIPTION'     "DESCRIPTION"
`#'define  `LINK'            "LINK"
`#'define  COPYRIGHT_YEAR  "YEAR"
`#'define  `AUTHOR'          "AUTHOR"

class APPLICATION`App' : public STB::ConsoleApp
{
private:
   virtual int startConsoleApp() override
   {
      printf("Hello, world!\n");
      return 0;
   }

public:
   APPLICATION`App'()
      : ConsoleApp(PROGRAM, `DESCRIPTION', `LINK', `AUTHOR', COPYRIGHT_YEAR)
   {
   }
};

int main(int argc, const char* argv[])
{
   return APPLICATION`App'().parseArgsAndStart(argc, argv);
}
<commit_msg>Tidy template app<commit_after>//------------------------------------------------------------------------------
// Copyright (c) YEAR AUTHOR
//
// 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 <cstdio>

#include "STB/ConsoleApp.h"

`#'define  PROGRAM         "APPLICATION"
`#'define  `DESCRIPTION'     "DESCRIPTION"
`#'define  `LINK'            "LINK"
`#'define  `AUTHOR'          "AUTHOR"
`#'define  COPYRIGHT_YEAR  "YEAR"

class APPLICATION`App' : public STB::ConsoleApp
{
public:
   APPLICATION`App'()
      : ConsoleApp(PROGRAM, `DESCRIPTION', `LINK', `AUTHOR', COPYRIGHT_YEAR)
   {
   }

private:
   virtual int startConsoleApp() override
   {
      printf("Hello, world!\n");
      return 0;
   }
};

int main(int argc, const char* argv[])
{
   return APPLICATION`App'().parseArgsAndStart(argc, argv);
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Posix/FileImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <cstdio>
#include <Nazara/Core/Debug.hpp>

namespace Nz
{
	FileImpl::FileImpl(const File* parent) :
	m_endOfFile(false),
	m_endOfFileUpdated(true)
	{
		NazaraUnused(parent);
	}

	void FileImpl::Close()
	{
        if (m_fileDescriptor != -1)
            close(m_fileDescriptor);
	}

	bool FileImpl::EndOfFile() const
	{
		if (!m_endOfFileUpdated)
		{
			struct stat64 fileSize;
			if (fstat64(m_fileDescriptor, &fileSize) == -1)
				fileSize.st_size = 0;

			m_endOfFile = (GetCursorPos() >= static_cast<UInt64>(fileSize.st_size));
			m_endOfFileUpdated = true;
		}

		return m_endOfFile;
	}

	void FileImpl::Flush()
	{
		if (fsync(m_fileDescriptor) == -1)
			NazaraError("Unable to flush file: " + Error::GetLastSystemError());
	}

	UInt64 FileImpl::GetCursorPos() const
	{
		off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR);
		return static_cast<UInt64>(position);
	}

	bool FileImpl::Open(const String& filePath, UInt32 mode)
	{
		int flags;
		mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

		if (mode & OpenMode_ReadOnly)
			flags = O_RDONLY;
		else if (mode & OpenMode_ReadWrite)
		{
			flags = O_CREAT | O_RDWR;

			if (mode & OpenMode_Append)
				flags |= O_APPEND;

			if (mode & OpenMode_Truncate)
				flags |= O_TRUNC;
		}
		else if (mode & OpenMode_WriteOnly)
		{
			flags = O_CREAT | O_WRONLY;

			if (mode & OpenMode_Append)
				flags |= O_APPEND;

			if (mode & OpenMode_Truncate)
				flags |= O_TRUNC;
		}
		else
			return false;

	///TODO: lock
	//	if ((mode & OpenMode_Lock) == 0)
	//		shareMode |= FILE_SHARE_WRITE;

		m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
		return m_fileDescriptor != -1;
	}

	std::size_t FileImpl::Read(void* buffer, std::size_t size)
	{
		ssize_t bytes;
		if ((bytes = read(m_fileDescriptor, buffer, size)) != -1)
		{
			m_endOfFile = (static_cast<std::size_t>(bytes) != size);
			m_endOfFileUpdated = true;

			return static_cast<std::size_t>(bytes);
		}
		else
			return 0;
	}

	bool FileImpl::SetCursorPos(CursorPosition pos, Int64 offset)
	{
		int moveMethod;
		switch (pos)
		{
			case CursorPosition_AtBegin:
				moveMethod = SEEK_SET;
				break;

			case CursorPosition_AtCurrent:
				moveMethod = SEEK_CUR;
				break;

			case CursorPosition_AtEnd:
				moveMethod = SEEK_END;
				break;

			default:
				NazaraInternalError("Cursor position not handled (0x" + String::Number(pos, 16) + ')');
				return false;
		}

		m_endOfFileUpdated = false;

		return lseek64(m_fileDescriptor, offset, moveMethod) != -1;
	}

	std::size_t FileImpl::Write(const void* buffer, std::size_t size)
	{
		lockf64(m_fileDescriptor, F_LOCK, size);
		ssize_t written = write(m_fileDescriptor, buffer, size);
		lockf64(m_fileDescriptor, F_ULOCK, size);

		m_endOfFileUpdated = false;

		return written;
	}

	bool FileImpl::Copy(const String& sourcePath, const String& targetPath)
	{
		int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY);
		if (fd1 == -1)
		{
			NazaraError("Fail to open input file (" + sourcePath + "): " + Error::GetLastSystemError());
			return false;
		}

		mode_t permissions; // TODO : get permission from first file
		int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions);
		if (fd2 == -1)
		{
			NazaraError("Fail to open output file (" + targetPath + "): " + Error::GetLastSystemError()); // TODO: more info ?
			close(fd1);
			return false;
		}

		char buffer[512];
		ssize_t bytes;
		do
		{
			bytes = read(fd1,buffer,512);
			if (bytes == -1)
			{
				close(fd1);
				close(fd2);
				NazaraError("An error occured from copy : " + Error::GetLastSystemError());
				return false;
			}
			write(fd2,buffer,bytes);
		}
		while (bytes == 512);

		close(fd1);
		close(fd2);
		return true;
	}

	bool FileImpl::Delete(const String& filePath)
	{
		bool success = unlink(filePath.GetConstBuffer()) != -1;

		if (success)
			return true;
		else
		{
			NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
			return false;
		}
	}

	bool FileImpl::Exists(const String& filePath)
	{
		const char* path = filePath.GetConstBuffer();
		if (access(path, F_OK) != -1)
			return true;

		return false;
	}

	time_t FileImpl::GetCreationTime(const String& filePath)
	{
		NazaraWarning("Posix has no creation time information");

		return 0;
	}

	time_t FileImpl::GetLastAccessTime(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return stats.st_atime;
	}

	time_t FileImpl::GetLastWriteTime(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return stats.st_mtime;
	}

	UInt64 FileImpl::GetSize(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return static_cast<UInt64>(stats.st_size);
	}

	bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
	{
		bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1;

		if (success)
			return true;
		else
		{
			NazaraError("Unable to rename file: " + Error::GetLastSystemError());
			return false;
		}
	}
}
<commit_msg>Core/Posix: Fix file opening in ReadWrite mode<commit_after>// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Posix/FileImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <cstdio>
#include <Nazara/Core/Debug.hpp>

namespace Nz
{
	FileImpl::FileImpl(const File* parent) :
	m_endOfFile(false),
	m_endOfFileUpdated(true)
	{
		NazaraUnused(parent);
	}

	void FileImpl::Close()
	{
        	if (m_fileDescriptor != -1)
        		close(m_fileDescriptor);
	}

	bool FileImpl::EndOfFile() const
	{
		if (!m_endOfFileUpdated)
		{
			struct stat64 fileSize;
			if (fstat64(m_fileDescriptor, &fileSize) == -1)
				fileSize.st_size = 0;

			m_endOfFile = (GetCursorPos() >= static_cast<UInt64>(fileSize.st_size));
			m_endOfFileUpdated = true;
		}

		return m_endOfFile;
	}

	void FileImpl::Flush()
	{
		if (fsync(m_fileDescriptor) == -1)
			NazaraError("Unable to flush file: " + Error::GetLastSystemError());
	}

	UInt64 FileImpl::GetCursorPos() const
	{
		off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR);
		return static_cast<UInt64>(position);
	}

	bool FileImpl::Open(const String& filePath, UInt32 mode)
	{
		int flags;
		mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

		if (mode & OpenMode_ReadWrite)
			flags = O_CREAT | O_RDWR;
		else if (mode & OpenMode_ReadOnly)
			flags = O_RDONLY;
		else if (mode & OpenMode_WriteOnly)
			flags = O_CREAT | O_WRONLY;
		else
			return false;

		if (mode & OpenMode_Append)
			flags |= O_APPEND;

		if (mode & OpenMode_Truncate)
			flags |= O_TRUNC;

	///TODO: lock
	//	if ((mode & OpenMode_Lock) == 0)
	//		shareMode |= FILE_SHARE_WRITE;

		m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
		return m_fileDescriptor != -1;
	}

	std::size_t FileImpl::Read(void* buffer, std::size_t size)
	{
		ssize_t bytes;
		if ((bytes = read(m_fileDescriptor, buffer, size)) != -1)
		{
			m_endOfFile = (static_cast<std::size_t>(bytes) != size);
			m_endOfFileUpdated = true;

			return static_cast<std::size_t>(bytes);
		}
		else
			return 0;
	}

	bool FileImpl::SetCursorPos(CursorPosition pos, Int64 offset)
	{
		int moveMethod;
		switch (pos)
		{
			case CursorPosition_AtBegin:
				moveMethod = SEEK_SET;
				break;

			case CursorPosition_AtCurrent:
				moveMethod = SEEK_CUR;
				break;

			case CursorPosition_AtEnd:
				moveMethod = SEEK_END;
				break;

			default:
				NazaraInternalError("Cursor position not handled (0x" + String::Number(pos, 16) + ')');
				return false;
		}

		m_endOfFileUpdated = false;

		return lseek64(m_fileDescriptor, offset, moveMethod) != -1;
	}

	std::size_t FileImpl::Write(const void* buffer, std::size_t size)
	{
		lockf64(m_fileDescriptor, F_LOCK, size);
		ssize_t written = write(m_fileDescriptor, buffer, size);
		lockf64(m_fileDescriptor, F_ULOCK, size);

		m_endOfFileUpdated = false;

		return written;
	}

	bool FileImpl::Copy(const String& sourcePath, const String& targetPath)
	{
		int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY);
		if (fd1 == -1)
		{
			NazaraError("Fail to open input file (" + sourcePath + "): " + Error::GetLastSystemError());
			return false;
		}

		mode_t permissions; // TODO : get permission from first file
		int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions);
		if (fd2 == -1)
		{
			NazaraError("Fail to open output file (" + targetPath + "): " + Error::GetLastSystemError()); // TODO: more info ?
			close(fd1);
			return false;
		}

		char buffer[512];
		ssize_t bytes;
		do
		{
			bytes = read(fd1,buffer,512);
			if (bytes == -1)
			{
				close(fd1);
				close(fd2);
				NazaraError("An error occured from copy : " + Error::GetLastSystemError());
				return false;
			}
			write(fd2,buffer,bytes);
		}
		while (bytes == 512);

		close(fd1);
		close(fd2);
		return true;
	}

	bool FileImpl::Delete(const String& filePath)
	{
		bool success = unlink(filePath.GetConstBuffer()) != -1;

		if (success)
			return true;
		else
		{
			NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
			return false;
		}
	}

	bool FileImpl::Exists(const String& filePath)
	{
		const char* path = filePath.GetConstBuffer();
		if (access(path, F_OK) != -1)
			return true;

		return false;
	}

	time_t FileImpl::GetCreationTime(const String& filePath)
	{
		NazaraWarning("Posix has no creation time information");

		return 0;
	}

	time_t FileImpl::GetLastAccessTime(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return stats.st_atime;
	}

	time_t FileImpl::GetLastWriteTime(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return stats.st_mtime;
	}

	UInt64 FileImpl::GetSize(const String& filePath)
	{
		struct stat64 stats;
		stat64(filePath.GetConstBuffer(), &stats);

		return static_cast<UInt64>(stats.st_size);
	}

	bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
	{
		bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1;

		if (success)
			return true;
		else
		{
			NazaraError("Unable to rename file: " + Error::GetLastSystemError());
			return false;
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Utility/IndexMapper.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/IndexIterator.hpp>
#include <Nazara/Utility/SubMesh.hpp>
#include <Nazara/Utility/Debug.hpp>

namespace
{
	nzUInt32 Getter16(const void* buffer, unsigned int i)
	{
		const nzUInt16* ptr = reinterpret_cast<const nzUInt16*>(buffer);
		return ptr[i];
	}

	nzUInt32 Getter32(const void* buffer, unsigned int i)
	{
		const nzUInt32* ptr = reinterpret_cast<const nzUInt32*>(buffer);
		return ptr[i];
	}

	nzUInt32 GetterSequential(const void* buffer, unsigned int i)
	{
		NazaraUnused(buffer);

		return static_cast<nzUInt32>(i);
	}

	void Setter16(void* buffer, unsigned int i, nzUInt32 value)
	{
		nzUInt16* ptr = reinterpret_cast<nzUInt16*>(buffer);
		ptr[i] = static_cast<nzUInt16>(value);
	}

	void Setter32(void* buffer, unsigned int i, nzUInt32 value)
	{
		nzUInt32* ptr = reinterpret_cast<nzUInt32*>(buffer);
		ptr[i] = value;
	}

	void SetterError(void*, unsigned int, nzUInt32)
	{
		NazaraError("Index buffer opened with read-only access");
	}
}

NzIndexMapper::NzIndexMapper(NzIndexBuffer* indexBuffer, nzBufferAccess access)
{
	if (indexBuffer && !indexBuffer->IsSequential())
	{
		if (!m_mapper.Map(indexBuffer, access))
			NazaraError("Failed to map buffer"); ///TODO: Unexcepted

		if (indexBuffer->HasLargeIndices())
		{
			m_getter = Getter32;
			if (access != nzBufferAccess_ReadOnly)
				m_setter = Setter32;
			else
				m_setter = SetterError;
		}
		else
		{
			m_getter = Getter16;
			if (access != nzBufferAccess_ReadOnly)
				m_setter = Setter16;
			else
				m_setter = SetterError;
		}
	}
	else
	{
		m_getter = GetterSequential;
		m_setter = SetterError;
	}
}

NzIndexMapper::NzIndexMapper(const NzIndexBuffer* indexBuffer, nzBufferAccess access) :
m_setter(SetterError)
{
	if (indexBuffer && !indexBuffer->IsSequential())
	{
		if (!m_mapper.Map(indexBuffer, access))
			NazaraError("Failed to map buffer"); ///TODO: Unexcepted

		if (indexBuffer->HasLargeIndices())
			m_getter = Getter32;
		else
			m_getter = Getter16;
	}
	else
		m_getter = GetterSequential;
}

NzIndexMapper::NzIndexMapper(const NzSubMesh* subMesh) :
NzIndexMapper(subMesh->GetIndexBuffer())
{
}

nzUInt32 NzIndexMapper::Get(unsigned int i) const
{
	#if NAZARA_UTILITY_SAFE
	if (i >= m_indexCount)
	{
		NazaraError("Index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_indexCount) + ')');
		return 0;
	}
	#endif

	return m_getter(m_mapper.GetPointer(), i);
}

const NzIndexBuffer* NzIndexMapper::GetBuffer() const
{
	return m_mapper.GetBuffer();
}

unsigned int NzIndexMapper::GetIndexCount() const
{
	return m_indexCount;
}

void NzIndexMapper::Set(unsigned int i, nzUInt32 value)
{
	#if NAZARA_UTILITY_SAFE
	if (i >= m_indexCount)
	{
		NazaraError("Index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_indexCount) + ')');
		return;
	}
	#endif

	m_setter(m_mapper.GetPointer(), i, value);
}

void NzIndexMapper::Unmap()
{
	m_mapper.Unmap();
}

NzIndexIterator NzIndexMapper::begin()
{
	return NzIndexIterator(this, 0);
}

NzIndexIterator NzIndexMapper::end()
{
	return NzIndexIterator(this, m_indexCount); // Post-end
}
<commit_msg>Fixed IndexMapper not working in safe mode<commit_after>// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Utility/IndexMapper.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/IndexIterator.hpp>
#include <Nazara/Utility/SubMesh.hpp>
#include <Nazara/Utility/Debug.hpp>

namespace
{
	nzUInt32 Getter16(const void* buffer, unsigned int i)
	{
		const nzUInt16* ptr = reinterpret_cast<const nzUInt16*>(buffer);
		return ptr[i];
	}

	nzUInt32 Getter32(const void* buffer, unsigned int i)
	{
		const nzUInt32* ptr = reinterpret_cast<const nzUInt32*>(buffer);
		return ptr[i];
	}

	nzUInt32 GetterSequential(const void* buffer, unsigned int i)
	{
		NazaraUnused(buffer);

		return static_cast<nzUInt32>(i);
	}

	void Setter16(void* buffer, unsigned int i, nzUInt32 value)
	{
		nzUInt16* ptr = reinterpret_cast<nzUInt16*>(buffer);
		ptr[i] = static_cast<nzUInt16>(value);
	}

	void Setter32(void* buffer, unsigned int i, nzUInt32 value)
	{
		nzUInt32* ptr = reinterpret_cast<nzUInt32*>(buffer);
		ptr[i] = value;
	}

	void SetterError(void*, unsigned int, nzUInt32)
	{
		NazaraError("Index buffer opened with read-only access");
	}
}

NzIndexMapper::NzIndexMapper(NzIndexBuffer* indexBuffer, nzBufferAccess access) :
m_indexCount(indexBuffer->GetIndexCount())
{
	if (indexBuffer && !indexBuffer->IsSequential())
	{
		if (!m_mapper.Map(indexBuffer, access))
			NazaraError("Failed to map buffer"); ///TODO: Unexcepted

		if (indexBuffer->HasLargeIndices())
		{
			m_getter = Getter32;
			if (access != nzBufferAccess_ReadOnly)
				m_setter = Setter32;
			else
				m_setter = SetterError;
		}
		else
		{
			m_getter = Getter16;
			if (access != nzBufferAccess_ReadOnly)
				m_setter = Setter16;
			else
				m_setter = SetterError;
		}
	}
	else
	{
		m_getter = GetterSequential;
		m_setter = SetterError;
	}
}

NzIndexMapper::NzIndexMapper(const NzIndexBuffer* indexBuffer, nzBufferAccess access) :
m_setter(SetterError),
m_indexCount(indexBuffer->GetIndexCount())
{
	if (indexBuffer && !indexBuffer->IsSequential())
	{
		if (!m_mapper.Map(indexBuffer, access))
			NazaraError("Failed to map buffer"); ///TODO: Unexcepted

		if (indexBuffer->HasLargeIndices())
			m_getter = Getter32;
		else
			m_getter = Getter16;
	}
	else
		m_getter = GetterSequential;
}

NzIndexMapper::NzIndexMapper(const NzSubMesh* subMesh) :
NzIndexMapper(subMesh->GetIndexBuffer())
{
}

nzUInt32 NzIndexMapper::Get(unsigned int i) const
{
	#if NAZARA_UTILITY_SAFE
	if (i >= m_indexCount)
	{
		NazaraError("Index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_indexCount) + ')');
		return 0;
	}
	#endif

	return m_getter(m_mapper.GetPointer(), i);
}

const NzIndexBuffer* NzIndexMapper::GetBuffer() const
{
	return m_mapper.GetBuffer();
}

unsigned int NzIndexMapper::GetIndexCount() const
{
	return m_indexCount;
}

void NzIndexMapper::Set(unsigned int i, nzUInt32 value)
{
	#if NAZARA_UTILITY_SAFE
	if (i >= m_indexCount)
	{
		NazaraError("Index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_indexCount) + ')');
		return;
	}
	#endif

	m_setter(m_mapper.GetPointer(), i, value);
}

void NzIndexMapper::Unmap()
{
	m_mapper.Unmap();
}

NzIndexIterator NzIndexMapper::begin()
{
	return NzIndexIterator(this, 0);
}

NzIndexIterator NzIndexMapper::end()
{
	return NzIndexIterator(this, m_indexCount); // Post-end
}
<|endoftext|>