<commit_before>#include "slicerconfigurationprivate.h"

namespace conveyor
{

    SlicerConfiguration *
    SlicerConfigurationPrivate::defaultConfiguration(SlicerConfiguration::Quality quality)
    {
        Json::Value null;
        SlicerConfiguration * const config(new SlicerConfiguration(null));

        switch(quality)
        {
        case SlicerConfiguration::LowQuality:
            config->setSlicer(SlicerConfiguration::MiracleGrue);
            config->setLayerHeight(.3);
            break;
        case SlicerConfiguration::MediumQuality:
            config->setSlicer(SlicerConfiguration::MiracleGrue);
            break;
        case SlicerConfiguration::HighQuality:
            config->setSlicer(SlicerConfiguration::Skeinforge);
            break;
        }
        return config;
    }

    SlicerConfigurationPrivate::SlicerConfigurationPrivate(Json::Value &) :
        m_slicer(SlicerConfiguration::MiracleGrue),
        m_extruder(SlicerConfiguration::Left),
        m_raft(true),
        m_supports(false),
        m_infill(0.90),
        m_layerHeight(0.2),
        m_shells(3),
        m_extruderTemperature(220),
        m_platformTemperature(220),
        m_printSpeed(80),
        m_travelSpeed(150)
    {
        // TODO
    }

    Json::Value SlicerConfigurationPrivate::toJSON() const
    {
        Json::Value root;

        // Slicer name and min/max versions
        root["slicer"] = slicerName().toStdString();

        // TODO: rewrite the software stack, using strings
        // instead of integers to represent toolheads
        root["extruder"] = 0;

        root["raft"] = m_raft;
        root["support"] = m_supports;

        root["infill"] = m_infill;
        root["layer_height"] = m_layerHeight;
        root["shells"] = m_shells;

        root["extruder_temperature"] = m_extruderTemperature;
        root["platform_temperature"] = m_platformTemperature;

        root["travel_speed"] = m_travelSpeed;
        root["print_speed"] = m_printSpeed;

        return root;
    }

    SlicerConfiguration::Slicer SlicerConfigurationPrivate::slicer() const
    {
        return m_slicer;
    }

    QString SlicerConfigurationPrivate::slicerName() const
    {
        switch (m_slicer) {
        case SlicerConfiguration::Skeinforge:
            return "SKEINFORGE";
        case SlicerConfiguration::MiracleGrue:
            return "MIRACLEGRUE";
        default:
            return QString();
        }
    }

    SlicerConfiguration::Extruder SlicerConfigurationPrivate::extruder() const
    {
        return m_extruder;
    }

    QString SlicerConfigurationPrivate::extruderName() const
    {
        switch (m_extruder) {
        case SlicerConfiguration::Left:
            return "Left";
        case SlicerConfiguration::Right:
            return "Right";
        default:
            return QString();
        }
    }

    bool SlicerConfigurationPrivate::raft() const
    {
        return m_raft;
    }

    bool SlicerConfigurationPrivate::supports() const
    {
        return m_supports;
    }

    double SlicerConfigurationPrivate::infill() const
    {
        return m_infill;
    }

    double SlicerConfigurationPrivate::layerHeight() const
    {
        return m_layerHeight;
    }

    unsigned SlicerConfigurationPrivate::shells() const
    {
        return m_shells;
    }

    unsigned SlicerConfigurationPrivate::extruderTemperature() const
    {
        return m_extruderTemperature;
    }

    unsigned SlicerConfigurationPrivate::platformTemperature() const
    {
        return m_platformTemperature;
    }

    unsigned SlicerConfigurationPrivate::printSpeed() const
    {
        return m_printSpeed;
    }

    unsigned SlicerConfigurationPrivate::travelSpeed() const
    {
        return m_travelSpeed;
    }

    void SlicerConfigurationPrivate::setSlicer(SlicerConfiguration::Slicer slicer)
    {
        m_slicer = slicer;
    }

    void SlicerConfigurationPrivate::setExtruder(SlicerConfiguration::Extruder extruder)
    {
        m_extruder = extruder;
    }

    void SlicerConfigurationPrivate::setRaft(bool raft)
    {
        m_raft = raft;
    }

    void SlicerConfigurationPrivate::setSupports(bool supports)
    {
        m_supports = supports;
    }

    void SlicerConfigurationPrivate::setInfill(double infill)
    {
        m_infill = infill;
    }

    void SlicerConfigurationPrivate::setLayerHeight(double height)
    {
        m_layerHeight = height;
    }

    void SlicerConfigurationPrivate::setShells(unsigned shells)
    {
        m_shells = shells;
    }

    void SlicerConfigurationPrivate::setExtruderTemperature(unsigned temperature)
    {
        m_extruderTemperature = temperature;
    }

    void SlicerConfigurationPrivate::setPlatformTemperature(unsigned temperature)
    {
        m_platformTemperature = temperature;
    }

    void SlicerConfigurationPrivate::setPrintSpeed(unsigned speed)
    {
        m_printSpeed = speed;
    }

    void SlicerConfigurationPrivate::setTravelSpeed(unsigned speed)
    {
        m_travelSpeed = speed;
    }
}
<commit_msg>Set default platform temperature to 110 instead of 220<commit_after>#include "slicerconfigurationprivate.h"

namespace conveyor
{

    SlicerConfiguration *
    SlicerConfigurationPrivate::defaultConfiguration(SlicerConfiguration::Quality quality)
    {
        Json::Value null;
        SlicerConfiguration * const config(new SlicerConfiguration(null));

        switch(quality)
        {
        case SlicerConfiguration::LowQuality:
            config->setSlicer(SlicerConfiguration::MiracleGrue);
            config->setLayerHeight(.3);
            break;
        case SlicerConfiguration::MediumQuality:
            config->setSlicer(SlicerConfiguration::MiracleGrue);
            break;
        case SlicerConfiguration::HighQuality:
            config->setSlicer(SlicerConfiguration::Skeinforge);
            break;
        }
        return config;
    }

    SlicerConfigurationPrivate::SlicerConfigurationPrivate(Json::Value &) :
        m_slicer(SlicerConfiguration::MiracleGrue),
        m_extruder(SlicerConfiguration::Left),
        m_raft(true),
        m_supports(false),
        m_infill(0.90),
        m_layerHeight(0.2),
        m_shells(3),
        m_extruderTemperature(220),
        m_platformTemperature(110),
        m_printSpeed(80),
        m_travelSpeed(150)
    {
        // TODO
    }

    Json::Value SlicerConfigurationPrivate::toJSON() const
    {
        Json::Value root;

        // Slicer name and min/max versions
        root["slicer"] = slicerName().toStdString();

        // TODO: rewrite the software stack, using strings
        // instead of integers to represent toolheads
        root["extruder"] = 0;

        root["raft"] = m_raft;
        root["support"] = m_supports;

        root["infill"] = m_infill;
        root["layer_height"] = m_layerHeight;
        root["shells"] = m_shells;

        root["extruder_temperature"] = m_extruderTemperature;
        root["platform_temperature"] = m_platformTemperature;

        root["travel_speed"] = m_travelSpeed;
        root["print_speed"] = m_printSpeed;

        return root;
    }

    SlicerConfiguration::Slicer SlicerConfigurationPrivate::slicer() const
    {
        return m_slicer;
    }

    QString SlicerConfigurationPrivate::slicerName() const
    {
        switch (m_slicer) {
        case SlicerConfiguration::Skeinforge:
            return "SKEINFORGE";
        case SlicerConfiguration::MiracleGrue:
            return "MIRACLEGRUE";
        default:
            return QString();
        }
    }

    SlicerConfiguration::Extruder SlicerConfigurationPrivate::extruder() const
    {
        return m_extruder;
    }

    QString SlicerConfigurationPrivate::extruderName() const
    {
        switch (m_extruder) {
        case SlicerConfiguration::Left:
            return "Left";
        case SlicerConfiguration::Right:
            return "Right";
        default:
            return QString();
        }
    }

    bool SlicerConfigurationPrivate::raft() const
    {
        return m_raft;
    }

    bool SlicerConfigurationPrivate::supports() const
    {
        return m_supports;
    }

    double SlicerConfigurationPrivate::infill() const
    {
        return m_infill;
    }

    double SlicerConfigurationPrivate::layerHeight() const
    {
        return m_layerHeight;
    }

    unsigned SlicerConfigurationPrivate::shells() const
    {
        return m_shells;
    }

    unsigned SlicerConfigurationPrivate::extruderTemperature() const
    {
        return m_extruderTemperature;
    }

    unsigned SlicerConfigurationPrivate::platformTemperature() const
    {
        return m_platformTemperature;
    }

    unsigned SlicerConfigurationPrivate::printSpeed() const
    {
        return m_printSpeed;
    }

    unsigned SlicerConfigurationPrivate::travelSpeed() const
    {
        return m_travelSpeed;
    }

    void SlicerConfigurationPrivate::setSlicer(SlicerConfiguration::Slicer slicer)
    {
        m_slicer = slicer;
    }

    void SlicerConfigurationPrivate::setExtruder(SlicerConfiguration::Extruder extruder)
    {
        m_extruder = extruder;
    }

    void SlicerConfigurationPrivate::setRaft(bool raft)
    {
        m_raft = raft;
    }

    void SlicerConfigurationPrivate::setSupports(bool supports)
    {
        m_supports = supports;
    }

    void SlicerConfigurationPrivate::setInfill(double infill)
    {
        m_infill = infill;
    }

    void SlicerConfigurationPrivate::setLayerHeight(double height)
    {
        m_layerHeight = height;
    }

    void SlicerConfigurationPrivate::setShells(unsigned shells)
    {
        m_shells = shells;
    }

    void SlicerConfigurationPrivate::setExtruderTemperature(unsigned temperature)
    {
        m_extruderTemperature = temperature;
    }

    void SlicerConfigurationPrivate::setPlatformTemperature(unsigned temperature)
    {
        m_platformTemperature = temperature;
    }

    void SlicerConfigurationPrivate::setPrintSpeed(unsigned speed)
    {
        m_printSpeed = speed;
    }

    void SlicerConfigurationPrivate::setTravelSpeed(unsigned speed)
    {
        m_travelSpeed = speed;
    }
}
<|endoftext|>


<commit_before>#ifndef ITER_RANGE_H_
#define ITER_RANGE_H_

// range() for range-based loops with start, stop, and step.
//
// Acceptable forms are:
// for (auto i : range(stop)) { ... } // start = 0, step = 1
// for (auto i : range(start, stop)) { ... } // step = 1
// for (auto i : range(start, stop, step)) { ... }
//
// The start may be greater than the stop if the range is negative
// The range will effectively be empty if:
//   1) step is positive and start > stop
//   2) step is negative and start < stop
//
// If a step of 0 is provided, a RangeException will be thrown

#include <exception>
#include <type_traits>
#include <iterator>
#include <cassert>

namespace iter {

    // Thrown when step 0 occurs
    class RangeException : public std::exception {
        const char *what() const noexcept override {
            return "range step must be non-zero";
        }
    };

    template <typename T, bool IsFloat =false>
    class Range;

    template <typename T, bool IsFloat =std::is_floating_point<T>::value>
    Range<T, IsFloat> range(T);
    template <typename T, bool IsFloat =std::is_floating_point<T>::value>
    Range<T, IsFloat> range(T, T);
    template <typename T, bool IsFloat =std::is_floating_point<T>::value>
    Range<T, IsFloat> range(T, T, T);

    // General version for everything not a float
    template <typename T, bool>
    class Range {
        friend Range range<T, false>(T);
        friend Range range<T, false>(T, T);
        friend Range range<T, false>(T, T, T);
        private:
            const T start;
            const T stop;
            const T step;

            Range(T in_stop)
                : start{0},
                stop{in_stop},
                step{1}
            { }

            Range(T in_start, T in_stop, T in_step =1)
                : start{in_start},
                stop{in_stop},
                step{in_step}
            { }

        public:
            class Iterator
                : public std::iterator<std::forward_iterator_tag, T>
            {
                private:
                    T value;
                    T step;
                    bool is_end;

                    // compare unsigned values
                    static bool not_equal_to_impl(
                            const Iterator& iter, const Iterator& end_iter,
                            std::true_type ) {
                        assert(!iter.is_end);
                        assert(end_iter.is_end);
                        return iter.value < end_iter.value;
                    }

                    // compare signed values
                    static bool not_equal_to_impl(
                            const Iterator& iter, const Iterator& end_iter,
                            std::false_type) {
                        assert(!iter.is_end);
                        assert(end_iter.is_end);
                        return !(iter.step > 0 && iter.value >= end_iter.value)
                            && !(iter.step < 0 && iter.value <= end_iter.value);
                    }

                    static bool not_equal_to_end(
                            const Iterator& lhs, const Iterator& rhs) {
                        if (rhs.is_end) {
                            return not_equal_to_impl(
                                    lhs, rhs, std::is_unsigned<T>{});
                        } else {
                            return not_equal_to_impl(
                                    rhs, lhs, std::is_unsigned<T>{});
                        }
                    }

                public:
                    Iterator() =default;

                    Iterator(T val, T in_step, bool in_is_end)
                        : value{val},
                        step{in_step},
                        is_end{in_is_end}
                    { }

                    T operator*() const {
                        return this->value;
                    }

                    Iterator& operator++() {
                        this->value += this->step;
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    // This operator would more accurately read as "in bounds"
                    // or "incomplete" because exact comparison with the end
                    // isn't good enough for the purposes of this Iterator.
                    // There are two odd cases that need to be handled
                    //
                    // 1) The Range is infinite, such as
                    // Range (-1, 0, -1) which would go forever down toward
                    // infinitely (theoretically).  If this occurs, the Range
                    // will instead effectively be empty
                    //
                    // 2) (stop - start) % step != 0.  For
                    // example Range(1, 10, 2).  The iterator will never be
                    // exactly equal to the stop value.
                    //
                    // Another way to think about it is that the "end"
                    // iterator represents the range of values that are invalid
                    // So, if an iterator is not equal to that, it is valid
                    bool operator!=(const Iterator& other) const {
                        if (this->is_end && other.is_end) {
                            return false;
                        }

                        if (!this->is_end && !other.is_end) {
                            return this->value != other.value;
                        }
                        return not_equal_to_end(*this, other);
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() const {
                return {start, step, false};
            }

            Iterator end() const {
                return {stop, step, true};
            }
    };

    // This specialization is used for floating point types.  Instead of
    // adding one "step" each time ++ is called on the iterator, the value
    // is recalculated as start + (steps_taken + step_size) to avoid
    // accumulating floating point inaccuracies
    template <typename T>
    class Range<T, true> {
        friend Range range<T, true>(T);
        friend Range range<T, true>(T, T);
        friend Range range<T, true>(T, T, T);
        private:
            const T start;
            const T stop;
            const T step;

            Range(T in_stop)
                : start{0},
                stop{in_stop},
                step{1}
            { }

            Range(T in_start, T in_stop, T in_step =1)
                : start{in_start},
                stop{in_stop},
                step{in_step}
            { }
        public:
            class Iterator
                : public std::iterator<std::forward_iterator_tag, T>
            {
                private:
                    T start;
                    T value;
                    T step;
                    unsigned long steps_taken =0;

                public:
                    Iterator() =default;

                    Iterator(T in_start, T in_step)
                        : start{in_start},
                        value{in_start},
                        step{in_step}
                    { }

                    bool operator!=(const Iterator& other) const {
                        return !(this->step > 0 && this->value >= other.value)
                            && !(this->step < 0 && this->value <= other.value);
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }

                    T operator*() const {
                        return this->value;
                    }

                    Iterator& operator++() {
                        ++this->steps_taken;
                        this->value = this->start +
                            (this->step * this->steps_taken);
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }
            };

            Iterator begin() const {
                return {start, step};
            }

            Iterator end() const {
                return {stop, step};
            }
    };

    template <typename T, bool IsFloat>
    Range<T, IsFloat> range(T stop) {
        return {stop};
    }

    template <typename T, bool IsFloat>
    Range<T, IsFloat> range(T start, T stop) {
        return {start, stop};
    }

    template <typename T, bool IsFloat>
    Range<T, IsFloat> range(T start, T stop, T step) {
        if (step == 0) {
            throw RangeException{};
        }
        return {start, stop, step};
    }
}

#endif // #ifndef ITER_RANGE_H_
<commit_msg>Moves the float specialization into a helper class<commit_after>#ifndef ITER_RANGE_H_
#define ITER_RANGE_H_

// range() for range-based loops with start, stop, and step.
//
// Acceptable forms are:
// for (auto i : range(stop)) { ... } // start = 0, step = 1
// for (auto i : range(start, stop)) { ... } // step = 1
// for (auto i : range(start, stop, step)) { ... }
//
// The start may be greater than the stop if the range is negative
// The range will effectively be empty if:
//   1) step is positive and start > stop
//   2) step is negative and start < stop
//
// If a step of 0 is provided, a RangeException will be thrown

#include <exception>
#include <type_traits>
#include <iterator>
#include <cassert>

namespace iter {

    template <typename T, bool IsFloat=std::is_floating_point<T>::value>
    class RangeIterData;

    // everything except floats
    template <typename T>
    class RangeIterData<T, false> {
        private:
            T value_{};
            T step_{};
        public:
            RangeIterData() =default;
            RangeIterData(T in_value, T in_step)
                : value_{in_value},
                step_{in_step}
            { }

            T value() const {
                return this->value_;
            }

            T step() const {
                return this->step_;
            }

            void inc() {
                this->value_ += step_;
            }

            bool operator==(const RangeIterData& other) const {
              return this->value_ == other.value_;
            }

            bool operator!=(const RangeIterData& other) const {
              return !(*this == other);
            }
    };

    // float data
    template <typename T>
    class RangeIterData<T, true> {
        private:
            T start_{};
            T value_{};
            T step_{};
            unsigned long steps_taken{};
        public:
            RangeIterData() =default;
            RangeIterData(T in_start, T in_step)
                : start_{in_start},
                value_{in_start},
                step_{in_step}
            { }

            T value() const {
                return this->value_;
            }

            T step() const {
                return this->step_;
            }

            void inc() {
                ++this->steps_taken;
                value_ = this->start_ +
                        (this->step_ * this->steps_taken);
            }

            bool operator==(const RangeIterData& other) const {
                // if the difference between the two values is less than the
                // step size, they are considered equal
                T diff = this->value_ < other.value_ ?
                    other.value_ - this->value_ : this->value_ - other.value_;
                return diff < step_;
            }

            bool operator!=(const RangeIterData& other) const {
              return !(*this == other);
            }
    };

    // Thrown when step 0 occurs
    class RangeException : public std::exception {
        const char *what() const noexcept override {
            return "range step must be non-zero";
        }
    };

    template <typename T>
    class Range;

    template <typename T>
    Range<T> range(T);
    template <typename T>
    Range<T> range(T, T);
    template <typename T>
    Range<T> range(T, T, T);

    // General version for everything not a float
    template <typename T>
    class Range {
        friend Range range<T>(T);
        friend Range range<T>(T, T);
        friend Range range<T>(T, T, T);
        private:
            const T start;
            const T stop;
            const T step;

            Range(T in_stop)
                : start{0},
                stop{in_stop},
                step{1}
            { }

            Range(T in_start, T in_stop, T in_step =1)
                : start{in_start},
                stop{in_stop},
                step{in_step}
            { }

        public:
            class Iterator
                : public std::iterator<std::forward_iterator_tag, T>
            {
                private:
                    RangeIterData<T> data;
                    bool is_end;

                    // compare unsigned values
                    static bool not_equal_to_impl(
                            const Iterator& iter, const Iterator& end_iter,
                            std::true_type ) {
                        assert(!iter.is_end);
                        assert(end_iter.is_end);
                        return iter.data.value() < end_iter.data.value();
                    }

                    // compare signed values
                    static bool not_equal_to_impl(
                            const Iterator& iter, const Iterator& end_iter,
                            std::false_type) {
                        assert(!iter.is_end);
                        assert(end_iter.is_end);
                        return !(iter.data.step() > 0 && iter.data.value()
                                 >= end_iter.data.value())
                            && !(iter.data.step() < 0 && iter.data.value()
                                 <= end_iter.data.value());
                    }

                    static bool not_equal_to_end(
                            const Iterator& lhs, const Iterator& rhs) {
                        if (rhs.is_end) {
                            return not_equal_to_impl(
                                    lhs, rhs, std::is_unsigned<T>{});
                        } else {
                            return not_equal_to_impl(
                                    rhs, lhs, std::is_unsigned<T>{});
                        }
                    }

                public:
                    Iterator() =default;

                    Iterator(T in_value, T in_step, bool in_is_end)
                        : data(in_value, in_step),
                        is_end{in_is_end}
                    { }

                    T operator*() const {
                        return this->data.value();
                    }

                    Iterator& operator++() {
                        this->data.inc();
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    // This operator would more accurately read as "in bounds"
                    // or "incomplete" because exact comparison with the end
                    // isn't good enough for the purposes of this Iterator.
                    // There are two odd cases that need to be handled
                    //
                    // 1) The Range is infinite, such as
                    // Range (-1, 0, -1) which would go forever down toward
                    // infinitely (theoretically).  If this occurs, the Range
                    // will instead effectively be empty
                    //
                    // 2) (stop - start) % step != 0.  For
                    // example Range(1, 10, 2).  The iterator will never be
                    // exactly equal to the stop value.
                    //
                    // Another way to think about it is that the "end"
                    // iterator represents the range of values that are invalid
                    // So, if an iterator is not equal to that, it is valid
                    //
                    // Two end iterators will compare equal
                    //
                    // Two non-end iterators will compare by their stored values
                    bool operator!=(const Iterator& other) const {
                        if (this->is_end && other.is_end) {
                            return false;
                        }

                        if (!this->is_end && !other.is_end) {
                            return this->data != other.data;
                        }
                        return not_equal_to_end(*this, other);
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() const {
                return {start, step, false};
            }

            Iterator end() const {
                return {stop, step, true};
            }
    };

    template <typename T>
    Range<T> range(T stop) {
        return {stop};
    }

    template <typename T>
    Range<T> range(T start, T stop) {
        return {start, stop};
    }

    template <typename T>
    Range<T> range(T start, T stop, T step) {
        if (step == 0) {
            throw RangeException{};
        }
        return {start, stop, step};
    }
}

#endif // #ifndef ITER_RANGE_H_
<|endoftext|>


<commit_before>#ifndef ITER_IMAP_H_
#define ITER_IMAP_H_

#include "zip.hpp"

#include <utility>
#include <type_traits>

namespace iter {

    namespace detail {

    template <std::size_t Index, typename Functor, typename Tup>
    struct Expander {
        template <typename... Ts>
        static auto call(Functor&& f, Tup&& tup, Ts&&... args)
            -> decltype(Expander<Index-1, Functor, Tup>::call(
                    std::forward<Functor>(f),
                    std::forward<Tup>(tup),
                    std::get<Index-1>(tup),
                    std::forward<Ts>(args)...))
        {
            // recurse
            return Expander<Index-1, Functor, Tup>::call(
                    std::forward<Functor>(f),
                    std::forward<Tup>(tup),
                    std::get<Index-1>(tup), // pull out one element
                    std::forward<Ts>(args)...); // everything already expanded
        }
    };

    template <typename Functor, typename Tup>
    struct Expander<0, Functor, Tup> {
        template <typename... Ts>
        static auto call(Functor&& f, Tup&&, Ts&&... args)
            -> decltype(f(std::forward<Ts>(args)...))
        {
            static_assert(
                std::tuple_size<
                    typename std::remove_reference<Tup>::type>::value
                    == sizeof...(Ts),
                "tuple has not been fully expanded");
            return f(std::forward<Ts>(args)...); // the actual call
        }
    };

    template <typename Functor, typename Tup>
    auto call_with_tuple(Functor&& f, Tup&& tup)
        -> decltype(Expander<std::tuple_size<
                    typename std::remove_reference<Tup>::type>::value,
                    Functor, Tup>::call(
                        std::forward<Functor>(f),
                        std::forward<Tup>(tup)))
    {
        return Expander<std::tuple_size<
            typename std::remove_reference<Tup>::type>::value,
            Functor, Tup>::call(
                std::forward<Functor>(f),
                std::forward<Tup>(tup));
    }

    } // end detail

    //Forward declarations of IMap and imap
    template <typename MapFunc, typename... Containers>
    class IMap;

    template <typename MapFunc, typename... Containers>
    IMap<MapFunc, Containers...> imap(MapFunc, Containers&&...);

    template <typename MapFunc, typename... Containers>
    class IMap {
        // The imap function is the only thing allowed to create a IMap
        friend IMap imap<MapFunc, Containers...>(MapFunc, Containers&& ...);

        using ZippedType = decltype(zip(std::declval<Containers>()...));
        using ZippedIterType = iterator_type<ZippedType>;
        private:
            MapFunc map_func;
            ZippedType zipped;

            using IMapIterDeref = decltype(detail::call_with_tuple(
                        map_func, *std::begin(zipped)));

            // Value constructor for use only in the imap function
            IMap(MapFunc map_func, Containers&& ... containers) :
                map_func(map_func),
                zipped(zip(std::forward<Containers>(containers)...))
            { }
            IMap() = delete;
            IMap& operator=(const IMap&) = delete;

        public:
            IMap(const IMap&) = default;
            IMap(IMap&&) = default;

            class Iterator
                : public std::iterator<std::input_iterator_tag, IMapIterDeref>
            {
                private:
                    MapFunc map_func;
                    ZippedIterType zipiter;

                public:
                    Iterator(MapFunc map_func, ZippedIterType zipiter) :
                        map_func(map_func),
                        zipiter(zipiter)
                    { }

                    IMapIterDeref operator*() {
                        return detail::call_with_tuple(
                                this->map_func, *(this->zipiter));
                    }

                    Iterator& operator++() {
                        ++this->zipiter;
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->zipiter != other.zipiter;
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() {
                return {this->map_func, this->zipped.begin()};
            }

            Iterator end() {
                return {this->map_func, this->zipped.end()};
            }

    };

    // Helper function to instantiate a IMap
    template <typename MapFunc, typename... Containers>
    IMap<MapFunc, Containers...> imap(
            MapFunc map_func, Containers&& ... containers) {
        return {map_func, std::forward<Containers>(containers)...};
    }

}

#endif // #ifndef ITER_IMAP_H_
<commit_msg>removes reference in imap iterator_traits<commit_after>#ifndef ITER_IMAP_H_
#define ITER_IMAP_H_

#include "zip.hpp"

#include <utility>
#include <type_traits>

namespace iter {

    namespace detail {

    template <std::size_t Index, typename Functor, typename Tup>
    struct Expander {
        template <typename... Ts>
        static auto call(Functor&& f, Tup&& tup, Ts&&... args)
            -> decltype(Expander<Index-1, Functor, Tup>::call(
                    std::forward<Functor>(f),
                    std::forward<Tup>(tup),
                    std::get<Index-1>(tup),
                    std::forward<Ts>(args)...))
        {
            // recurse
            return Expander<Index-1, Functor, Tup>::call(
                    std::forward<Functor>(f),
                    std::forward<Tup>(tup),
                    std::get<Index-1>(tup), // pull out one element
                    std::forward<Ts>(args)...); // everything already expanded
        }
    };

    template <typename Functor, typename Tup>
    struct Expander<0, Functor, Tup> {
        template <typename... Ts>
        static auto call(Functor&& f, Tup&&, Ts&&... args)
            -> decltype(f(std::forward<Ts>(args)...))
        {
            static_assert(
                std::tuple_size<
                    typename std::remove_reference<Tup>::type>::value
                    == sizeof...(Ts),
                "tuple has not been fully expanded");
            return f(std::forward<Ts>(args)...); // the actual call
        }
    };

    template <typename Functor, typename Tup>
    auto call_with_tuple(Functor&& f, Tup&& tup)
        -> decltype(Expander<std::tuple_size<
                    typename std::remove_reference<Tup>::type>::value,
                    Functor, Tup>::call(
                        std::forward<Functor>(f),
                        std::forward<Tup>(tup)))
    {
        return Expander<std::tuple_size<
            typename std::remove_reference<Tup>::type>::value,
            Functor, Tup>::call(
                std::forward<Functor>(f),
                std::forward<Tup>(tup));
    }

    } // end detail

    //Forward declarations of IMap and imap
    template <typename MapFunc, typename... Containers>
    class IMap;

    template <typename MapFunc, typename... Containers>
    IMap<MapFunc, Containers...> imap(MapFunc, Containers&&...);

    template <typename MapFunc, typename... Containers>
    class IMap {
        // The imap function is the only thing allowed to create a IMap
        friend IMap imap<MapFunc, Containers...>(MapFunc, Containers&& ...);

        using ZippedType = decltype(zip(std::declval<Containers>()...));
        using ZippedIterType = iterator_type<ZippedType>;
        private:
            MapFunc map_func;
            ZippedType zipped;

            using IMapIterDeref = decltype(detail::call_with_tuple(
                        map_func, *std::begin(zipped)));

            // Value constructor for use only in the imap function
            IMap(MapFunc map_func, Containers&& ... containers) :
                map_func(map_func),
                zipped(zip(std::forward<Containers>(containers)...))
            { }

        public:
            class Iterator
                : public std::iterator<std::input_iterator_tag,
                    typename std::remove_reference<IMapIterDeref>::type >
            {
                private:
                    MapFunc map_func;
                    ZippedIterType zipiter;

                public:
                    Iterator(MapFunc map_func, ZippedIterType zipiter) :
                        map_func(map_func),
                        zipiter(zipiter)
                    { }

                    IMapIterDeref operator*() {
                        return detail::call_with_tuple(
                                this->map_func, *(this->zipiter));
                    }

                    Iterator& operator++() {
                        ++this->zipiter;
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->zipiter != other.zipiter;
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() {
                return {this->map_func, this->zipped.begin()};
            }

            Iterator end() {
                return {this->map_func, this->zipped.end()};
            }

    };

    // Helper function to instantiate a IMap
    template <typename MapFunc, typename... Containers>
    IMap<MapFunc, Containers...> imap(
            MapFunc map_func, Containers&& ... containers) {
        return {map_func, std::forward<Containers>(containers)...};
    }

}

#endif // #ifndef ITER_IMAP_H_
<|endoftext|>


<commit_before>
#include "../Flare.h"
#include "FlareSpacecraft.h"
#include "../Game/FlareAsteroid.h"
#include "../Game/FlareGame.h"
#include "../Player/FlarePlayerController.h"
#include "FlareWeapon.h"
#include "FlareBombComponent.h"
#include "FlareBomb.h"

#define LOCTEXT_NAMESPACE "FlareBomb"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

AFlareBomb::AFlareBomb(const class FObjectInitializer& PCIP) : Super(PCIP)
{
	// Mesh data
	BombComp = PCIP.CreateDefaultSubobject<UFlareBombComponent>(this, TEXT("Root"));
	BombComp->bTraceComplexOnMove = true;
	BombComp->LDMaxDrawDistance = 100000; // 1km*/
	BombComp->SetSimulatePhysics(true);
	BombComp->SetLinearDamping(0);
	BombComp->SetAngularDamping(0);
	RootComponent = BombComp;

	// Settings
	SetActorEnableCollision(false);
	PrimaryActorTick.bCanEverTick = true;
	Paused = false;
}

/*----------------------------------------------------
	Gameplay
----------------------------------------------------*/

void AFlareBomb::PostInitializeComponents()
{
	Super::PostInitializeComponents();
}

void AFlareBomb::Initialize(const FFlareBombSave* Data, UFlareWeapon* Weapon)
{
	ParentWeapon = Weapon;
	WeaponDescription = Weapon->GetDescription();

	// Get the power from description
	if (WeaponDescription)
	{
		FFlareSpacecraftComponentSave ComponentData;
		ComponentData.ComponentIdentifier = WeaponDescription->Identifier;
		BombComp->Initialize(&ComponentData, Weapon->GetSpacecraft()->GetParent()->GetCompany(), Weapon->GetSpacecraft(), false);

		DamageSound = WeaponDescription->WeaponCharacteristics.DamageSound;

		ExplosionEffectTemplate = WeaponDescription->WeaponCharacteristics.ExplosionEffect;
		ExplosionEffectScale = WeaponDescription->WeaponCharacteristics.ExplosionEffectScale;
		ExplosionEffectMaterial = WeaponDescription->WeaponCharacteristics.GunCharacteristics.ExplosionMaterial;

	}

	SetActorScale3D(ParentWeapon->GetSpacecraft()->GetActorScale3D());

	if (Data)
	{
		BombData = *Data;
	}
	else
	{
		BombData.Activated = false;
		BombData.Dropped = false;
		BombData.LifeTime = 0;
		BombData.DropParentDistance = 0;
		BombData.Identifier = Weapon->GetSpacecraft()->GetGame()->GenerateIdentifier(TEXT("bomb"));
	}

	if (BombData.Activated)
	{
		SetActorEnableCollision(true);
	}

	if (BombData.AttachTarget != NAME_None)
	{
		AFlareSpacecraft* AttachTarget = ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->FindSpacecraft(BombData.AttachTarget);
		AttachBomb(AttachTarget);
	}
}

void AFlareBomb::OnLaunched()
{
	FLOG("AFlareBomb::OnLaunched");

	CombatLog::BombDropped(this);

	DetachRootComponentFromParent(true);
	ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->RegisterBomb(this);

	// Spin to stabilize
	FVector FrontVector = BombComp->ComponentToWorld.TransformVector(FVector(1, 0, 0));
	BombComp->SetPhysicsAngularVelocity(FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropAngularVelocity);
	BombComp->SetPhysicsLinearVelocity(ParentWeapon->GetSpacecraft()->Airframe->GetPhysicsLinearVelocity() + FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropLinearVelocity * 100);

	BombData.DropParentDistance = GetParentDistance();
	BombData.Dropped = true;
	BombData.LifeTime = 0;
}

void AFlareBomb::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	// Activate after few centimeters
	if (BombData.Dropped && !BombData.Activated)
	{
		if (GetParentDistance() > BombData.DropParentDistance + WeaponDescription->WeaponCharacteristics.BombCharacteristics.ActivationDistance * 100)
		{
			SetActorEnableCollision(true);
			BombData.Activated = true;
		}
	}

	if (BombData.Dropped && BombData.Activated)
	{
		BombData.LifeTime += DeltaSeconds;
		LastTickRotation = GetActorRotation();
	}

	// Auto-destroy
	AFlarePlayerController* PC = Cast<AFlarePlayerController>(GetWorld()->GetFirstPlayerController());
	if (PC)
	{
		AFlareSpacecraft* PlayerShip = PC->GetShipPawn();
		if (PlayerShip)
		{
			// 5 km and 30s auto-destroy
			float Distance = (GetActorLocation() - PlayerShip->GetActorLocation()).Size();
			if (Distance > 500000 && BombData.LifeTime > 30)
			{
				OnBombDetonated(NULL, NULL, FVector(), FVector());
			}

			// Parent removed destroy
			if (!ParentWeapon || !ParentWeapon->IsValidLowLevel() || !ParentWeapon->GetSpacecraft()->IsValidLowLevel())
			{
				OnBombDetonated(NULL, NULL, FVector(), FVector());
			}
		}
	}

}

void AFlareBomb::NotifyHit(class UPrimitiveComponent* MyComp, class AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
	Super::ReceiveHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);

	AFlareBomb* BombCandidate = Cast<AFlareBomb>(Other);
	AFlareAsteroid* Asteroid = Cast<AFlareAsteroid>(Other);
	AFlareSpacecraft* Spacecraft = Cast<AFlareSpacecraft>(Other);
	UFlareSpacecraftComponent* ShipComponent = Cast<UFlareSpacecraftComponent>(OtherComp);

	// Forget uninteresting hits
	if (!Other || !OtherComp || !ParentWeapon || Other == ParentWeapon->GetSpacecraft() || BombCandidate || (BombData.AttachTarget != NAME_None))
	{
		FLOG("AFlareBomb::NotifyHit : invalid hit");
		return;
	}

	// Spawn penetration effect
	if (ExplosionEffectTemplate && !(Spacecraft && Spacecraft->IsInImmersiveMode()))
	{
		UParticleSystemComponent* PSC = UGameplayStatics::SpawnEmitterAttached(
			ExplosionEffectTemplate,
			OtherComp,
			NAME_None,
			HitLocation,
			HitNormal.Rotation(),
			EAttachLocation::KeepWorldPosition,
			true);
		if (PSC)
		{
			PSC->SetWorldScale3D(ExplosionEffectScale * FVector(1, 1, 1));
		}
	}

	// Physics impulse
	float ImpulseForce = 1000 * WeaponDescription->WeaponCharacteristics.ExplosionPower * WeaponDescription->WeaponCharacteristics.AmmoDamageRadius;
	FVector ImpulseDirection = (HitLocation - GetActorLocation()).GetUnsafeNormal();

	// Process damage
	if (Spacecraft)
	{
		Spacecraft->Airframe->AddImpulseAtLocation(ImpulseForce * ImpulseDirection, HitLocation);
		OnSpacecraftHit(Spacecraft, ShipComponent, HitLocation, NormalImpulse);
	}
	else if (Asteroid)
	{
		Asteroid->GetAsteroidComponent()->AddImpulseAtLocation(ImpulseForce * ImpulseDirection, HitLocation);
	}

	// Spawn impact decal
	if (ShipComponent && ExplosionEffectMaterial)
	{
		// Spawn
		UDecalComponent* Decal = UGameplayStatics::SpawnDecalAttached(
			ExplosionEffectMaterial,
			FMath::FRandRange(50, 150) * FVector(1, 1, 1),
			ShipComponent,
			NAME_None,
			HitLocation,
			HitNormal.Rotation(),
			EAttachLocation::KeepWorldPosition,
			120);

		// Instanciate and configure the decal material
		UMaterialInterface* DecalMaterial = Decal->GetMaterial(0);
		UMaterialInstanceDynamic* DecalMaterialInst = UMaterialInstanceDynamic::Create(DecalMaterial, GetWorld());
		if (DecalMaterialInst)
		{
			DecalMaterialInst->SetScalarParameterValue("RandomParameter", FMath::FRandRange(1, 0));
			DecalMaterialInst->SetScalarParameterValue("RandomParameter2", FMath::FRandRange(1, 0));
			DecalMaterialInst->SetScalarParameterValue("IsShipHull", ShipComponent->IsA(UFlareSpacecraftComponent::StaticClass()));
			Decal->SetMaterial(0, DecalMaterialInst);
		}
	}

	// Bomb has done its job, good job bomb
	OnBombDetonated(Spacecraft, ShipComponent, HitLocation, ImpulseDirection);
}

void AFlareBomb::OnSpacecraftHit(AFlareSpacecraft* HitSpacecraft, UFlareSpacecraftComponent* HitComponent, FVector HitLocation, FVector InertialNormal)
{
	UFlareCompany* OwnerCompany = ParentWeapon->GetSpacecraft()->GetCompany();
	AFlarePlayerController* PC = Cast<AFlarePlayerController>(GetWorld()->GetFirstPlayerController());

	// Apply damage
	HitSpacecraft->GetDamageSystem()->ApplyDamage(WeaponDescription->WeaponCharacteristics.ExplosionPower,
		WeaponDescription->WeaponCharacteristics.AmmoDamageRadius,
		HitLocation,
		SpacecraftHelper::GetWeaponDamageType(WeaponDescription->WeaponCharacteristics.DamageType),
		ParentWeapon->GetSpacecraft()->GetParent());

	// Play sound
	if (HitSpacecraft->IsPlayerShip())
	{
		HitSpacecraft->GetPC()->PlayLocalizedSound(DamageSound, HitLocation);
	}

	// Ship salvage
	if (!HitSpacecraft->IsStation() &&
		((WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::LightSalvage && HitSpacecraft->GetDescription()->Size == EFlarePartSize::S)
	 || (WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::HeavySalvage && HitSpacecraft->GetDescription()->Size == EFlarePartSize::L)))
	{
		FLOGV("AFlareBomb::OnSpacecraftHit : salvaging %s for %s", *HitSpacecraft->GetImmatriculation().ToString(), *OwnerCompany->GetCompanyName().ToString());
		HitSpacecraft->GetParent()->SetHarpooned(OwnerCompany);

		if (OwnerCompany == PC->GetCompany())
		{
			FFlareMenuParameterData Data;
			Data.Spacecraft = HitSpacecraft->GetParent();
			PC->Notify(LOCTEXT("HeavyShipHarpooned", "Ship harpooned !"),
				FText::Format(LOCTEXT("HeavyShipHarpoonedFormat", "If it is uncontrollable, you will retrieve {0} on the next day, if you are still in this sector."),
					FText::FromString(HitSpacecraft->GetImmatriculation().ToString())),
				FName("ship-harpooned"),
				EFlareNotification::NT_Military,
				false,
				EFlareMenu::MENU_Ship,
				Data);
		}
	}
}

void AFlareBomb::OnBombDetonated(AFlareSpacecraft* HitSpacecraft, UFlareSpacecraftComponent* HitComponent, FVector HitLocation, FVector InertialNormal)
{
	// Attach to the hull if it's a salvage harpoon
	if (HitSpacecraft && (
			(WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::LightSalvage)
	 || (WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::HeavySalvage)))
	{
		if (HitSpacecraft && !HitSpacecraft->IsStation() && HitComponent && WeaponDescription &&
		   ((WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::LightSalvage && HitSpacecraft->GetDescription()->Size == EFlarePartSize::S)
		 || (WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::HeavySalvage && HitSpacecraft->GetDescription()->Size == EFlarePartSize::L)))
		{
			SetActorLocation(HitLocation);
			FLOGV("Attach actor rotation %s", *GetActorRotation().ToString());
			SetActorRotation(LastTickRotation);
			AttachBomb(HitSpacecraft);
		}
	}
	else
	{
		if (ParentWeapon)
		{
			ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->UnregisterBomb(this);
		}
		CombatLog::BombDestroyed(GetIdentifier());
		Destroy();
	}
}

void AFlareBomb::AttachBomb(AFlareSpacecraft* HitSpacecraft)
{
	if(HitSpacecraft)
	{
		AttachToActor(HitSpacecraft, FAttachmentTransformRules(EAttachmentRule::KeepWorld, true), NAME_None);
		BombData.AttachTarget =  HitSpacecraft->GetImmatriculation();
	}
	else
	{
		BombData.AttachTarget =  NAME_None;
	}
}

FFlareBombSave* AFlareBomb::Save()
{
	// Physical data
	BombData.Location = GetActorLocation();
	BombData.Rotation = GetActorRotation();
	if (!Paused)
	{
		BombData.LinearVelocity = BombComp->GetPhysicsLinearVelocity();
		BombData.AngularVelocity = BombComp->GetPhysicsAngularVelocity();
	}

	// TODO Investigate on NULL ParentWeapon
	if (ParentWeapon)
	{
		BombData.ParentSpacecraft = ParentWeapon->GetSpacecraft()->GetImmatriculation();
		BombData.WeaponSlotIdentifier = ParentWeapon->SlotIdentifier;
	}

	return &BombData;
}

void AFlareBomb::SetPause(bool Pause)
{
	if (Paused == Pause)
	{
		return;
	}

	// On pause, save the state
	if (Pause)
	{
		Save();
	}

	// Toggle pause
	Paused = Pause;
	SetActorHiddenInGame(Pause);
	BombComp->SetSimulatePhysics(!Pause);
	CustomTimeDilation = (Pause ? 0.f : 1.0);

	// On unpause, restore physics
	if (!Pause)
	{
		BombComp->SetPhysicsLinearVelocity(BombData.LinearVelocity);
		BombComp->SetPhysicsAngularVelocity(BombData.AngularVelocity);
		if (!BombData.Dropped && ParentWeapon)
		{
			AttachToActor(ParentWeapon->GetSpacecraft(), FAttachmentTransformRules(EAttachmentRule::KeepWorld, true), NAME_None);
		}
	}
}

float AFlareBomb::GetParentDistance() const
{
	return (ParentWeapon->GetComponentLocation() - GetActorLocation()).Size();
}

#undef LOCTEXT_NAMESPACE
<commit_msg>Fixed bomb collision settings<commit_after>
#include "../Flare.h"
#include "FlareSpacecraft.h"
#include "../Game/FlareAsteroid.h"
#include "../Game/FlareGame.h"
#include "../Player/FlarePlayerController.h"
#include "FlareWeapon.h"
#include "FlareBombComponent.h"
#include "FlareBomb.h"

#define LOCTEXT_NAMESPACE "FlareBomb"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

AFlareBomb::AFlareBomb(const class FObjectInitializer& PCIP) : Super(PCIP)
{
	// Mesh data
	BombComp = PCIP.CreateDefaultSubobject<UFlareBombComponent>(this, TEXT("Root"));
	BombComp->bTraceComplexOnMove = true;
	BombComp->LDMaxDrawDistance = 100000; // 1km*/
	BombComp->SetSimulatePhysics(true);
	BombComp->SetLinearDamping(0);
	BombComp->SetAngularDamping(0);
	RootComponent = BombComp;

	// Settings
	PrimaryActorTick.bCanEverTick = true;
	Paused = false;
}

/*----------------------------------------------------
	Gameplay
----------------------------------------------------*/

void AFlareBomb::PostInitializeComponents()
{
	Super::PostInitializeComponents();
}

void AFlareBomb::Initialize(const FFlareBombSave* Data, UFlareWeapon* Weapon)
{
	ParentWeapon = Weapon;
	WeaponDescription = Weapon->GetDescription();

	// Get the power from description
	if (WeaponDescription)
	{
		FFlareSpacecraftComponentSave ComponentData;
		ComponentData.ComponentIdentifier = WeaponDescription->Identifier;
		BombComp->Initialize(&ComponentData, Weapon->GetSpacecraft()->GetParent()->GetCompany(), Weapon->GetSpacecraft(), false);

		DamageSound = WeaponDescription->WeaponCharacteristics.DamageSound;

		ExplosionEffectTemplate = WeaponDescription->WeaponCharacteristics.ExplosionEffect;
		ExplosionEffectScale = WeaponDescription->WeaponCharacteristics.ExplosionEffectScale;
		ExplosionEffectMaterial = WeaponDescription->WeaponCharacteristics.GunCharacteristics.ExplosionMaterial;

	}

	SetActorScale3D(ParentWeapon->GetSpacecraft()->GetActorScale3D());

	if (Data)
	{
		BombData = *Data;
	}
	else
	{
		BombData.Activated = false;
		BombData.Dropped = false;
		BombData.LifeTime = 0;
		BombData.DropParentDistance = 0;
		BombData.Identifier = Weapon->GetSpacecraft()->GetGame()->GenerateIdentifier(TEXT("bomb"));
	}

	SetActorEnableCollision(BombData.Activated);

	if (BombData.AttachTarget != NAME_None)
	{
		AFlareSpacecraft* AttachTarget = ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->FindSpacecraft(BombData.AttachTarget);
		AttachBomb(AttachTarget);
	}
}

void AFlareBomb::OnLaunched()
{
	FLOG("AFlareBomb::OnLaunched");

	CombatLog::BombDropped(this);

	DetachRootComponentFromParent(true);
	ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->RegisterBomb(this);

	// Spin to stabilize
	FVector FrontVector = BombComp->ComponentToWorld.TransformVector(FVector(1, 0, 0));
	BombComp->SetPhysicsAngularVelocity(FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropAngularVelocity);
	BombComp->SetPhysicsLinearVelocity(ParentWeapon->GetSpacecraft()->Airframe->GetPhysicsLinearVelocity() + FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropLinearVelocity * 100);

	BombData.DropParentDistance = GetParentDistance();
	BombData.Dropped = true;
	BombData.LifeTime = 0;
}

void AFlareBomb::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	// Activate after few centimeters
	if (BombData.Dropped && !BombData.Activated)
	{
		if (GetParentDistance() > BombData.DropParentDistance + WeaponDescription->WeaponCharacteristics.BombCharacteristics.ActivationDistance * 100)
		{
			SetActorEnableCollision(true);
			BombData.Activated = true;
		}
	}

	if (BombData.Dropped && BombData.Activated)
	{
		BombData.LifeTime += DeltaSeconds;
		LastTickRotation = GetActorRotation();
	}

	// Auto-destroy
	AFlarePlayerController* PC = Cast<AFlarePlayerController>(GetWorld()->GetFirstPlayerController());
	if (PC)
	{
		AFlareSpacecraft* PlayerShip = PC->GetShipPawn();
		if (PlayerShip)
		{
			// 5 km and 30s auto-destroy
			float Distance = (GetActorLocation() - PlayerShip->GetActorLocation()).Size();
			if (Distance > 500000 && BombData.LifeTime > 30)
			{
				OnBombDetonated(NULL, NULL, FVector(), FVector());
			}

			// Parent removed destroy
			if (!ParentWeapon || !ParentWeapon->IsValidLowLevel() || !ParentWeapon->GetSpacecraft()->IsValidLowLevel())
			{
				OnBombDetonated(NULL, NULL, FVector(), FVector());
			}
		}
	}

}

void AFlareBomb::NotifyHit(class UPrimitiveComponent* MyComp, class AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
	Super::ReceiveHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);

	AFlareBomb* BombCandidate = Cast<AFlareBomb>(Other);
	AFlareAsteroid* Asteroid = Cast<AFlareAsteroid>(Other);
	AFlareSpacecraft* Spacecraft = Cast<AFlareSpacecraft>(Other);
	UFlareSpacecraftComponent* ShipComponent = Cast<UFlareSpacecraftComponent>(OtherComp);

	// Forget uninteresting hits
	if (!Other || !OtherComp || !ParentWeapon || Other == ParentWeapon->GetSpacecraft() || BombCandidate || (BombData.AttachTarget != NAME_None))
	{
		FLOG("AFlareBomb::NotifyHit : invalid hit");
		return;
	}

	// Spawn penetration effect
	if (ExplosionEffectTemplate && !(Spacecraft && Spacecraft->IsInImmersiveMode()))
	{
		UParticleSystemComponent* PSC = UGameplayStatics::SpawnEmitterAttached(
			ExplosionEffectTemplate,
			OtherComp,
			NAME_None,
			HitLocation,
			HitNormal.Rotation(),
			EAttachLocation::KeepWorldPosition,
			true);
		if (PSC)
		{
			PSC->SetWorldScale3D(ExplosionEffectScale * FVector(1, 1, 1));
		}
	}

	// Physics impulse
	float ImpulseForce = 1000 * WeaponDescription->WeaponCharacteristics.ExplosionPower * WeaponDescription->WeaponCharacteristics.AmmoDamageRadius;
	FVector ImpulseDirection = (HitLocation - GetActorLocation()).GetUnsafeNormal();

	// Process damage
	if (Spacecraft)
	{
		Spacecraft->Airframe->AddImpulseAtLocation(ImpulseForce * ImpulseDirection, HitLocation);
		OnSpacecraftHit(Spacecraft, ShipComponent, HitLocation, NormalImpulse);
	}
	else if (Asteroid)
	{
		Asteroid->GetAsteroidComponent()->AddImpulseAtLocation(ImpulseForce * ImpulseDirection, HitLocation);
	}

	// Spawn impact decal
	if (ShipComponent && ExplosionEffectMaterial)
	{
		// Spawn
		UDecalComponent* Decal = UGameplayStatics::SpawnDecalAttached(
			ExplosionEffectMaterial,
			FMath::FRandRange(50, 150) * FVector(1, 1, 1),
			ShipComponent,
			NAME_None,
			HitLocation,
			HitNormal.Rotation(),
			EAttachLocation::KeepWorldPosition,
			120);

		// Instanciate and configure the decal material
		UMaterialInterface* DecalMaterial = Decal->GetMaterial(0);
		UMaterialInstanceDynamic* DecalMaterialInst = UMaterialInstanceDynamic::Create(DecalMaterial, GetWorld());
		if (DecalMaterialInst)
		{
			DecalMaterialInst->SetScalarParameterValue("RandomParameter", FMath::FRandRange(1, 0));
			DecalMaterialInst->SetScalarParameterValue("RandomParameter2", FMath::FRandRange(1, 0));
			DecalMaterialInst->SetScalarParameterValue("IsShipHull", ShipComponent->IsA(UFlareSpacecraftComponent::StaticClass()));
			Decal->SetMaterial(0, DecalMaterialInst);
		}
	}

	// Bomb has done its job, good job bomb
	OnBombDetonated(Spacecraft, ShipComponent, HitLocation, ImpulseDirection);
}

void AFlareBomb::OnSpacecraftHit(AFlareSpacecraft* HitSpacecraft, UFlareSpacecraftComponent* HitComponent, FVector HitLocation, FVector InertialNormal)
{
	UFlareCompany* OwnerCompany = ParentWeapon->GetSpacecraft()->GetCompany();
	AFlarePlayerController* PC = Cast<AFlarePlayerController>(GetWorld()->GetFirstPlayerController());

	// Apply damage
	HitSpacecraft->GetDamageSystem()->ApplyDamage(WeaponDescription->WeaponCharacteristics.ExplosionPower,
		WeaponDescription->WeaponCharacteristics.AmmoDamageRadius,
		HitLocation,
		SpacecraftHelper::GetWeaponDamageType(WeaponDescription->WeaponCharacteristics.DamageType),
		ParentWeapon->GetSpacecraft()->GetParent());

	// Play sound
	if (HitSpacecraft->IsPlayerShip())
	{
		HitSpacecraft->GetPC()->PlayLocalizedSound(DamageSound, HitLocation);
	}

	// Ship salvage
	if (!HitSpacecraft->IsStation() &&
		((WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::LightSalvage && HitSpacecraft->GetDescription()->Size == EFlarePartSize::S)
	 || (WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::HeavySalvage && HitSpacecraft->GetDescription()->Size == EFlarePartSize::L)))
	{
		FLOGV("AFlareBomb::OnSpacecraftHit : salvaging %s for %s", *HitSpacecraft->GetImmatriculation().ToString(), *OwnerCompany->GetCompanyName().ToString());
		HitSpacecraft->GetParent()->SetHarpooned(OwnerCompany);

		if (OwnerCompany == PC->GetCompany())
		{
			FFlareMenuParameterData Data;
			Data.Spacecraft = HitSpacecraft->GetParent();
			PC->Notify(LOCTEXT("HeavyShipHarpooned", "Ship harpooned !"),
				FText::Format(LOCTEXT("HeavyShipHarpoonedFormat", "If it is uncontrollable, you will retrieve {0} on the next day, if you are still in this sector."),
					FText::FromString(HitSpacecraft->GetImmatriculation().ToString())),
				FName("ship-harpooned"),
				EFlareNotification::NT_Military,
				false,
				EFlareMenu::MENU_Ship,
				Data);
		}
	}
}

void AFlareBomb::OnBombDetonated(AFlareSpacecraft* HitSpacecraft, UFlareSpacecraftComponent* HitComponent, FVector HitLocation, FVector InertialNormal)
{
	// Attach to the hull if it's a salvage harpoon
	if (HitSpacecraft && (
			(WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::LightSalvage)
	 || (WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::HeavySalvage)))
	{
		if (HitSpacecraft && !HitSpacecraft->IsStation() && HitComponent && WeaponDescription &&
		   ((WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::LightSalvage && HitSpacecraft->GetDescription()->Size == EFlarePartSize::S)
		 || (WeaponDescription->WeaponCharacteristics.DamageType == EFlareShellDamageType::HeavySalvage && HitSpacecraft->GetDescription()->Size == EFlarePartSize::L)))
		{
			SetActorLocation(HitLocation);
			FLOGV("Attach actor rotation %s", *GetActorRotation().ToString());
			SetActorRotation(LastTickRotation);
			AttachBomb(HitSpacecraft);
		}
	}
	else
	{
		if (ParentWeapon)
		{
			ParentWeapon->GetSpacecraft()->GetGame()->GetActiveSector()->UnregisterBomb(this);
		}
		CombatLog::BombDestroyed(GetIdentifier());
		Destroy();
	}
}

void AFlareBomb::AttachBomb(AFlareSpacecraft* HitSpacecraft)
{
	if(HitSpacecraft)
	{
		AttachToActor(HitSpacecraft, FAttachmentTransformRules(EAttachmentRule::KeepWorld, true), NAME_None);
		BombData.AttachTarget =  HitSpacecraft->GetImmatriculation();
	}
	else
	{
		BombData.AttachTarget =  NAME_None;
	}
}

FFlareBombSave* AFlareBomb::Save()
{
	// Physical data
	BombData.Location = GetActorLocation();
	BombData.Rotation = GetActorRotation();
	if (!Paused)
	{
		BombData.LinearVelocity = BombComp->GetPhysicsLinearVelocity();
		BombData.AngularVelocity = BombComp->GetPhysicsAngularVelocity();
	}

	// TODO Investigate on NULL ParentWeapon
	if (ParentWeapon)
	{
		BombData.ParentSpacecraft = ParentWeapon->GetSpacecraft()->GetImmatriculation();
		BombData.WeaponSlotIdentifier = ParentWeapon->SlotIdentifier;
	}

	return &BombData;
}

void AFlareBomb::SetPause(bool Pause)
{
	if (Paused == Pause)
	{
		return;
	}

	// On pause, save the state
	if (Pause)
	{
		Save();
	}

	// Toggle pause
	Paused = Pause;
	SetActorHiddenInGame(Pause);
	BombComp->SetSimulatePhysics(!Pause);
	CustomTimeDilation = (Pause ? 0.f : 1.0);

	// On unpause, restore physics
	if (!Pause)
	{
		BombComp->SetPhysicsLinearVelocity(BombData.LinearVelocity);
		BombComp->SetPhysicsAngularVelocity(BombData.AngularVelocity);
		if (!BombData.Dropped && ParentWeapon)
		{
			AttachToActor(ParentWeapon->GetSpacecraft(), FAttachmentTransformRules(EAttachmentRule::KeepWorld, true), NAME_None);
		}
	}
}

float AFlareBomb::GetParentDistance() const
{
	return (ParentWeapon->GetComponentLocation() - GetActorLocation()).Size();
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: generictoolboxcontroller.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2004-09-09 17:13:40 $
 *
 *  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 __SVTOOLS_GENERICTOOLBOXCONTROLLER_HXX_
#include "generictoolboxcontroller.hxx"
#endif

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
#include <com/sun/star/util/XURLTransformer.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDER_HPP_
#include <com/sun/star/frame/XDispatchProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_STATUS_ITEMSTATUS_HPP_
#include <com/sun/star/frame/status/ItemStatus.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_STATUS_ITEMSTATE_HPP_
#include <com/sun/star/frame/status/ItemState.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _VOS_MUTEX_HXX_
#include <vos/mutex.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::frame::status;
using namespace ::com::sun::star::util;

namespace svt
{

struct ExecuteInfo
{
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >     xDispatch;
    ::com::sun::star::util::URL                                                aTargetURL;
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >  aArgs;
};

GenericToolboxController::GenericToolboxController( const Reference< XMultiServiceFactory >& rServiceManager,
                                                    const Reference< XFrame >&               rFrame,
                                                    ToolBox*                                 pToolbox,
                                                    USHORT                                   nID,
                                                    const OUString&                          aCommand ) :
    svt::ToolboxController( rServiceManager, rFrame, aCommand )
    ,   m_pToolbox( pToolbox )
    ,   m_nID( nID )
{
    // Initialization is done through ctor
    m_bInitialized = sal_True;

    // insert main command to our listener map
    if ( m_aCommandURL.getLength() )
        m_aListenerMap.insert( URLToDispatchMap::value_type( aCommand, Reference< XDispatch >() ));
}

GenericToolboxController::~GenericToolboxController()
{
}

void SAL_CALL GenericToolboxController::dispose()
throw ( RuntimeException )
{
    vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

    svt::ToolboxController::dispose();

    m_pToolbox = 0;
    m_nID = 0;
}

void SAL_CALL GenericToolboxController::execute( sal_Int16 KeyModifier )
throw ( RuntimeException )
{
    Reference< XDispatch >       xDispatch;
    Reference< XURLTransformer > xURLTransformer;
    OUString                     aCommandURL;

    {
        vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

        if ( m_bDisposed )
            throw DisposedException();

        if ( m_bInitialized &&
             m_xFrame.is() &&
             m_xServiceManager.is() &&
             m_aCommandURL.getLength() )
        {
            xURLTransformer = Reference< XURLTransformer >( m_xServiceManager->createInstance(
                                                                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
                                                            UNO_QUERY );

            aCommandURL = m_aCommandURL;
            URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL );
            if ( pIter != m_aListenerMap.end() )
                xDispatch = pIter->second;
        }
    }

    if ( xDispatch.is() && xURLTransformer.is() )
    {
        com::sun::star::util::URL aTargetURL;
        Sequence<PropertyValue>   aArgs;

        aTargetURL.Complete = aCommandURL;
        xURLTransformer->parseStrict( aTargetURL );

        // Execute dispatch asynchronously
        ExecuteInfo* pExecuteInfo = new ExecuteInfo;
        pExecuteInfo->xDispatch     = xDispatch;
        pExecuteInfo->aTargetURL    = aTargetURL;
        pExecuteInfo->aArgs         = aArgs;
        Application::PostUserEvent( STATIC_LINK(0, GenericToolboxController , ExecuteHdl_Impl), pExecuteInfo );
    }
}

void GenericToolboxController::statusChanged( const FeatureStateEvent& Event )
throw ( RuntimeException )
{
    vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

    if ( m_bDisposed )
        return;

    if ( m_pToolbox )
    {
        m_pToolbox->EnableItem( m_nID, Event.IsEnabled );

        USHORT nItemBits = m_pToolbox->GetItemBits( m_nID );
        nItemBits &= ~TIB_CHECKABLE;
        TriState eTri = STATE_NOCHECK;

        sal_Bool        bValue;
        rtl::OUString   aStrValue;
        ItemStatus      aItemState;

        if ( Event.State >>= bValue )
        {
            // Boolean, treat it as checked/unchecked
            m_pToolbox->SetItemBits( m_nID, nItemBits );
            m_pToolbox->CheckItem( m_nID, bValue );
            if ( bValue )
                eTri = STATE_CHECK;
            nItemBits |= TIB_CHECKABLE;
        }
        else if ( Event.State >>= aStrValue )
        {
            m_pToolbox->SetItemText( m_nID, aStrValue );
        }
        else if ( Event.State >>= aItemState )
        {
            eTri = STATE_DONTKNOW;
            nItemBits |= TIB_CHECKABLE;
        }

        m_pToolbox->SetItemState( m_nID, eTri );
        m_pToolbox->SetItemBits( m_nID, nItemBits );
    }
}

IMPL_STATIC_LINK( GenericToolboxController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
{
   try
   {
       // Asynchronous execution as this can lead to our own destruction!
       // Framework can recycle our current frame and the layout manager disposes all user interface
       // elements if a component gets detached from its frame!
       pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
   }
   catch ( Exception& )
   {
   }
   delete pExecuteInfo;
   return 0;
}

} // namespace
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.386); FILE MERGED 2005/09/05 14:54:24 rt 1.2.386.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: generictoolboxcontroller.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 16:53:38 $
 *
 *  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 __SVTOOLS_GENERICTOOLBOXCONTROLLER_HXX_
#include "generictoolboxcontroller.hxx"
#endif

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
#include <com/sun/star/util/XURLTransformer.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDER_HPP_
#include <com/sun/star/frame/XDispatchProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_STATUS_ITEMSTATUS_HPP_
#include <com/sun/star/frame/status/ItemStatus.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_STATUS_ITEMSTATE_HPP_
#include <com/sun/star/frame/status/ItemState.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _VOS_MUTEX_HXX_
#include <vos/mutex.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::frame::status;
using namespace ::com::sun::star::util;

namespace svt
{

struct ExecuteInfo
{
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >     xDispatch;
    ::com::sun::star::util::URL                                                aTargetURL;
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >  aArgs;
};

GenericToolboxController::GenericToolboxController( const Reference< XMultiServiceFactory >& rServiceManager,
                                                    const Reference< XFrame >&               rFrame,
                                                    ToolBox*                                 pToolbox,
                                                    USHORT                                   nID,
                                                    const OUString&                          aCommand ) :
    svt::ToolboxController( rServiceManager, rFrame, aCommand )
    ,   m_pToolbox( pToolbox )
    ,   m_nID( nID )
{
    // Initialization is done through ctor
    m_bInitialized = sal_True;

    // insert main command to our listener map
    if ( m_aCommandURL.getLength() )
        m_aListenerMap.insert( URLToDispatchMap::value_type( aCommand, Reference< XDispatch >() ));
}

GenericToolboxController::~GenericToolboxController()
{
}

void SAL_CALL GenericToolboxController::dispose()
throw ( RuntimeException )
{
    vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

    svt::ToolboxController::dispose();

    m_pToolbox = 0;
    m_nID = 0;
}

void SAL_CALL GenericToolboxController::execute( sal_Int16 KeyModifier )
throw ( RuntimeException )
{
    Reference< XDispatch >       xDispatch;
    Reference< XURLTransformer > xURLTransformer;
    OUString                     aCommandURL;

    {
        vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

        if ( m_bDisposed )
            throw DisposedException();

        if ( m_bInitialized &&
             m_xFrame.is() &&
             m_xServiceManager.is() &&
             m_aCommandURL.getLength() )
        {
            xURLTransformer = Reference< XURLTransformer >( m_xServiceManager->createInstance(
                                                                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
                                                            UNO_QUERY );

            aCommandURL = m_aCommandURL;
            URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL );
            if ( pIter != m_aListenerMap.end() )
                xDispatch = pIter->second;
        }
    }

    if ( xDispatch.is() && xURLTransformer.is() )
    {
        com::sun::star::util::URL aTargetURL;
        Sequence<PropertyValue>   aArgs;

        aTargetURL.Complete = aCommandURL;
        xURLTransformer->parseStrict( aTargetURL );

        // Execute dispatch asynchronously
        ExecuteInfo* pExecuteInfo = new ExecuteInfo;
        pExecuteInfo->xDispatch     = xDispatch;
        pExecuteInfo->aTargetURL    = aTargetURL;
        pExecuteInfo->aArgs         = aArgs;
        Application::PostUserEvent( STATIC_LINK(0, GenericToolboxController , ExecuteHdl_Impl), pExecuteInfo );
    }
}

void GenericToolboxController::statusChanged( const FeatureStateEvent& Event )
throw ( RuntimeException )
{
    vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );

    if ( m_bDisposed )
        return;

    if ( m_pToolbox )
    {
        m_pToolbox->EnableItem( m_nID, Event.IsEnabled );

        USHORT nItemBits = m_pToolbox->GetItemBits( m_nID );
        nItemBits &= ~TIB_CHECKABLE;
        TriState eTri = STATE_NOCHECK;

        sal_Bool        bValue;
        rtl::OUString   aStrValue;
        ItemStatus      aItemState;

        if ( Event.State >>= bValue )
        {
            // Boolean, treat it as checked/unchecked
            m_pToolbox->SetItemBits( m_nID, nItemBits );
            m_pToolbox->CheckItem( m_nID, bValue );
            if ( bValue )
                eTri = STATE_CHECK;
            nItemBits |= TIB_CHECKABLE;
        }
        else if ( Event.State >>= aStrValue )
        {
            m_pToolbox->SetItemText( m_nID, aStrValue );
        }
        else if ( Event.State >>= aItemState )
        {
            eTri = STATE_DONTKNOW;
            nItemBits |= TIB_CHECKABLE;
        }

        m_pToolbox->SetItemState( m_nID, eTri );
        m_pToolbox->SetItemBits( m_nID, nItemBits );
    }
}

IMPL_STATIC_LINK( GenericToolboxController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
{
   try
   {
       // Asynchronous execution as this can lead to our own destruction!
       // Framework can recycle our current frame and the layout manager disposes all user interface
       // elements if a component gets detached from its frame!
       pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
   }
   catch ( Exception& )
   {
   }
   delete pExecuteInfo;
   return 0;
}

} // namespace
<|endoftext|>


<commit_before>#include "staticservicebrowserview.h"
#include <QFile>
#include <QApplication>
#include <QTextStream>
#include <QAction>
#include <QMenu>

StaticServiceBrowserView::StaticServiceBrowserView(QWidget *parent)
    : QTreeView(parent)
{
    setSelectionBehavior(QAbstractItemView::SelectRows);

    m_model = new QStandardItemModel(this);
    initModelFromFile(":/services.conf");
    setModel(m_model);
    connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(handleActivated(QModelIndex)));

    for (int i = 0; i < m_model->columnCount(); i++)
        resizeColumnToContents(i);

    selectionModel()->select(m_model->index(0, 0), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
}

StaticServiceBrowserView::~StaticServiceBrowserView()
{
}

void StaticServiceBrowserView::initModelFromFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QFile::ReadOnly)) {
        qWarning("Failed to open static services file");
        return;
    }

    QStringList headerLabels;
    headerLabels << StaticServiceBrowserView::tr("Host Name")
                 << StaticServiceBrowserView::tr("IP")
                 << StaticServiceBrowserView::tr("Port");
    m_model->setHorizontalHeaderLabels(headerLabels);

    QTextStream stream(&file);
    while (!stream.atEnd()) {
        QString hostName;
        stream >> hostName;
        if (hostName.startsWith('#')) {
            stream.readLine();
            continue;
        }
        QString ip, port;
        stream >> ip >> port;

        QList<QStandardItem *> columns;
        columns.append(new QStandardItem);
        columns[0]->setText(hostName);
        columns[0]->setEditable(false);
        columns.append(new QStandardItem);
        columns[1]->setText(ip);
        columns[1]->setEditable(false);
        columns.append(new QStandardItem);
        columns[2]->setText(port);
        columns[2]->setEditable(false);

        addService(hostName, ip, port);
    }
}

void StaticServiceBrowserView::handleActivated(const QModelIndex &index)
{
    QStandardItem *item = m_model->invisibleRootItem();
    QString hostName = item->child(index.row(), 0)->text();
    Q_UNUSED(hostName);
    QString ip = item->child(index.row(), 1)->text();
    QString port = item->child(index.row(), 2)->text();

    emit serviceSelected(QHostAddress(ip), port.toInt());
}

void StaticServiceBrowserView::addService(const QString &hostName, const QString &ip, const QString &port)
{
    QList<QStandardItem *> columns;
    columns.append(new QStandardItem);
    columns[0]->setText(hostName);
    columns[0]->setEditable(false);
    columns.append(new QStandardItem);
    columns[1]->setText(ip);
    columns[1]->setEditable(false);
    columns.append(new QStandardItem);
    columns[2]->setText(port);
    columns[2]->setEditable(false);

    m_model->appendRow(columns);
}

void StaticServiceBrowserView::removeService()
{
    m_model->removeRow(currentIndex().row());
}
<commit_msg>remotecontrol: remove dead code<commit_after>#include "staticservicebrowserview.h"
#include <QFile>
#include <QApplication>
#include <QTextStream>
#include <QAction>
#include <QMenu>

StaticServiceBrowserView::StaticServiceBrowserView(QWidget *parent)
    : QTreeView(parent)
{
    setSelectionBehavior(QAbstractItemView::SelectRows);

    m_model = new QStandardItemModel(this);
    initModelFromFile(":/services.conf");
    setModel(m_model);
    connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(handleActivated(QModelIndex)));

    for (int i = 0; i < m_model->columnCount(); i++)
        resizeColumnToContents(i);

    selectionModel()->select(m_model->index(0, 0), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
}

StaticServiceBrowserView::~StaticServiceBrowserView()
{
}

void StaticServiceBrowserView::initModelFromFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QFile::ReadOnly)) {
        qWarning("Failed to open static services file");
        return;
    }

    QStringList headerLabels;
    headerLabels << StaticServiceBrowserView::tr("Host Name")
                 << StaticServiceBrowserView::tr("IP")
                 << StaticServiceBrowserView::tr("Port");
    m_model->setHorizontalHeaderLabels(headerLabels);

    QTextStream stream(&file);
    while (!stream.atEnd()) {
        QString hostName;
        stream >> hostName;
        if (hostName.startsWith('#')) {
            stream.readLine();
            continue;
        }
        QString ip, port;
        stream >> ip >> port;

        addService(hostName, ip, port);
    }
}

void StaticServiceBrowserView::handleActivated(const QModelIndex &index)
{
    QStandardItem *item = m_model->invisibleRootItem();
    QString hostName = item->child(index.row(), 0)->text();
    Q_UNUSED(hostName);
    QString ip = item->child(index.row(), 1)->text();
    QString port = item->child(index.row(), 2)->text();

    emit serviceSelected(QHostAddress(ip), port.toInt());
}

void StaticServiceBrowserView::addService(const QString &hostName, const QString &ip, const QString &port)
{
    QList<QStandardItem *> columns;
    columns.append(new QStandardItem);
    columns[0]->setText(hostName);
    columns[0]->setEditable(false);
    columns.append(new QStandardItem);
    columns[1]->setText(ip);
    columns[1]->setEditable(false);
    columns.append(new QStandardItem);
    columns[2]->setText(port);
    columns[2]->setEditable(false);

    m_model->appendRow(columns);
}

void StaticServiceBrowserView::removeService()
{
    m_model->removeRow(currentIndex().row());
}
<|endoftext|>


<commit_before>#include "Opaques.hpp"

void orogen_typekits::toIntermediate(TestOpaque::Point2D& intermediate, NotOrogenCompatible::Point2D const& real_type)
{
    intermediate.padding = 100;
    intermediate.x = real_type.x();
    intermediate.y = real_type.y();
}
void orogen_typekits::fromIntermediate(NotOrogenCompatible::Point2D& real_type, TestOpaque::Point2D const& intermediate)
{
    real_type.x() = intermediate.x;
    real_type.y() = intermediate.y;
}

std::vector<float> const& orogen_typekits::toIntermediate(boost::shared_ptr<std::vector<float> > const& real_type)
{
    return *real_type;
}
bool orogen_typekits::fromIntermediate(boost::shared_ptr<std::vector<float> >& real_type, std::vector<float>* intermediate)
{
    if (intermediate != real_type.get())
        real_type.reset( intermediate );
    return true; // we get the ownership on +intermediate+
}
<commit_msg>gen,test: update typekit_opaque's user-visible opaque handling files<commit_after>#include <opaque/typekit/OpaqueTypes.hpp>
#include <opaque/typekit/Opaques.hpp>

void orogen_typekits::toIntermediate(TestOpaque::Point2D& intermediate, NotOrogenCompatible::Point2D const& real_type)
{
    intermediate.padding = 100;
    intermediate.x = real_type.x();
    intermediate.y = real_type.y();
}
void orogen_typekits::fromIntermediate(NotOrogenCompatible::Point2D& real_type, TestOpaque::Point2D const& intermediate)
{
    real_type.x() = intermediate.x;
    real_type.y() = intermediate.y;
}

std::vector<float> const& orogen_typekits::toIntermediate(boost::shared_ptr<std::vector<float> > const& real_type)
{
    return *real_type;
}
bool orogen_typekits::fromIntermediate(boost::shared_ptr<std::vector<float> >& real_type, std::vector<float>* intermediate)
{
    if (intermediate != real_type.get())
        real_type.reset( intermediate );
    return true; // we get the ownership on +intermediate+
}
<|endoftext|>


<commit_before>#include "HeightMap.h"

HeightMap::HeightMap() : ReadWriteLock("HeightMap"), Logger() {
	planes = (HeightMapPlane**) malloc(PLANESSIZE * PLANESSIZE * sizeof(HeightMapPlane*));

	for (int i = 0; i < PLANESSIZE * PLANESSIZE; ++i) {
		planes[i] = NULL;
	}

	reader = NULL;

	setLoggingName("HeightMap");
	setLogging(false);
	setGlobalLogging(true);
}

HeightMap::~HeightMap() {
	if (reader != NULL) {
		delete reader;
		reader = NULL;
	}

	for (int i = 0; i < PLANESSIZE * PLANESSIZE; ++i) {
		HeightMapPlane* plane = planes[i];

		if (plane != NULL)
			delete plane;
	}

	free(planes);
}

void HeightMap::load(const String& path) {
	wlock();

	File* file = new File(path);

	try {
		reader = new FileInputStream(file);

		info("loaded " + path);
	} catch (FileNotFoundException& e) {
		reader = NULL;

		info("failed to load " + path);
	}

	unlock();
}

float HeightMap::getHeight(float x, float y) {
	if (reader == NULL)
		return 0;

	float retHeight = 0;

	try {

		int planePosition = getPlanePosition(x, y);

		rlock();

		HeightMapPlane* plane = planes[planePosition];

		if (plane == NULL) {
			//System::out << "Streaming in heightplane number " << planePosition << ".\n";
			runlock();

			plane = streamPlaneAt(x, y);

			rlock();
		}

		int width = (int) (x + ORIGOSHIFT) % PLANEWIDTH;
		int height = (int) (y + ORIGOSHIFT) % PLANEWIDTH;

		retHeight = plane->getHeight(width, height);

		runlock();
	} catch (...) {
		System::out << "Exception while getting height";
		runlock();
	}

	return retHeight;
}

float HeightMap::getHeightFrom(FileInputStream* file, float x, float y) {
	if (x < -7680 || x > 7680 || y < -7680 || y > 7680)
		return 0;

	byte buffer[sizeof(float)];

	int tableX = (int) x + 7680;
	int tableY = (int) y + 7680;

	uint32 offset = ((7680 * 2 + 1) * tableX + tableY) * sizeof(float);

	file->read(buffer, offset, sizeof(float));

	return *((float*) buffer);
}

HeightMapPlane* HeightMap::streamPlaneAt(float x, float y) {
	wlock();

	int planePosition = getPlanePosition(x, y);

	HeightMapPlane* plane = planes[planePosition];

	if (plane != NULL) {
		unlock();
		return plane;
	}

	if (planeQueue.size() < PLANELIMIT) {
		plane = planes[planePosition] = new HeightMapPlane(planePosition, PLANEWIDTH);
	} else {
		plane = planeQueue.remove();
		planes[plane->getIndex()] = NULL;

		planes[planePosition] = plane;
		plane->setIndex(planePosition);
	}

	planeQueue.add(plane);

	int planeOffset = planePosition * PLANEWIDTH * PLANEWIDTH * HEIGHTSIZE;
	reader->read(plane->getBuffer(), planeOffset, PLANEWIDTH * PLANEWIDTH * HEIGHTSIZE);

	unlock();

	return plane;
}

int HeightMap::getPlanePosition(float x, float y) {
	int planeX = (int) (x + ORIGOSHIFT) / PLANEWIDTH;
	// check needed only for when x == ORIGOSHIFT because the plane with that
	// x value doesn't exist
	if(planeX > PLANESSIZE - 1)
		planeX = PLANESSIZE - 1;

	int planeY = (int) (y + ORIGOSHIFT) / PLANEWIDTH;
	// check needed only for when y == ORIGOSHIFT because the plane with that
	// y value doesn't exist
	if(planeY > PLANESSIZE - 1)
		planeY = PLANESSIZE - 1;

	return planeX + planeY * PLANESSIZE;
}

void HeightMap::convert(const String& path) {
	FileInputStream* reader = new FileInputStream(new File(path));
	FileOutputStream* writer = new FileOutputStream(new File("converted_" + path));

	byte emptybuffer[PLANEWIDTH * HEIGHTSIZE];

	for (int i = 0; i < PLANEWIDTH * HEIGHTSIZE; ++i)
		emptybuffer[i] = 0;

	// first 2 lines
	for (int i = 0; i < 2 * 64; ++i) {
		for (int j = 0; j < PLANEWIDTH; ++j)
			writer->write(emptybuffer, PLANEWIDTH * HEIGHTSIZE);
	}

	int planeIndexX = 2;
	int planeIndexY = 2;

	// inner 60 lines
	for (int i = 0; i < 60; ++i) {
		// 2 beginning plane
		for (int j = 0; j < 2 * PLANEWIDTH; ++j)
			writer->write(emptybuffer, PLANEWIDTH * HEIGHTSIZE);

		// inner 60 planes
		for (int j = 0; j < 60; ++j) {
			System::out << "\r writing(" << planeIndexX << ", " << planeIndexY << ")";

			float plane[PLANEWIDTH * PLANEWIDTH];
			readPlaneForConversion(reader, plane, planeIndexX - 2, planeIndexY - 2);

			writer->write((byte*) plane, PLANEWIDTH * PLANEWIDTH * HEIGHTSIZE);

			++planeIndexX;
		}

		planeIndexX = 2;
		++planeIndexY;

		// 2 ending plane
		for (int j = 0; j < 2 * PLANEWIDTH; ++j)
			writer->write(emptybuffer, PLANEWIDTH * HEIGHTSIZE);
	}

	//last 2 lines
	for (int i = 0; i < 2 * 64; ++i) {
		for (int j = 0; j < PLANEWIDTH; ++j)
			writer->write(emptybuffer, PLANEWIDTH * HEIGHTSIZE);
	}

	writer->close();
}

void HeightMap::readPlaneForConversion(FileInputStream* file, float* buffer, int planeX, int planeY) {
	int tableX = planeX * PLANEWIDTH - 7680;
	int tableY = planeY * PLANEWIDTH - 7680;

	for (int y = 0; y < PLANEWIDTH; ++y) {
		for (int x = 0; x < PLANEWIDTH; ++x) {
			*(buffer++) = getHeightFrom(file, tableX + x, tableY + y);
		}
	}
}

<commit_msg>[fixed] TC fixes<commit_after>#include "HeightMap.h"

HeightMap::HeightMap() : ReadWriteLock("HeightMap"), Logger() {
	planes = (HeightMapPlane**) malloc(PLANESSIZE * PLANESSIZE * sizeof(HeightMapPlane*));

	for (int i = 0; i < PLANESSIZE * PLANESSIZE; ++i) {
		planes[i] = NULL;
	}

	reader = NULL;

	setLoggingName("HeightMap");
	setLogging(false);
	setGlobalLogging(true);
}

HeightMap::~HeightMap() {
	if (reader != NULL) {
		delete reader;
		reader = NULL;
	}

	for (int i = 0; i < PLANESSIZE * PLANESSIZE; ++i) {
		HeightMapPlane* plane = planes[i];

		if (plane != NULL)
			delete plane;
	}

	free(planes);
}

void HeightMap::load(const String& path) {
	wlock();

	try {
		File* file = new File(path);

		reader = new FileInputStream(file);

		if (file->exists()) {
			info("loaded " + path);
		} else {
			info("failed to load " + path);

			reader = NULL;
		}
	} catch (FileNotFoundException& e) {
		reader = NULL;

		info("failed to load " + path);
	}

	unlock();
}

float HeightMap::getHeight(float x, float y) {
	if (reader == NULL)
		return 0;

	float retHeight = 0;

	try {

		int planePosition = getPlanePosition(x, y);

		rlock();

		HeightMapPlane* plane = planes[planePosition];

		if (plane == NULL) {
			//System::out << "Streaming in heightplane number " << planePosition << ".\n";
			runlock();

			plane = streamPlaneAt(x, y);

			rlock();
		}

		int width = (int) (x + ORIGOSHIFT) % PLANEWIDTH;
		int height = (int) (y + ORIGOSHIFT) % PLANEWIDTH;

		retHeight = plane->getHeight(width, height);

		runlock();
	} catch (...) {
		System::out << "Exception while getting height";
		runlock();
	}

	return retHeight;
}

float HeightMap::getHeightFrom(FileInputStream* file, float x, float y) {
	if (x < -7680 || x > 7680 || y < -7680 || y > 7680)
		return 0;

	byte buffer[sizeof(float)];

	int tableX = (int) x + 7680;
	int tableY = (int) y + 7680;

	uint32 offset = ((7680 * 2 + 1) * tableX + tableY) * sizeof(float);

	file->read(buffer, offset, sizeof(float));

	return *((float*) buffer);
}

HeightMapPlane* HeightMap::streamPlaneAt(float x, float y) {
	wlock();

	int planePosition = getPlanePosition(x, y);

	HeightMapPlane* plane = planes[planePosition];

	if (plane != NULL) {
		unlock();
		return plane;
	}

	if (planeQueue.size() < PLANELIMIT) {
		plane = planes[planePosition] = new HeightMapPlane(planePosition, PLANEWIDTH);
	} else {
		plane = planeQueue.remove();
		planes[plane->getIndex()] = NULL;

		planes[planePosition] = plane;
		plane->setIndex(planePosition);
	}

	planeQueue.add(plane);

	int planeOffset = planePosition * PLANEWIDTH * PLANEWIDTH * HEIGHTSIZE;
	reader->read(plane->getBuffer(), planeOffset, PLANEWIDTH * PLANEWIDTH * HEIGHTSIZE);

	unlock();

	return plane;
}

int HeightMap::getPlanePosition(float x, float y) {
	int planeX = (int) (x + ORIGOSHIFT) / PLANEWIDTH;
	// check needed only for when x == ORIGOSHIFT because the plane with that
	// x value doesn't exist
	if(planeX > PLANESSIZE - 1)
		planeX = PLANESSIZE - 1;

	int planeY = (int) (y + ORIGOSHIFT) / PLANEWIDTH;
	// check needed only for when y == ORIGOSHIFT because the plane with that
	// y value doesn't exist
	if(planeY > PLANESSIZE - 1)
		planeY = PLANESSIZE - 1;

	return planeX + planeY * PLANESSIZE;
}

void HeightMap::convert(const String& path) {
	FileInputStream* reader = new FileInputStream(new File(path));
	FileOutputStream* writer = new FileOutputStream(new File("converted_" + path));

	byte emptybuffer[PLANEWIDTH * HEIGHTSIZE];

	for (int i = 0; i < PLANEWIDTH * HEIGHTSIZE; ++i)
		emptybuffer[i] = 0;

	// first 2 lines
	for (int i = 0; i < 2 * 64; ++i) {
		for (int j = 0; j < PLANEWIDTH; ++j)
			writer->write(emptybuffer, PLANEWIDTH * HEIGHTSIZE);
	}

	int planeIndexX = 2;
	int planeIndexY = 2;

	// inner 60 lines
	for (int i = 0; i < 60; ++i) {
		// 2 beginning plane
		for (int j = 0; j < 2 * PLANEWIDTH; ++j)
			writer->write(emptybuffer, PLANEWIDTH * HEIGHTSIZE);

		// inner 60 planes
		for (int j = 0; j < 60; ++j) {
			System::out << "\r writing(" << planeIndexX << ", " << planeIndexY << ")";

			float plane[PLANEWIDTH * PLANEWIDTH];
			readPlaneForConversion(reader, plane, planeIndexX - 2, planeIndexY - 2);

			writer->write((byte*) plane, PLANEWIDTH * PLANEWIDTH * HEIGHTSIZE);

			++planeIndexX;
		}

		planeIndexX = 2;
		++planeIndexY;

		// 2 ending plane
		for (int j = 0; j < 2 * PLANEWIDTH; ++j)
			writer->write(emptybuffer, PLANEWIDTH * HEIGHTSIZE);
	}

	//last 2 lines
	for (int i = 0; i < 2 * 64; ++i) {
		for (int j = 0; j < PLANEWIDTH; ++j)
			writer->write(emptybuffer, PLANEWIDTH * HEIGHTSIZE);
	}

	writer->close();
}

void HeightMap::readPlaneForConversion(FileInputStream* file, float* buffer, int planeX, int planeY) {
	int tableX = planeX * PLANEWIDTH - 7680;
	int tableY = planeY * PLANEWIDTH - 7680;

	for (int y = 0; y < PLANEWIDTH; ++y) {
		for (int x = 0; x < PLANEWIDTH; ++x) {
			*(buffer++) = getHeightFrom(file, tableX + x, tableY + y);
		}
	}
}

<|endoftext|>