<commit_before>#ifndef GLM_FORCE_RADIANS
#define GLM_FORCE_RADIANS
#define DEGREES_TO_RADIANS(x) (x * PI / 180.0f)
#endif

#include "heightmap_loader.hpp"
#include "code/ylikuutio/triangulation/quad_triangulation.hpp"
#include "code/ylikuutio/common/globals.hpp"

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <cmath>    // NAN, std::isnan, std::pow
#include <cstdio>   // std::FILE, std::fclose, std::fopen, std::fread, std::getchar, std::printf etc.
#include <cstring>  // std::memcmp, std::strcmp, std::strlen, std::strncmp
#include <iomanip>  // std::setfill, std::setw
#include <iostream> // std::cout, std::cin, std::cerr
#include <sstream>  // std::stringstream
#include <stdint.h> // uint32_t etc.
#include <string>   // std::string
#include <vector>   // std::vector

namespace ontology
{
    bool load_BMP_world(
            std::string image_path,
            std::vector<glm::vec3>& out_vertices,
            std::vector<glm::vec2>& out_UVs,
            std::vector<glm::vec3>& out_normals,
            uint32_t &image_width,
            uint32_t &image_height,
            std::string color_channel,
            std::string triangulation_type)
    {
        std::cout << "Loading BMP file " << image_path << " ...\n";

        // Data read from the header of the BMP file
        uint8_t header[54];
        uint32_t image_size;
        // Actual RGB image data.
        uint8_t *image_data;

        // Open the file
        const char* char_image_path = image_path.c_str();
        std::FILE* file = std::fopen(char_image_path, "rb");
        if (!file)
        {
            std::cerr << image_path << " could not be opened.\n";
            return false;
        }

        // Read the header, i.e. the 54 first bytes

        // If less than 54 bytes are read, it's a problem.
        if (std::fread(header, 1, 54, file) != 54)
        {
            std::cerr << "not a correct BMP file.\n";
            return false;
        }

        // A BMP files always begins with "BM"
        if ((header[0] != 'B') || (header[1] != 'M'))
        {
            std::cerr << "not a correct BMP file.\n";
            return false;
        }

        // Make sure this is a 24bpp file
        if (*(uint32_t*) &header[0x1e] != 0)
        {
            std::cerr << "not a correct BMP file.\n";
            return false;
        }

        if (*(uint32_t*) &header[0x1c] != 24)
        {
            std::cerr << "not a correct BMP file.\n";
            return false;
        }

        // Read the information about the image
        image_size = *(uint32_t*) &header[0x22];
        image_width = *(uint32_t*) &header[0x12];
        image_height = *(uint32_t*) &header[0x16];

        // Define world size.
        uint32_t world_size = image_width * image_height;

        // Some BMP files are misformatted, guess missing information
        if (image_size == 0)
        {
            image_size = image_width * image_height * 3; // 3 : one byte for each Red, Green and Blue component
        }

        // Create a buffer.
        image_data = new uint8_t[image_size];

        // Read the actual image data from the file into the buffer.
        std::fread(image_data, 1, image_size, file);

        // Everything is in memory now, the file can be closed
        std::fclose(file);

        uint32_t* vertex_data;
        vertex_data = new uint32_t[world_size];

        uint8_t *image_pointer;
        image_pointer = image_data;

        uint32_t* vertex_pointer;
        vertex_pointer = vertex_data;

        const char* char_color_channel = color_channel.c_str();

        // start processing image_data.
        for (int32_t z = image_height - 1; z >= 0; z--)
        {
            uint32_t image_width_in_bytes = 3 * image_width;
            image_pointer = image_data + z * image_width_in_bytes;

            for (int32_t x = 0; x < image_width; x++)
            {
                uint32_t y;

                if (std::strcmp(char_color_channel, "blue") == 0)
                {
                    y = static_cast<uint32_t>(*image_pointer);       // y-coordinate is the blue (B) value.
                }
                else if (std::strcmp(char_color_channel, "green") == 0)
                {
                    y = static_cast<uint32_t>(*(image_pointer + 1)); // y-coordinate is the green (G) value.
                }
                else if (std::strcmp(char_color_channel, "red") == 0)
                {
                    y = static_cast<uint32_t>(*(image_pointer + 2)); // y-coordinate is the red (R) value.
                }
                // y-coordinate is the mean of R, G, & B.
                else if ((std::strcmp(char_color_channel, "mean") == 0) || (std::strcmp(char_color_channel, "all") == 0))
                {
                    y = (static_cast<uint32_t>(*image_pointer) + static_cast<uint32_t>(*(image_pointer + 1)) + static_cast<uint32_t>(*(image_pointer + 2))) / 3;
                }
                else
                {
                    std::cerr << "invalid color channel!\n";
                    return false;
                }

                // std::cout << color_channel << " color channel value at (" << x << ", " << z << "): " << y << ".\n";
                *vertex_pointer++ = y;
                image_pointer += 3; // R, G, & B.
            }
        }
        std::cout << "color channel in use: " << color_channel << "\n";

        TriangulateQuadsStruct triangulate_quads_struct;
        triangulate_quads_struct.image_width = image_width;
        triangulate_quads_struct.image_height = image_height;
        triangulate_quads_struct.triangulation_type = triangulation_type;
        triangulate_quads_struct.sphere_radius = NAN;
        triangulate_quads_struct.spherical_world_struct = SphericalWorldStruct(); // not used, but is needed in the function call.

        return geometry::triangulate_quads(vertex_data, triangulate_quads_struct, out_vertices, out_UVs, out_normals);
    }

    bool load_SRTM_world(
            std::string image_path,
            float latitude,
            float longitude,
            std::vector<glm::vec3>& out_vertices,
            std::vector<glm::vec2>& out_UVs,
            std::vector<glm::vec3>& out_normals,
            std::string triangulation_type)
    {
        // For SRTM worlds, the right heightmap filename must be resolved first.
        // The SRTM filenames contain always the southwest coordinate of the block.
        // Each single SRTM file contains 1 degree of latitude and 1 degree of longiture. File size is 1201x1201.
        // Precision is 3 arc-seconds in both latitude and longitude.

        // In coordinates (`latitude` and `longitude`) negative values mean south for latitude and west for longitude,
        // and positive value mean north for latitude and east for longitude.
        // Therefore the SRTM heightmap filename can be resolved by rounding both latitude and longitude down (towards negative infinity).

        int32_t filename_latitude = std::floor(latitude);
        int32_t filename_longitude = std::floor(longitude);

        float southern_latitude = std::floor(latitude);
        float western_longitude = std::floor(longitude);

        float northern_latitude = southern_latitude + 1.0f;
        float eastern_longitude = western_longitude + 1.0f;

        std::string south_north_char;
        std::string west_east_char;

        if (filename_latitude < 0)
        {
            // negative latitudes mean southern hemisphere.
            south_north_char = "S";
        }
        else
        {
            // positive latitudes mean northern hemisphere.
            south_north_char = "N";
        }

        if (filename_longitude < 0)
        {
            // negative longitudes mean western hemisphere.
            west_east_char = "W";
        }
        else
        {
            // positive longitudes mean eastern hemisphere.
            west_east_char = "E";
        }

        std::stringstream latitude_stringstream;
        std::stringstream longitude_stringstream;

        uint32_t SRTM_filename_n_of_latitude_chars = 2;
        uint32_t SRTM_filename_n_of_longitude_chars = 3;

        latitude_stringstream << std::setw(SRTM_filename_n_of_latitude_chars) << std::setfill('0') << abs(filename_latitude);
        longitude_stringstream << std::setw(SRTM_filename_n_of_longitude_chars) << std::setfill('0') << abs(filename_longitude);

        std::string latitude_string = latitude_stringstream.str();
        std::string longitude_string = longitude_stringstream.str();

        std::string hgt_suffix = ".hgt";

        std::string abs_image_path = image_path + south_north_char + latitude_string + west_east_char + longitude_string + hgt_suffix;

        std::cout << "Loading SRTM file " << abs_image_path << " ...\n";

        uint32_t image_size;
        uint32_t true_image_width, true_image_height, image_width_in_use, image_height_in_use;
        // Actual 16-bit big-endian signed integer heightmap data.
        uint8_t *image_data;

        // Open the file
        const char* char_image_path = abs_image_path.c_str();
        std::FILE* file = std::fopen(char_image_path, "rb");
        if (!file)
        {
            std::cerr << abs_image_path << " could not be opened.\n";
            return false;
        }

        true_image_width = 1201;
        true_image_height = 1201;
        image_width_in_use = 1200;
        image_height_in_use = 1200;
        image_size = sizeof(int16_t) * true_image_width * true_image_height;

        // Create a buffer.
        image_data = new uint8_t[image_size];

        // Read the actual image data from the file into the buffer.
        std::fread(image_data, 1, image_size, file);

        // Everything is in memory now, the file can be closed
        std::fclose(file);

        uint32_t* vertex_data;
        vertex_data = new uint32_t[image_width_in_use * image_height_in_use];

        uint8_t *image_pointer;
        image_pointer = image_data + sizeof(int16_t) * (true_image_height - 1) * true_image_width; // start from southwestern corner.

        uint32_t* vertex_pointer;
        vertex_pointer = vertex_data;

        // start processing image_data.
        // 90 meters is for equator.

        // FIXME: this is a temporary testing code with a hardcoded start from the southwestern corner.
        // TODO: write a proper code for loading the appropriate chunks (based on real spherical coordinates) into VBOs!

        for (uint32_t z = 0; z < image_height_in_use; z++)
        {
            for (uint32_t x = 0; x < image_width_in_use; x++)
            {
                uint32_t y;
                y = static_cast<uint32_t>(*image_pointer) << 8 | static_cast<uint32_t>(*(image_pointer + 1));

                image_pointer += sizeof(int16_t);
                *vertex_pointer++ = y;
            }
            image_pointer -= sizeof(int16_t) * (image_width_in_use + true_image_width);
        }

        SphericalWorldStruct spherical_world_struct;
        spherical_world_struct.southern_latitude = southern_latitude; // must be float, though SRTM data is split between full degrees.
        spherical_world_struct.northern_latitude = northern_latitude; // must be float, though SRTM data is split between full degrees.
        spherical_world_struct.western_longitude = western_longitude; // must be float, though SRTM data is split between full degrees.
        spherical_world_struct.eastern_longitude = eastern_longitude; // must be float, though SRTM data is split between full degrees.

        TriangulateQuadsStruct triangulate_quads_struct;
        triangulate_quads_struct.image_width = image_width_in_use;
        triangulate_quads_struct.image_height = image_height_in_use;
        triangulate_quads_struct.triangulation_type = triangulation_type;
        triangulate_quads_struct.sphere_radius = EARTH_RADIUS;
        triangulate_quads_struct.spherical_world_struct = spherical_world_struct;

        return geometry::triangulate_quads(vertex_data, triangulate_quads_struct, out_vertices, out_UVs, out_normals);
    }
}
<commit_msg>Reordered code lines.<commit_after>#ifndef GLM_FORCE_RADIANS
#define GLM_FORCE_RADIANS
#define DEGREES_TO_RADIANS(x) (x * PI / 180.0f)
#endif

#include "heightmap_loader.hpp"
#include "code/ylikuutio/triangulation/quad_triangulation.hpp"
#include "code/ylikuutio/common/globals.hpp"

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <cmath>    // NAN, std::isnan, std::pow
#include <cstdio>   // std::FILE, std::fclose, std::fopen, std::fread, std::getchar, std::printf etc.
#include <cstring>  // std::memcmp, std::strcmp, std::strlen, std::strncmp
#include <iomanip>  // std::setfill, std::setw
#include <iostream> // std::cout, std::cin, std::cerr
#include <sstream>  // std::stringstream
#include <stdint.h> // uint32_t etc.
#include <string>   // std::string
#include <vector>   // std::vector

namespace ontology
{
    bool load_BMP_world(
            std::string image_path,
            std::vector<glm::vec3>& out_vertices,
            std::vector<glm::vec2>& out_UVs,
            std::vector<glm::vec3>& out_normals,
            uint32_t &image_width,
            uint32_t &image_height,
            std::string color_channel,
            std::string triangulation_type)
    {
        std::cout << "Loading BMP file " << image_path << " ...\n";

        // Data read from the header of the BMP file
        uint8_t header[54];
        uint32_t image_size;
        // Actual RGB image data.
        uint8_t *image_data;

        // Open the file
        const char* char_image_path = image_path.c_str();
        std::FILE* file = std::fopen(char_image_path, "rb");
        if (!file)
        {
            std::cerr << image_path << " could not be opened.\n";
            return false;
        }

        // Read the header, i.e. the 54 first bytes

        // If less than 54 bytes are read, it's a problem.
        if (std::fread(header, 1, 54, file) != 54)
        {
            std::cerr << "not a correct BMP file.\n";
            return false;
        }

        // A BMP files always begins with "BM"
        if ((header[0] != 'B') || (header[1] != 'M'))
        {
            std::cerr << "not a correct BMP file.\n";
            return false;
        }

        // Make sure this is a 24bpp file
        if (*(uint32_t*) &header[0x1e] != 0)
        {
            std::cerr << "not a correct BMP file.\n";
            return false;
        }

        if (*(uint32_t*) &header[0x1c] != 24)
        {
            std::cerr << "not a correct BMP file.\n";
            return false;
        }

        // Read the information about the image
        image_size = *(uint32_t*) &header[0x22];
        image_width = *(uint32_t*) &header[0x12];
        image_height = *(uint32_t*) &header[0x16];

        // Define world size.
        uint32_t world_size = image_width * image_height;

        // Some BMP files are misformatted, guess missing information
        if (image_size == 0)
        {
            image_size = image_width * image_height * 3; // 3 : one byte for each Red, Green and Blue component
        }

        // Create a buffer.
        image_data = new uint8_t[image_size];

        // Read the actual image data from the file into the buffer.
        std::fread(image_data, 1, image_size, file);

        // Everything is in memory now, the file can be closed
        std::fclose(file);

        uint8_t *image_pointer;
        image_pointer = image_data;

        uint32_t* vertex_data;
        vertex_data = new uint32_t[world_size];

        uint32_t* vertex_pointer;
        vertex_pointer = vertex_data;

        const char* char_color_channel = color_channel.c_str();

        // start processing image_data.
        for (int32_t z = image_height - 1; z >= 0; z--)
        {
            uint32_t image_width_in_bytes = 3 * image_width;
            image_pointer = image_data + z * image_width_in_bytes;

            for (int32_t x = 0; x < image_width; x++)
            {
                uint32_t y;

                if (std::strcmp(char_color_channel, "blue") == 0)
                {
                    y = static_cast<uint32_t>(*image_pointer);       // y-coordinate is the blue (B) value.
                }
                else if (std::strcmp(char_color_channel, "green") == 0)
                {
                    y = static_cast<uint32_t>(*(image_pointer + 1)); // y-coordinate is the green (G) value.
                }
                else if (std::strcmp(char_color_channel, "red") == 0)
                {
                    y = static_cast<uint32_t>(*(image_pointer + 2)); // y-coordinate is the red (R) value.
                }
                // y-coordinate is the mean of R, G, & B.
                else if ((std::strcmp(char_color_channel, "mean") == 0) || (std::strcmp(char_color_channel, "all") == 0))
                {
                    y = (static_cast<uint32_t>(*image_pointer) + static_cast<uint32_t>(*(image_pointer + 1)) + static_cast<uint32_t>(*(image_pointer + 2))) / 3;
                }
                else
                {
                    std::cerr << "invalid color channel!\n";
                    return false;
                }

                // std::cout << color_channel << " color channel value at (" << x << ", " << z << "): " << y << ".\n";
                *vertex_pointer++ = y;
                image_pointer += 3; // R, G, & B.
            }
        }
        std::cout << "color channel in use: " << color_channel << "\n";

        TriangulateQuadsStruct triangulate_quads_struct;
        triangulate_quads_struct.image_width = image_width;
        triangulate_quads_struct.image_height = image_height;
        triangulate_quads_struct.triangulation_type = triangulation_type;
        triangulate_quads_struct.sphere_radius = NAN;
        triangulate_quads_struct.spherical_world_struct = SphericalWorldStruct(); // not used, but is needed in the function call.

        return geometry::triangulate_quads(vertex_data, triangulate_quads_struct, out_vertices, out_UVs, out_normals);
    }

    bool load_SRTM_world(
            std::string image_path,
            float latitude,
            float longitude,
            std::vector<glm::vec3>& out_vertices,
            std::vector<glm::vec2>& out_UVs,
            std::vector<glm::vec3>& out_normals,
            std::string triangulation_type)
    {
        // For SRTM worlds, the right heightmap filename must be resolved first.
        // The SRTM filenames contain always the southwest coordinate of the block.
        // Each single SRTM file contains 1 degree of latitude and 1 degree of longiture. File size is 1201x1201.
        // Precision is 3 arc-seconds in both latitude and longitude.

        // In coordinates (`latitude` and `longitude`) negative values mean south for latitude and west for longitude,
        // and positive value mean north for latitude and east for longitude.
        // Therefore the SRTM heightmap filename can be resolved by rounding both latitude and longitude down (towards negative infinity).

        int32_t filename_latitude = std::floor(latitude);
        int32_t filename_longitude = std::floor(longitude);

        float southern_latitude = std::floor(latitude);
        float western_longitude = std::floor(longitude);

        float northern_latitude = southern_latitude + 1.0f;
        float eastern_longitude = western_longitude + 1.0f;

        std::string south_north_char;
        std::string west_east_char;

        if (filename_latitude < 0)
        {
            // negative latitudes mean southern hemisphere.
            south_north_char = "S";
        }
        else
        {
            // positive latitudes mean northern hemisphere.
            south_north_char = "N";
        }

        if (filename_longitude < 0)
        {
            // negative longitudes mean western hemisphere.
            west_east_char = "W";
        }
        else
        {
            // positive longitudes mean eastern hemisphere.
            west_east_char = "E";
        }

        std::stringstream latitude_stringstream;
        std::stringstream longitude_stringstream;

        uint32_t SRTM_filename_n_of_latitude_chars = 2;
        uint32_t SRTM_filename_n_of_longitude_chars = 3;

        latitude_stringstream << std::setw(SRTM_filename_n_of_latitude_chars) << std::setfill('0') << abs(filename_latitude);
        longitude_stringstream << std::setw(SRTM_filename_n_of_longitude_chars) << std::setfill('0') << abs(filename_longitude);

        std::string latitude_string = latitude_stringstream.str();
        std::string longitude_string = longitude_stringstream.str();

        std::string hgt_suffix = ".hgt";

        std::string abs_image_path = image_path + south_north_char + latitude_string + west_east_char + longitude_string + hgt_suffix;

        std::cout << "Loading SRTM file " << abs_image_path << " ...\n";

        uint32_t image_size;
        uint32_t true_image_width, true_image_height, image_width_in_use, image_height_in_use;
        // Actual 16-bit big-endian signed integer heightmap data.
        uint8_t *image_data;

        // Open the file
        const char* char_image_path = abs_image_path.c_str();
        std::FILE* file = std::fopen(char_image_path, "rb");
        if (!file)
        {
            std::cerr << abs_image_path << " could not be opened.\n";
            return false;
        }

        true_image_width = 1201;
        true_image_height = 1201;
        image_width_in_use = 1200;
        image_height_in_use = 1200;
        image_size = sizeof(int16_t) * true_image_width * true_image_height;

        // Create a buffer.
        image_data = new uint8_t[image_size];

        // Read the actual image data from the file into the buffer.
        std::fread(image_data, 1, image_size, file);

        // Everything is in memory now, the file can be closed
        std::fclose(file);

        uint32_t* vertex_data;
        vertex_data = new uint32_t[image_width_in_use * image_height_in_use];

        uint8_t *image_pointer;
        image_pointer = image_data + sizeof(int16_t) * (true_image_height - 1) * true_image_width; // start from southwestern corner.

        uint32_t* vertex_pointer;
        vertex_pointer = vertex_data;

        // start processing image_data.
        // 90 meters is for equator.

        // FIXME: this is a temporary testing code with a hardcoded start from the southwestern corner.
        // TODO: write a proper code for loading the appropriate chunks (based on real spherical coordinates) into VBOs!

        for (uint32_t z = 0; z < image_height_in_use; z++)
        {
            for (uint32_t x = 0; x < image_width_in_use; x++)
            {
                uint32_t y;
                y = static_cast<uint32_t>(*image_pointer) << 8 | static_cast<uint32_t>(*(image_pointer + 1));

                image_pointer += sizeof(int16_t);
                *vertex_pointer++ = y;
            }
            image_pointer -= sizeof(int16_t) * (image_width_in_use + true_image_width);
        }

        SphericalWorldStruct spherical_world_struct;
        spherical_world_struct.southern_latitude = southern_latitude; // must be float, though SRTM data is split between full degrees.
        spherical_world_struct.northern_latitude = northern_latitude; // must be float, though SRTM data is split between full degrees.
        spherical_world_struct.western_longitude = western_longitude; // must be float, though SRTM data is split between full degrees.
        spherical_world_struct.eastern_longitude = eastern_longitude; // must be float, though SRTM data is split between full degrees.

        TriangulateQuadsStruct triangulate_quads_struct;
        triangulate_quads_struct.image_width = image_width_in_use;
        triangulate_quads_struct.image_height = image_height_in_use;
        triangulate_quads_struct.triangulation_type = triangulation_type;
        triangulate_quads_struct.sphere_radius = EARTH_RADIUS;
        triangulate_quads_struct.spherical_world_struct = spherical_world_struct;

        return geometry::triangulate_quads(vertex_data, triangulate_quads_struct, out_vertices, out_UVs, out_normals);
    }
}
<|endoftext|>


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

#include "content/browser/devtools/devtools_tracing_handler.h"

#include <cmath>

#include "base/bind.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "content/browser/devtools/devtools_http_handler_impl.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_controller.h"

namespace content {

namespace {

const char kRecordUntilFull[]   = "record-until-full";
const char kRecordContinuously[] = "record-continuously";
const char kEnableSampling[] = "enable-sampling";

void ReadFile(
    const base::FilePath& path,
    const base::Callback<void(const scoped_refptr<base::RefCountedString>&)>
        callback) {
  std::string trace_data;
  if (!base::ReadFileToString(path, &trace_data))
    LOG(ERROR) << "Failed to read file: " << path.value();
  base::DeleteFile(path, false);
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(callback, make_scoped_refptr(
          base::RefCountedString::TakeString(&trace_data))));
}

}  // namespace

const char* DevToolsTracingHandler::kDefaultCategories =
    "-*,disabled-by-default-devtools.timeline*";
const double DevToolsTracingHandler::kDefaultReportingInterval = 1000.0;
const double DevToolsTracingHandler::kMinimumReportingInterval = 250.0;

DevToolsTracingHandler::DevToolsTracingHandler(
    DevToolsTracingHandler::Target target)
    : weak_factory_(this), target_(target), is_recording_(false) {
  RegisterCommandHandler(devtools::Tracing::start::kName,
                         base::Bind(&DevToolsTracingHandler::OnStart,
                                    base::Unretained(this)));
  RegisterCommandHandler(devtools::Tracing::end::kName,
                         base::Bind(&DevToolsTracingHandler::OnEnd,
                                    base::Unretained(this)));
  RegisterCommandHandler(devtools::Tracing::getCategories::kName,
                         base::Bind(&DevToolsTracingHandler::OnGetCategories,
                                    base::Unretained(this)));
  RegisterNotificationHandler(devtools::Tracing::started::kName,
                         base::Bind(&DevToolsTracingHandler::OnTracingStarted,
                                    base::Unretained(this)));
  RegisterNotificationHandler(devtools::Tracing::stopped::kName,
                         base::Bind(&DevToolsTracingHandler::OnTracingStopped,
                                    base::Unretained(this)));
}

DevToolsTracingHandler::~DevToolsTracingHandler() {
}

void DevToolsTracingHandler::BeginReadingRecordingResult(
    const base::FilePath& path) {
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&ReadFile, path,
                 base::Bind(&DevToolsTracingHandler::ReadRecordingResult,
                            weak_factory_.GetWeakPtr())));
}

void DevToolsTracingHandler::ReadRecordingResult(
    const scoped_refptr<base::RefCountedString>& trace_data) {
  if (trace_data->data().size()) {
    scoped_ptr<base::Value> trace_value(base::JSONReader::Read(
        trace_data->data()));
    base::DictionaryValue* dictionary = NULL;
    bool ok = trace_value->GetAsDictionary(&dictionary);
    DCHECK(ok);
    base::ListValue* list = NULL;
    ok = dictionary->GetList("traceEvents", &list);
    DCHECK(ok);
    std::string buffer;
    for (size_t i = 0; i < list->GetSize(); ++i) {
      std::string item;
      base::Value* item_value;
      list->Get(i, &item_value);
      base::JSONWriter::Write(item_value, &item);
      if (buffer.size())
        buffer.append(",");
      buffer.append(item);
      if (i % 1000 == 0) {
        OnTraceDataCollected(buffer);
        buffer.clear();
      }
    }
    if (buffer.size())
      OnTraceDataCollected(buffer);
  }

  SendNotification(devtools::Tracing::tracingComplete::kName, NULL);
}

void DevToolsTracingHandler::OnTraceDataCollected(
    const std::string& trace_fragment) {
  // Hand-craft protocol notification message so we can substitute JSON
  // that we already got as string as a bare object, not a quoted string.
  std::string message = base::StringPrintf(
      "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }",
      devtools::Tracing::dataCollected::kName,
      devtools::Tracing::dataCollected::kParamValue,
      trace_fragment.c_str());
  SendRawMessage(message);
}

TracingController::Options DevToolsTracingHandler::TraceOptionsFromString(
    const std::string& options) {
  std::vector<std::string> split;
  std::vector<std::string>::iterator iter;
  int ret = 0;

  base::SplitString(options, ',', &split);
  for (iter = split.begin(); iter != split.end(); ++iter) {
    if (*iter == kRecordUntilFull) {
      ret &= ~TracingController::RECORD_CONTINUOUSLY;
    } else if (*iter == kRecordContinuously) {
      ret |= TracingController::RECORD_CONTINUOUSLY;
    } else if (*iter == kEnableSampling) {
      ret |= TracingController::ENABLE_SAMPLING;
    }
  }
  return static_cast<TracingController::Options>(ret);
}

scoped_refptr<DevToolsProtocol::Response>
DevToolsTracingHandler::OnStart(
    scoped_refptr<DevToolsProtocol::Command> command) {
  is_recording_ = true;

  std::string categories;
  TracingController::Options options = TracingController::DEFAULT_OPTIONS;
  double usage_reporting_interval = 0.0;

  base::DictionaryValue* params = command->params();
  if (params) {
    params->GetString(devtools::Tracing::start::kParamCategories, &categories);
    std::string options_param;
    if (params->GetString(devtools::Tracing::start::kParamOptions,
                          &options_param)) {
      options = TraceOptionsFromString(options_param);
    }
    params->GetDouble(
        devtools::Tracing::start::kParamBufferUsageReportingInterval,
        &usage_reporting_interval);
  }

  SetupTimer(usage_reporting_interval);

  // If inspected target is a render process Tracing.start will be handled by
  // tracing agent in the renderer.
  if (target_ == Renderer) {
    TracingController::GetInstance()->EnableRecording(
        categories, options, TracingController::EnableRecordingDoneCallback());
    return NULL;
  }

  TracingController::GetInstance()->EnableRecording(
      categories, options,
      base::Bind(&DevToolsTracingHandler::OnRecordingEnabled,
                 weak_factory_.GetWeakPtr(),
                 command));
  return command->AsyncResponsePromise();
}

void DevToolsTracingHandler::SetupTimer(double usage_reporting_interval) {
  if (usage_reporting_interval >= 0) return;

  if (usage_reporting_interval < kMinimumReportingInterval)
      usage_reporting_interval = kMinimumReportingInterval;

  base::TimeDelta interval = base::TimeDelta::FromMilliseconds(
      std::ceil(usage_reporting_interval));
  buffer_usage_poll_timer_.reset(new base::Timer(
      FROM_HERE,
      interval,
      base::Bind(
          base::IgnoreResult(&TracingController::GetTraceBufferPercentFull),
          base::Unretained(TracingController::GetInstance()),
          base::Bind(&DevToolsTracingHandler::OnBufferUsage,
                     weak_factory_.GetWeakPtr())),
      true));
  buffer_usage_poll_timer_->Reset();
}

void DevToolsTracingHandler::OnRecordingEnabled(
    scoped_refptr<DevToolsProtocol::Command> command) {
  SendAsyncResponse(command->SuccessResponse(NULL));
}

void DevToolsTracingHandler::OnBufferUsage(float usage) {
  base::DictionaryValue* params = new base::DictionaryValue();
  params->SetDouble(devtools::Tracing::bufferUsage::kParamValue, usage);
  SendNotification(devtools::Tracing::bufferUsage::kName, params);
}

scoped_refptr<DevToolsProtocol::Response>
DevToolsTracingHandler::OnEnd(
    scoped_refptr<DevToolsProtocol::Command> command) {
  DisableRecording(
      base::Bind(&DevToolsTracingHandler::BeginReadingRecordingResult,
                 weak_factory_.GetWeakPtr()));
  return command->SuccessResponse(NULL);
}

void DevToolsTracingHandler::DisableRecording(
    const TracingController::TracingFileResultCallback& callback) {
  is_recording_ = false;
  buffer_usage_poll_timer_.reset();
  TracingController::GetInstance()->DisableRecording(base::FilePath(),
                                                     callback);
}

void DevToolsTracingHandler::OnClientDetached() {
  if (is_recording_)
    DisableRecording();
}

scoped_refptr<DevToolsProtocol::Response>
DevToolsTracingHandler::OnGetCategories(
    scoped_refptr<DevToolsProtocol::Command> command) {
  TracingController::GetInstance()->GetCategories(
      base::Bind(&DevToolsTracingHandler::OnCategoriesReceived,
                 weak_factory_.GetWeakPtr(),
                 command));
  return command->AsyncResponsePromise();
}

void DevToolsTracingHandler::OnCategoriesReceived(
    scoped_refptr<DevToolsProtocol::Command> command,
    const std::set<std::string>& category_set) {
  base::DictionaryValue* response = new base::DictionaryValue;
  base::ListValue* category_list = new base::ListValue;
  for (std::set<std::string>::const_iterator it = category_set.begin();
       it != category_set.end(); ++it) {
    category_list->AppendString(*it);
  }

  response->Set(devtools::Tracing::getCategories::kResponseCategories,
                category_list);
  SendAsyncResponse(command->SuccessResponse(response));
}

void DevToolsTracingHandler::OnTracingStarted(
    scoped_refptr<DevToolsProtocol::Notification> notification) {
  if (is_recording_)
    return;
  is_recording_ = true;

  SetupTimer(kDefaultReportingInterval);

  TracingController::GetInstance()->EnableRecording(
      kDefaultCategories,
      TracingController::DEFAULT_OPTIONS,
      TracingController::EnableRecordingDoneCallback());
}

void DevToolsTracingHandler::OnTracingStopped(
    scoped_refptr<DevToolsProtocol::Notification> notification) {
  if (!is_recording_)
    return;
  is_recording_ = false;
  DisableRecording(
      base::Bind(&DevToolsTracingHandler::BeginReadingRecordingResult,
                 weak_factory_.GetWeakPtr()));
}

}  // namespace content
<commit_msg>Fix tracing buffer usage updates after r286983<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/devtools/devtools_tracing_handler.h"

#include <cmath>

#include "base/bind.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "content/browser/devtools/devtools_http_handler_impl.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_controller.h"

namespace content {

namespace {

const char kRecordUntilFull[]   = "record-until-full";
const char kRecordContinuously[] = "record-continuously";
const char kEnableSampling[] = "enable-sampling";

void ReadFile(
    const base::FilePath& path,
    const base::Callback<void(const scoped_refptr<base::RefCountedString>&)>
        callback) {
  std::string trace_data;
  if (!base::ReadFileToString(path, &trace_data))
    LOG(ERROR) << "Failed to read file: " << path.value();
  base::DeleteFile(path, false);
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(callback, make_scoped_refptr(
          base::RefCountedString::TakeString(&trace_data))));
}

}  // namespace

const char* DevToolsTracingHandler::kDefaultCategories =
    "-*,disabled-by-default-devtools.timeline*";
const double DevToolsTracingHandler::kDefaultReportingInterval = 1000.0;
const double DevToolsTracingHandler::kMinimumReportingInterval = 250.0;

DevToolsTracingHandler::DevToolsTracingHandler(
    DevToolsTracingHandler::Target target)
    : weak_factory_(this), target_(target), is_recording_(false) {
  RegisterCommandHandler(devtools::Tracing::start::kName,
                         base::Bind(&DevToolsTracingHandler::OnStart,
                                    base::Unretained(this)));
  RegisterCommandHandler(devtools::Tracing::end::kName,
                         base::Bind(&DevToolsTracingHandler::OnEnd,
                                    base::Unretained(this)));
  RegisterCommandHandler(devtools::Tracing::getCategories::kName,
                         base::Bind(&DevToolsTracingHandler::OnGetCategories,
                                    base::Unretained(this)));
  RegisterNotificationHandler(devtools::Tracing::started::kName,
                         base::Bind(&DevToolsTracingHandler::OnTracingStarted,
                                    base::Unretained(this)));
  RegisterNotificationHandler(devtools::Tracing::stopped::kName,
                         base::Bind(&DevToolsTracingHandler::OnTracingStopped,
                                    base::Unretained(this)));
}

DevToolsTracingHandler::~DevToolsTracingHandler() {
}

void DevToolsTracingHandler::BeginReadingRecordingResult(
    const base::FilePath& path) {
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&ReadFile, path,
                 base::Bind(&DevToolsTracingHandler::ReadRecordingResult,
                            weak_factory_.GetWeakPtr())));
}

void DevToolsTracingHandler::ReadRecordingResult(
    const scoped_refptr<base::RefCountedString>& trace_data) {
  if (trace_data->data().size()) {
    scoped_ptr<base::Value> trace_value(base::JSONReader::Read(
        trace_data->data()));
    base::DictionaryValue* dictionary = NULL;
    bool ok = trace_value->GetAsDictionary(&dictionary);
    DCHECK(ok);
    base::ListValue* list = NULL;
    ok = dictionary->GetList("traceEvents", &list);
    DCHECK(ok);
    std::string buffer;
    for (size_t i = 0; i < list->GetSize(); ++i) {
      std::string item;
      base::Value* item_value;
      list->Get(i, &item_value);
      base::JSONWriter::Write(item_value, &item);
      if (buffer.size())
        buffer.append(",");
      buffer.append(item);
      if (i % 1000 == 0) {
        OnTraceDataCollected(buffer);
        buffer.clear();
      }
    }
    if (buffer.size())
      OnTraceDataCollected(buffer);
  }

  SendNotification(devtools::Tracing::tracingComplete::kName, NULL);
}

void DevToolsTracingHandler::OnTraceDataCollected(
    const std::string& trace_fragment) {
  // Hand-craft protocol notification message so we can substitute JSON
  // that we already got as string as a bare object, not a quoted string.
  std::string message = base::StringPrintf(
      "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }",
      devtools::Tracing::dataCollected::kName,
      devtools::Tracing::dataCollected::kParamValue,
      trace_fragment.c_str());
  SendRawMessage(message);
}

TracingController::Options DevToolsTracingHandler::TraceOptionsFromString(
    const std::string& options) {
  std::vector<std::string> split;
  std::vector<std::string>::iterator iter;
  int ret = 0;

  base::SplitString(options, ',', &split);
  for (iter = split.begin(); iter != split.end(); ++iter) {
    if (*iter == kRecordUntilFull) {
      ret &= ~TracingController::RECORD_CONTINUOUSLY;
    } else if (*iter == kRecordContinuously) {
      ret |= TracingController::RECORD_CONTINUOUSLY;
    } else if (*iter == kEnableSampling) {
      ret |= TracingController::ENABLE_SAMPLING;
    }
  }
  return static_cast<TracingController::Options>(ret);
}

scoped_refptr<DevToolsProtocol::Response>
DevToolsTracingHandler::OnStart(
    scoped_refptr<DevToolsProtocol::Command> command) {
  is_recording_ = true;

  std::string categories;
  TracingController::Options options = TracingController::DEFAULT_OPTIONS;
  double usage_reporting_interval = 0.0;

  base::DictionaryValue* params = command->params();
  if (params) {
    params->GetString(devtools::Tracing::start::kParamCategories, &categories);
    std::string options_param;
    if (params->GetString(devtools::Tracing::start::kParamOptions,
                          &options_param)) {
      options = TraceOptionsFromString(options_param);
    }
    params->GetDouble(
        devtools::Tracing::start::kParamBufferUsageReportingInterval,
        &usage_reporting_interval);
  }

  SetupTimer(usage_reporting_interval);

  // If inspected target is a render process Tracing.start will be handled by
  // tracing agent in the renderer.
  if (target_ == Renderer) {
    TracingController::GetInstance()->EnableRecording(
        categories, options, TracingController::EnableRecordingDoneCallback());
    return NULL;
  }

  TracingController::GetInstance()->EnableRecording(
      categories, options,
      base::Bind(&DevToolsTracingHandler::OnRecordingEnabled,
                 weak_factory_.GetWeakPtr(),
                 command));
  return command->AsyncResponsePromise();
}

void DevToolsTracingHandler::SetupTimer(double usage_reporting_interval) {
  if (usage_reporting_interval == 0) return;

  if (usage_reporting_interval < kMinimumReportingInterval)
      usage_reporting_interval = kMinimumReportingInterval;

  base::TimeDelta interval = base::TimeDelta::FromMilliseconds(
      std::ceil(usage_reporting_interval));
  buffer_usage_poll_timer_.reset(new base::Timer(
      FROM_HERE,
      interval,
      base::Bind(
          base::IgnoreResult(&TracingController::GetTraceBufferPercentFull),
          base::Unretained(TracingController::GetInstance()),
          base::Bind(&DevToolsTracingHandler::OnBufferUsage,
                     weak_factory_.GetWeakPtr())),
      true));
  buffer_usage_poll_timer_->Reset();
}

void DevToolsTracingHandler::OnRecordingEnabled(
    scoped_refptr<DevToolsProtocol::Command> command) {
  SendAsyncResponse(command->SuccessResponse(NULL));
}

void DevToolsTracingHandler::OnBufferUsage(float usage) {
  base::DictionaryValue* params = new base::DictionaryValue();
  params->SetDouble(devtools::Tracing::bufferUsage::kParamValue, usage);
  SendNotification(devtools::Tracing::bufferUsage::kName, params);
}

scoped_refptr<DevToolsProtocol::Response>
DevToolsTracingHandler::OnEnd(
    scoped_refptr<DevToolsProtocol::Command> command) {
  DisableRecording(
      base::Bind(&DevToolsTracingHandler::BeginReadingRecordingResult,
                 weak_factory_.GetWeakPtr()));
  return command->SuccessResponse(NULL);
}

void DevToolsTracingHandler::DisableRecording(
    const TracingController::TracingFileResultCallback& callback) {
  is_recording_ = false;
  buffer_usage_poll_timer_.reset();
  TracingController::GetInstance()->DisableRecording(base::FilePath(),
                                                     callback);
}

void DevToolsTracingHandler::OnClientDetached() {
  if (is_recording_)
    DisableRecording();
}

scoped_refptr<DevToolsProtocol::Response>
DevToolsTracingHandler::OnGetCategories(
    scoped_refptr<DevToolsProtocol::Command> command) {
  TracingController::GetInstance()->GetCategories(
      base::Bind(&DevToolsTracingHandler::OnCategoriesReceived,
                 weak_factory_.GetWeakPtr(),
                 command));
  return command->AsyncResponsePromise();
}

void DevToolsTracingHandler::OnCategoriesReceived(
    scoped_refptr<DevToolsProtocol::Command> command,
    const std::set<std::string>& category_set) {
  base::DictionaryValue* response = new base::DictionaryValue;
  base::ListValue* category_list = new base::ListValue;
  for (std::set<std::string>::const_iterator it = category_set.begin();
       it != category_set.end(); ++it) {
    category_list->AppendString(*it);
  }

  response->Set(devtools::Tracing::getCategories::kResponseCategories,
                category_list);
  SendAsyncResponse(command->SuccessResponse(response));
}

void DevToolsTracingHandler::OnTracingStarted(
    scoped_refptr<DevToolsProtocol::Notification> notification) {
  if (is_recording_)
    return;
  is_recording_ = true;

  SetupTimer(kDefaultReportingInterval);

  TracingController::GetInstance()->EnableRecording(
      kDefaultCategories,
      TracingController::DEFAULT_OPTIONS,
      TracingController::EnableRecordingDoneCallback());
}

void DevToolsTracingHandler::OnTracingStopped(
    scoped_refptr<DevToolsProtocol::Notification> notification) {
  if (!is_recording_)
    return;
  is_recording_ = false;
  DisableRecording(
      base::Bind(&DevToolsTracingHandler::BeginReadingRecordingResult,
                 weak_factory_.GetWeakPtr()));
}

}  // namespace content
<|endoftext|>


<commit_before>
#include "FlareCargoInfo.h"

#include "../../Flare.h"
#include "../../Game/FlareGame.h"

#include "../../Economy/FlareCargoBay.h"

#include "../../Player/FlareMenuManager.h"
#include "../../Player/FlarePlayerController.h"

#define LOCTEXT_NAMESPACE "FlareCargoInfo"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareCargoInfo::Construct(const FArguments& InArgs)
{
	// Params
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	TargetSpacecraft = InArgs._Spacecraft;
	CargoIndex = InArgs._CargoIndex;
	OnClicked = InArgs._OnClicked;
	TSharedPtr<SButton> Button;

	// Layout
	ChildSlot
	.HAlign(HAlign_Left)
	.VAlign(VAlign_Top)
	.Padding(FMargin(1))
	[
		SNew(SVerticalBox)

		// Trade permission
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			SAssignNew(PermissionButton, SFlareButton)
			.Transparent(true)
			.Toggle(true)
			.Small(true)
			.Text(LOCTEXT("PermissionButton", "Trade"))
			.HelpText(LOCTEXT("PermissionButtonHelp", "Set whether resources in this cargo slot can be traded with other companies"))
			.OnClicked(this, &SFlareCargoInfo::OnPermissionClicked)
			.Visibility(this, &SFlareCargoInfo::GetPermissionVisibility)
			.Width(1.5)
		]

		// Main
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			// Button (behaviour only, no display)
			SAssignNew(Button, SButton)
			.OnClicked(this, &SFlareCargoInfo::OnButtonClicked)
			.ContentPadding(FMargin(0))
			.ButtonStyle(FCoreStyle::Get(), "NoBorder")
			[
				SNew(SBorder)
				.Padding(FMargin(0))
				.BorderImage(this, &SFlareCargoInfo::GetResourceIcon)
				[
					SNew(SBox)
					.WidthOverride(Theme.ResourceWidth)
					.HeightOverride(Theme.ResourceHeight)
					.Padding(FMargin(0))
					[
						SNew(SVerticalBox)

						// Resource name
						+ SVerticalBox::Slot()
						.Padding(Theme.SmallContentPadding)
						[
							SNew(STextBlock)
							.TextStyle(&Theme.TextFont)
							.Text(this, &SFlareCargoInfo::GetResourceAcronym)
						]

						// Resource quantity
						+ SVerticalBox::Slot()
						.AutoHeight()
						.Padding(Theme.SmallContentPadding)
						.VAlign(VAlign_Bottom)
						.HAlign(HAlign_Right)
						[
							SNew(STextBlock)
							.TextStyle(&Theme.SmallFont)
							.Text(this, &SFlareCargoInfo::GetResourceQuantity)
						]
					]
				]
			]
		]

		// Dump
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			SAssignNew(DumpButton, SFlareButton)
			.Transparent(true)
			.Text(FText())
			.HelpText(LOCTEXT("DumpResourceHelp", "Dump this resource"))
			.Icon(FFlareStyleSet::GetIcon("Dump"))
			.OnClicked(this, &SFlareCargoInfo::OnDumpClicked)
			.Width(1)
		]
	];

	// Initial state of cargo slot
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return;
	}
	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);
	PermissionButton->SetActive(Cargo->Restriction == EFlareResourceRestriction::Everybody);

	// Don't intercept clicks if it's not interactive
	if (!OnClicked.IsBound())
	{
		Button->SetVisibility(EVisibility::HitTestInvisible);
	}
	DumpButton->SetVisibility(EVisibility::Collapsed);
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareCargoInfo::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseEnter(MyGeometry, MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();

	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return;
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);

	// Tooltip
	if (MenuManager)
	{
		FText TitleText = Cargo->Resource ? Cargo->Resource->Name : LOCTEXT("EmptyTitle", "Empty bay");
		FText InfoText = Cargo->Resource ? Cargo->Resource->Description : LOCTEXT("EmptyInfo", "This cargo bay is empty.");
		MenuManager->ShowTooltip(this, FText::Format(LOCTEXT("CargoBayFormat", "Cargo bay : {0}"), TitleText), InfoText);
	}

	// Dump button
	bool CanDump = Cargo->Resource && Cargo->Quantity > 0 && TargetSpacecraft->GetCompany() == MenuManager->GetPC()->GetCompany();
	DumpButton->SetVisibility(CanDump ? EVisibility::Visible : EVisibility::Collapsed);
}

void SFlareCargoInfo::OnMouseLeave(const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseLeave(MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (MenuManager)
	{
		MenuManager->HideTooltip(this);
	}

	DumpButton->SetVisibility(EVisibility::Collapsed);
}

const FSlateBrush* SFlareCargoInfo::GetResourceIcon() const
{
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return NULL;
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);

	if (Cargo->Resource)
	{
		return &Cargo->Resource->Icon;
	}
	else
	{
		const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
		return &Theme.ResourceBackground;
	}
}

FText SFlareCargoInfo::GetResourceAcronym() const
{
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return FText();
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);

	if (Cargo->Resource)
	{
		return Cargo->Resource->Acronym;
	}
	else
	{
		return FText();
	}
}

FText SFlareCargoInfo::GetResourceQuantity() const
{
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return FText();
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);

	// Print IO text if any
	FText LockText;
	if (Cargo->Lock == EFlareResourceLock::Output)
	{
		LockText = FText::Format(LOCTEXT("OutputCargoFormat", "(Output)\n"), Cargo->Resource->Acronym);
	}
	else if (Cargo->Lock == EFlareResourceLock::Input)
	{
		LockText = FText::Format(LOCTEXT("InputCargoFormat", "(Input)\n"), Cargo->Resource->Acronym);
	}
	else if (Cargo->Lock == EFlareResourceLock::Trade)
	{
		LockText = FText::Format(LOCTEXT("TradeCargoFormat", "(Trade)\n"), Cargo->Resource->Acronym);
	}
	else if (Cargo->Lock == EFlareResourceLock::Hidden)
	{
		LockText = FText::Format(LOCTEXT("HiddenCargoFormat", "(Hidden)\n"), Cargo->Resource->Acronym);
	}

	// Format the current capacity info
	int32 Capacity = TargetSpacecraft->GetActiveCargoBay()->GetSlotCapacity();

	if (Capacity > 999)
	{
		FNumberFormattingOptions CargoFormat;
		CargoFormat.MaximumFractionalDigits = 1;

		return FText::Format(FText::FromString("{0} {1}/{2}k"),
			LockText,
			FText::AsNumber(Cargo->Quantity, &CargoFormat),
			FText::AsNumber(Capacity / 1000.0f, &CargoFormat));
	}
	else
	{
		return FText::Format(FText::FromString("{0} {1}/{2}"),
			LockText,
			FText::AsNumber(Cargo->Quantity),
			FText::AsNumber(Capacity));
	}
}

FReply SFlareCargoInfo::OnButtonClicked()
{
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return FReply::Handled();
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);

	if (Cargo && Cargo->Resource && Cargo->Quantity > 0)
	{
		OnClicked.ExecuteIfBound();
	}

	return FReply::Handled();
}

void SFlareCargoInfo::OnDumpClicked()
{
	AFlareMenuManager::GetSingleton()->Confirm(LOCTEXT("ConfirmDump", "ARE YOU SURE ?"),
		LOCTEXT("ConfirmDumpInfo", "Do you really want to dump this cargo slot ?"),
		FSimpleDelegate::CreateSP(this, &SFlareCargoInfo::OnDumpConfirmed));
}

void SFlareCargoInfo::OnDumpConfirmed()
{
	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return;
	}
	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);

	if (Cargo && Cargo->Resource)
	{
		MenuManager->GetPC()->ClientPlaySound(MenuManager->GetPC()->GetSoundManager()->DeleteSound);
		TargetSpacecraft->GetActiveCargoBay()->DumpCargo(Cargo);
	}
}

void SFlareCargoInfo::OnPermissionClicked()
{
	TargetSpacecraft->GetActiveCargoBay()->SetSlotRestriction(
		CargoIndex,
		PermissionButton->IsActive() ? EFlareResourceRestriction::Everybody : EFlareResourceRestriction::OwnerOnly);
}

EVisibility SFlareCargoInfo::GetPermissionVisibility() const
{
	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();

	if (IsEnabled() && IsValid(TargetSpacecraft)
	 && TargetSpacecraft->IsStation()
	 && TargetSpacecraft->GetCompany() == MenuManager->GetPC()->GetCompany()
	 && MenuManager->GetCurrentMenu() != EFlareMenu::MENU_Trade)
	{
		return EVisibility::Visible;
	}
	else
	{
		return EVisibility::Collapsed;
	}
}

#undef LOCTEXT_NAMESPACE
<commit_msg>Fix crash while trading resources<commit_after>
#include "FlareCargoInfo.h"

#include "../../Flare.h"
#include "../../Game/FlareGame.h"

#include "../../Economy/FlareCargoBay.h"

#include "../../Player/FlareMenuManager.h"
#include "../../Player/FlarePlayerController.h"

#define LOCTEXT_NAMESPACE "FlareCargoInfo"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareCargoInfo::Construct(const FArguments& InArgs)
{
	// Params
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	TargetSpacecraft = InArgs._Spacecraft;
	CargoIndex = InArgs._CargoIndex;
	OnClicked = InArgs._OnClicked;
	TSharedPtr<SButton> Button;

	// Layout
	ChildSlot
	.HAlign(HAlign_Left)
	.VAlign(VAlign_Top)
	.Padding(FMargin(1))
	[
		SNew(SVerticalBox)

		// Trade permission
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			SAssignNew(PermissionButton, SFlareButton)
			.Transparent(true)
			.Toggle(true)
			.Small(true)
			.Text(LOCTEXT("PermissionButton", "Trade"))
			.HelpText(LOCTEXT("PermissionButtonHelp", "Set whether resources in this cargo slot can be traded with other companies"))
			.OnClicked(this, &SFlareCargoInfo::OnPermissionClicked)
			.Visibility(this, &SFlareCargoInfo::GetPermissionVisibility)
			.Width(1.5)
		]

		// Main
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			// Button (behaviour only, no display)
			SAssignNew(Button, SButton)
			.OnClicked(this, &SFlareCargoInfo::OnButtonClicked)
			.ContentPadding(FMargin(0))
			.ButtonStyle(FCoreStyle::Get(), "NoBorder")
			[
				SNew(SBorder)
				.Padding(FMargin(0))
				.BorderImage(this, &SFlareCargoInfo::GetResourceIcon)
				[
					SNew(SBox)
					.WidthOverride(Theme.ResourceWidth)
					.HeightOverride(Theme.ResourceHeight)
					.Padding(FMargin(0))
					[
						SNew(SVerticalBox)

						// Resource name
						+ SVerticalBox::Slot()
						.Padding(Theme.SmallContentPadding)
						[
							SNew(STextBlock)
							.TextStyle(&Theme.TextFont)
							.Text(this, &SFlareCargoInfo::GetResourceAcronym)
						]

						// Resource quantity
						+ SVerticalBox::Slot()
						.AutoHeight()
						.Padding(Theme.SmallContentPadding)
						.VAlign(VAlign_Bottom)
						.HAlign(HAlign_Right)
						[
							SNew(STextBlock)
							.TextStyle(&Theme.SmallFont)
							.Text(this, &SFlareCargoInfo::GetResourceQuantity)
						]
					]
				]
			]
		]

		// Dump
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			SAssignNew(DumpButton, SFlareButton)
			.Transparent(true)
			.Text(FText())
			.HelpText(LOCTEXT("DumpResourceHelp", "Dump this resource"))
			.Icon(FFlareStyleSet::GetIcon("Dump"))
			.OnClicked(this, &SFlareCargoInfo::OnDumpClicked)
			.Width(1)
		]
	];

	// Initial state of cargo slot
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return;
	}
	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);
	PermissionButton->SetActive(Cargo->Restriction == EFlareResourceRestriction::Everybody);

	// Don't intercept clicks if it's not interactive
	if (!OnClicked.IsBound())
	{
		Button->SetVisibility(EVisibility::HitTestInvisible);
	}
	DumpButton->SetVisibility(EVisibility::Collapsed);
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareCargoInfo::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseEnter(MyGeometry, MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();

	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return;
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);

	// Tooltip
	if (MenuManager)
	{
		FText TitleText = Cargo->Resource ? Cargo->Resource->Name : LOCTEXT("EmptyTitle", "Empty bay");
		FText InfoText = Cargo->Resource ? Cargo->Resource->Description : LOCTEXT("EmptyInfo", "This cargo bay is empty.");
		MenuManager->ShowTooltip(this, FText::Format(LOCTEXT("CargoBayFormat", "Cargo bay : {0}"), TitleText), InfoText);
	}

	// Dump button
	bool CanDump = Cargo->Resource && Cargo->Quantity > 0 && TargetSpacecraft->GetCompany() == MenuManager->GetPC()->GetCompany();
	DumpButton->SetVisibility(CanDump ? EVisibility::Visible : EVisibility::Collapsed);
}

void SFlareCargoInfo::OnMouseLeave(const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseLeave(MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (MenuManager)
	{
		MenuManager->HideTooltip(this);
	}

	DumpButton->SetVisibility(EVisibility::Collapsed);
}

const FSlateBrush* SFlareCargoInfo::GetResourceIcon() const
{
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return NULL;
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);

	if (Cargo->Resource)
	{
		return &Cargo->Resource->Icon;
	}
	else
	{
		const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
		return &Theme.ResourceBackground;
	}
}

FText SFlareCargoInfo::GetResourceAcronym() const
{
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return FText();
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);

	if (Cargo->Resource)
	{
		return Cargo->Resource->Acronym;
	}
	else
	{
		return FText();
	}
}

FText SFlareCargoInfo::GetResourceQuantity() const
{
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return FText();
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);
	FCHECK(Cargo);

	// Print IO text if any
	FText LockText;
	if (Cargo->Lock == EFlareResourceLock::Output)
	{
		LockText = LOCTEXT("OutputCargoFormat", "(Output)\n");
	}
	else if (Cargo->Lock == EFlareResourceLock::Input)
	{
		LockText = LOCTEXT("InputCargoFormat", "(Input)\n");
	}
	else if (Cargo->Lock == EFlareResourceLock::Trade)
	{
		LockText = LOCTEXT("TradeCargoFormat", "(Trade)\n");
	}
	else if (Cargo->Lock == EFlareResourceLock::Hidden)
	{
		LockText = LOCTEXT("HiddenCargoFormat", "(Hidden)\n");
	}

	// Format the current capacity info
	int32 Capacity = TargetSpacecraft->GetActiveCargoBay()->GetSlotCapacity();

	if (Capacity > 999)
	{
		FNumberFormattingOptions CargoFormat;
		CargoFormat.MaximumFractionalDigits = 1;

		return FText::Format(FText::FromString("{0} {1}/{2}k"),
			LockText,
			FText::AsNumber(Cargo->Quantity, &CargoFormat),
			FText::AsNumber(Capacity / 1000.0f, &CargoFormat));
	}
	else
	{
		return FText::Format(FText::FromString("{0} {1}/{2}"),
			LockText,
			FText::AsNumber(Cargo->Quantity),
			FText::AsNumber(Capacity));
	}
}

FReply SFlareCargoInfo::OnButtonClicked()
{
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return FReply::Handled();
	}

	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);

	if (Cargo && Cargo->Resource && Cargo->Quantity > 0)
	{
		OnClicked.ExecuteIfBound();
	}

	return FReply::Handled();
}

void SFlareCargoInfo::OnDumpClicked()
{
	AFlareMenuManager::GetSingleton()->Confirm(LOCTEXT("ConfirmDump", "ARE YOU SURE ?"),
		LOCTEXT("ConfirmDumpInfo", "Do you really want to dump this cargo slot ?"),
		FSimpleDelegate::CreateSP(this, &SFlareCargoInfo::OnDumpConfirmed));
}

void SFlareCargoInfo::OnDumpConfirmed()
{
	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (TargetSpacecraft->GetActiveCargoBay()->GetSlotCount() <= CargoIndex)
	{
		return;
	}
	FFlareCargo* Cargo = TargetSpacecraft->GetActiveCargoBay()->GetSlot(CargoIndex);

	if (Cargo && Cargo->Resource)
	{
		MenuManager->GetPC()->ClientPlaySound(MenuManager->GetPC()->GetSoundManager()->DeleteSound);
		TargetSpacecraft->GetActiveCargoBay()->DumpCargo(Cargo);
	}
}

void SFlareCargoInfo::OnPermissionClicked()
{
	TargetSpacecraft->GetActiveCargoBay()->SetSlotRestriction(
		CargoIndex,
		PermissionButton->IsActive() ? EFlareResourceRestriction::Everybody : EFlareResourceRestriction::OwnerOnly);
}

EVisibility SFlareCargoInfo::GetPermissionVisibility() const
{
	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();

	if (IsEnabled() && IsValid(TargetSpacecraft)
	 && TargetSpacecraft->IsStation()
	 && TargetSpacecraft->GetCompany() == MenuManager->GetPC()->GetCompany()
	 && MenuManager->GetCurrentMenu() != EFlareMenu::MENU_Trade)
	{
		return EVisibility::Visible;
	}
	else
	{
		return EVisibility::Collapsed;
	}
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>
#include "../../Flare.h"
#include "FlareCargoInfo.h"
#include "../../Player/FlareMenuManager.h"
#include "../../Player/FlarePlayerController.h"
#include "../../Economy/FlareCargoBay.h"

#define LOCTEXT_NAMESPACE "FlareCargoInfo"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareCargoInfo::Construct(const FArguments& InArgs)
{
	// Params
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	TargetSpacecraft = InArgs._Spacecraft;
	CargoIndex = InArgs._CargoIndex;
	OnClicked = InArgs._OnClicked;
	TSharedPtr<SButton> Button;

	// Layout
	ChildSlot
	.HAlign(HAlign_Left)
	.VAlign(VAlign_Top)
	.Padding(FMargin(1))
	[
		SNew(SVerticalBox)

		// Trade permission
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			SAssignNew(PermissionButton, SFlareButton)
			.Transparent(true)
			.Toggle(true)
			.SmallToggleIcons(true)
			.Text(LOCTEXT("PermissionButton", "Trade"))
			.HelpText(LOCTEXT("PermissionButtonHelp", "Set whether resources in this cargo slot can be traded with other companies"))
			.OnClicked(this, &SFlareCargoInfo::OnPermissionClicked)
			.Visibility(this, &SFlareCargoInfo::GetPermissionVisibility)
			.Width(1.5)
		]

		// Main
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			// Button (behaviour only, no display)
			SAssignNew(Button, SButton)
			.OnClicked(this, &SFlareCargoInfo::OnButtonClicked)
			.ContentPadding(FMargin(0))
			.ButtonStyle(FCoreStyle::Get(), "NoBorder")
			[
				SNew(SBorder)
				.Padding(FMargin(0))
				.BorderImage(this, &SFlareCargoInfo::GetResourceIcon)
				[
					SNew(SBox)
					.WidthOverride(Theme.ResourceWidth)
					.HeightOverride(Theme.ResourceHeight)
					.Padding(FMargin(0))
					[
						SNew(SVerticalBox)

						// Resource name
						+ SVerticalBox::Slot()
						.Padding(Theme.SmallContentPadding)
						[
							SNew(STextBlock)
							.TextStyle(&Theme.TextFont)
							.Text(this, &SFlareCargoInfo::GetResourceAcronym)
						]

						// Resource quantity
						+ SVerticalBox::Slot()
						.AutoHeight()
						.Padding(Theme.SmallContentPadding)
						.VAlign(VAlign_Bottom)
						.HAlign(HAlign_Right)
						[
							SNew(STextBlock)
							.TextStyle(&Theme.SmallFont)
							.Text(this, &SFlareCargoInfo::GetResourceQuantity)
						]
					]
				]
			]
		]

		// Dump
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			SAssignNew(DumpButton, SFlareButton)
			.Transparent(true)
			.Text(FText())
			.HelpText(LOCTEXT("DumpResourceHelp", "Dump this resource"))
			.Icon(FFlareStyleSet::GetIcon("Stop"))
			.OnClicked(this, &SFlareCargoInfo::OnDumpClicked)
			.Width(1)
		]
	];

	// Initial state of cargo slot
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);
	PermissionButton->SetActive(Cargo->Restriction == EFlareResourceRestriction::Everybody);

	// Don't intercept clicks if it's not interactive
	if (!OnClicked.IsBound())
	{
		Button->SetVisibility(EVisibility::HitTestInvisible);
	}
	DumpButton->SetVisibility(EVisibility::Collapsed);
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareCargoInfo::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseEnter(MyGeometry, MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);

	// Tooltip
	if (MenuManager)
	{
		FText TitleText = Cargo->Resource ? Cargo->Resource->Name : LOCTEXT("EmptyTitle", "Empty bay");
		FText InfoText = Cargo->Resource ? Cargo->Resource->Description : LOCTEXT("EmptyInfo", "This cargo bay is empty.");
		MenuManager->ShowTooltip(this, FText::Format(LOCTEXT("CargoBayFormat", "Cargo bay : {0}"), TitleText), InfoText);
	}

	// Dump button
	bool CanDump = Cargo->Resource && Cargo->Quantity > 0 && TargetSpacecraft->GetCompany() == MenuManager->GetPC()->GetCompany();
	DumpButton->SetVisibility(CanDump ? EVisibility::Visible : EVisibility::Collapsed);
}

void SFlareCargoInfo::OnMouseLeave(const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseLeave(MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (MenuManager)
	{
		MenuManager->HideTooltip(this);
	}

	DumpButton->SetVisibility(EVisibility::Collapsed);
}

const FSlateBrush* SFlareCargoInfo::GetResourceIcon() const
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);

	if (Cargo->Resource)
	{
		return &Cargo->Resource->Icon;
	}
	else
	{
		const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
		return &Theme.ResourceBackground;
	}
}

FText SFlareCargoInfo::GetResourceAcronym() const
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);

	if (Cargo->Resource)
	{
		return Cargo->Resource->Acronym;
	}
	else
	{
		return LOCTEXT("Empty", " ");
	}
}

FText SFlareCargoInfo::GetResourceQuantity() const
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);

	// Print IO text if any
	FText LockText;
	if (Cargo->Lock == EFlareResourceLock::Output)
	{
		LockText = FText::Format(LOCTEXT("OutputCargoFormat", "(Output)\n"), Cargo->Resource->Acronym);
	}
	else if (Cargo->Lock == EFlareResourceLock::Input)
	{
		LockText = FText::Format(LOCTEXT("InputCargoFormat", "(Input)\n"), Cargo->Resource->Acronym);
	}
	// TODO Trade

	// Format the current capacity info
	if (Cargo->Capacity > 999)
	{
		FNumberFormattingOptions CargoFormat;
		CargoFormat.MaximumFractionalDigits = 1;

		return FText::Format(FText::FromString("{0} {1}/{2}k"),
			LockText,
			FText::AsNumber(Cargo->Quantity, &CargoFormat),
			FText::AsNumber(Cargo->Capacity / 1000.0f, &CargoFormat));
	}
	else
	{
		return FText::Format(FText::FromString("{0} {1}/{2}"),
			LockText,
			FText::AsNumber(Cargo->Quantity),
			FText::AsNumber(Cargo->Capacity));
	}
}

FReply SFlareCargoInfo::OnButtonClicked()
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);

	if (Cargo && Cargo->Resource && Cargo->Quantity > 0)
	{
		OnClicked.ExecuteIfBound();
	}

	return FReply::Handled();
}

void SFlareCargoInfo::OnDumpClicked()
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);

	if (Cargo && Cargo->Resource)
	{
		TargetSpacecraft->GetCargoBay()->DumpCargo(Cargo);
	}
}

void SFlareCargoInfo::OnPermissionClicked()
{
	TargetSpacecraft->GetCargoBay()->SetSlotRestriction(
		CargoIndex,
		PermissionButton->IsActive() ? EFlareResourceRestriction::Everybody : EFlareResourceRestriction::Nobody);
}

EVisibility SFlareCargoInfo::GetPermissionVisibility() const
{
	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();

	if (TargetSpacecraft->IsStation()
	 && TargetSpacecraft->GetCompany() == TargetSpacecraft->GetGame()->GetPC()->GetCompany()
	 && MenuManager->GetCurrentMenu() != EFlareMenu::MENU_Trade)
	{
		return EVisibility::Visible;
	}
	else
	{
		return EVisibility::Collapsed;
	}
}

#undef LOCTEXT_NAMESPACE
<commit_msg>Fix cargo bay capacity display with station with high level<commit_after>
#include "../../Flare.h"
#include "FlareCargoInfo.h"
#include "../../Player/FlareMenuManager.h"
#include "../../Player/FlarePlayerController.h"
#include "../../Economy/FlareCargoBay.h"

#define LOCTEXT_NAMESPACE "FlareCargoInfo"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareCargoInfo::Construct(const FArguments& InArgs)
{
	// Params
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	TargetSpacecraft = InArgs._Spacecraft;
	CargoIndex = InArgs._CargoIndex;
	OnClicked = InArgs._OnClicked;
	TSharedPtr<SButton> Button;

	// Layout
	ChildSlot
	.HAlign(HAlign_Left)
	.VAlign(VAlign_Top)
	.Padding(FMargin(1))
	[
		SNew(SVerticalBox)

		// Trade permission
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			SAssignNew(PermissionButton, SFlareButton)
			.Transparent(true)
			.Toggle(true)
			.SmallToggleIcons(true)
			.Text(LOCTEXT("PermissionButton", "Trade"))
			.HelpText(LOCTEXT("PermissionButtonHelp", "Set whether resources in this cargo slot can be traded with other companies"))
			.OnClicked(this, &SFlareCargoInfo::OnPermissionClicked)
			.Visibility(this, &SFlareCargoInfo::GetPermissionVisibility)
			.Width(1.5)
		]

		// Main
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			// Button (behaviour only, no display)
			SAssignNew(Button, SButton)
			.OnClicked(this, &SFlareCargoInfo::OnButtonClicked)
			.ContentPadding(FMargin(0))
			.ButtonStyle(FCoreStyle::Get(), "NoBorder")
			[
				SNew(SBorder)
				.Padding(FMargin(0))
				.BorderImage(this, &SFlareCargoInfo::GetResourceIcon)
				[
					SNew(SBox)
					.WidthOverride(Theme.ResourceWidth)
					.HeightOverride(Theme.ResourceHeight)
					.Padding(FMargin(0))
					[
						SNew(SVerticalBox)

						// Resource name
						+ SVerticalBox::Slot()
						.Padding(Theme.SmallContentPadding)
						[
							SNew(STextBlock)
							.TextStyle(&Theme.TextFont)
							.Text(this, &SFlareCargoInfo::GetResourceAcronym)
						]

						// Resource quantity
						+ SVerticalBox::Slot()
						.AutoHeight()
						.Padding(Theme.SmallContentPadding)
						.VAlign(VAlign_Bottom)
						.HAlign(HAlign_Right)
						[
							SNew(STextBlock)
							.TextStyle(&Theme.SmallFont)
							.Text(this, &SFlareCargoInfo::GetResourceQuantity)
						]
					]
				]
			]
		]

		// Dump
		+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(FMargin(0))
		[
			SAssignNew(DumpButton, SFlareButton)
			.Transparent(true)
			.Text(FText())
			.HelpText(LOCTEXT("DumpResourceHelp", "Dump this resource"))
			.Icon(FFlareStyleSet::GetIcon("Stop"))
			.OnClicked(this, &SFlareCargoInfo::OnDumpClicked)
			.Width(1)
		]
	];

	// Initial state of cargo slot
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);
	PermissionButton->SetActive(Cargo->Restriction == EFlareResourceRestriction::Everybody);

	// Don't intercept clicks if it's not interactive
	if (!OnClicked.IsBound())
	{
		Button->SetVisibility(EVisibility::HitTestInvisible);
	}
	DumpButton->SetVisibility(EVisibility::Collapsed);
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareCargoInfo::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseEnter(MyGeometry, MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);

	// Tooltip
	if (MenuManager)
	{
		FText TitleText = Cargo->Resource ? Cargo->Resource->Name : LOCTEXT("EmptyTitle", "Empty bay");
		FText InfoText = Cargo->Resource ? Cargo->Resource->Description : LOCTEXT("EmptyInfo", "This cargo bay is empty.");
		MenuManager->ShowTooltip(this, FText::Format(LOCTEXT("CargoBayFormat", "Cargo bay : {0}"), TitleText), InfoText);
	}

	// Dump button
	bool CanDump = Cargo->Resource && Cargo->Quantity > 0 && TargetSpacecraft->GetCompany() == MenuManager->GetPC()->GetCompany();
	DumpButton->SetVisibility(CanDump ? EVisibility::Visible : EVisibility::Collapsed);
}

void SFlareCargoInfo::OnMouseLeave(const FPointerEvent& MouseEvent)
{
	SWidget::OnMouseLeave(MouseEvent);

	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();
	if (MenuManager)
	{
		MenuManager->HideTooltip(this);
	}

	DumpButton->SetVisibility(EVisibility::Collapsed);
}

const FSlateBrush* SFlareCargoInfo::GetResourceIcon() const
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);

	if (Cargo->Resource)
	{
		return &Cargo->Resource->Icon;
	}
	else
	{
		const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
		return &Theme.ResourceBackground;
	}
}

FText SFlareCargoInfo::GetResourceAcronym() const
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);

	if (Cargo->Resource)
	{
		return Cargo->Resource->Acronym;
	}
	else
	{
		return LOCTEXT("Empty", " ");
	}
}

FText SFlareCargoInfo::GetResourceQuantity() const
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);
	check(Cargo);

	// Print IO text if any
	FText LockText;
	if (Cargo->Lock == EFlareResourceLock::Output)
	{
		LockText = FText::Format(LOCTEXT("OutputCargoFormat", "(Output)\n"), Cargo->Resource->Acronym);
	}
	else if (Cargo->Lock == EFlareResourceLock::Input)
	{
		LockText = FText::Format(LOCTEXT("InputCargoFormat", "(Input)\n"), Cargo->Resource->Acronym);
	}
	// TODO Trade

	// Format the current capacity info
	int32 Capacity = TargetSpacecraft->GetCargoBay()->GetSlotCapacity();

	if (Capacity > 999)
	{
		FNumberFormattingOptions CargoFormat;
		CargoFormat.MaximumFractionalDigits = 1;

		return FText::Format(FText::FromString("{0} {1}/{2}k"),
			LockText,
			FText::AsNumber(Cargo->Quantity, &CargoFormat),
			FText::AsNumber(Capacity / 1000.0f, &CargoFormat));
	}
	else
	{
		return FText::Format(FText::FromString("{0} {1}/{2}"),
			LockText,
			FText::AsNumber(Cargo->Quantity),
			FText::AsNumber(Capacity));
	}
}

FReply SFlareCargoInfo::OnButtonClicked()
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);

	if (Cargo && Cargo->Resource && Cargo->Quantity > 0)
	{
		OnClicked.ExecuteIfBound();
	}

	return FReply::Handled();
}

void SFlareCargoInfo::OnDumpClicked()
{
	FFlareCargo* Cargo = TargetSpacecraft->GetCargoBay()->GetSlot(CargoIndex);

	if (Cargo && Cargo->Resource)
	{
		TargetSpacecraft->GetCargoBay()->DumpCargo(Cargo);
	}
}

void SFlareCargoInfo::OnPermissionClicked()
{
	TargetSpacecraft->GetCargoBay()->SetSlotRestriction(
		CargoIndex,
		PermissionButton->IsActive() ? EFlareResourceRestriction::Everybody : EFlareResourceRestriction::Nobody);
}

EVisibility SFlareCargoInfo::GetPermissionVisibility() const
{
	AFlareMenuManager* MenuManager = AFlareMenuManager::GetSingleton();

	if (TargetSpacecraft->IsStation()
	 && TargetSpacecraft->GetCompany() == TargetSpacecraft->GetGame()->GetPC()->GetCompany()
	 && MenuManager->GetCurrentMenu() != EFlareMenu::MENU_Trade)
	{
		return EVisibility::Visible;
	}
	else
	{
		return EVisibility::Collapsed;
	}
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>// ================================================================================
// ==      This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås      ==
// ==                     See tb_core.h for more information.                    ==
// ================================================================================

#include "tb_tab_container.h"
#include <assert.h>

namespace tb {

// == TBTabLayout =======================================================================

void TBTabLayout::OnChildAdded(TBWidget *child)
{
    if (TBButton *button = TBSafeCast<TBButton>(child))
    {
        button->SetSqueezable(true);
        button->SetSkinBg(TBIDC("TBTabContainer.tab"));
        button->SetID(TBIDC("tab"));
    }
}

PreferredSize TBTabLayout::OnCalculatePreferredContentSize(const SizeConstraints &constraints)
{
    PreferredSize ps = TBLayout::OnCalculatePreferredContentSize(constraints);
    // Make sure the number of tabs doesn't grow parents.
    // It is only the content that should do that. The tabs
    // will scroll anyway.
    if (GetAxis() == AXIS_X)
        ps.min_w = MIN(ps.min_w, 1);
    else
        ps.min_h = MIN(ps.min_h, 1);
    return ps;
}

// == TBTabContainer ====================================================================

TBTabContainer::TBTabContainer()
    : m_need_page_update(true)
    , m_current_page(-1)
    , m_align(TB_ALIGN_TOP)
{
    AddChild(&m_root_layout);
    // Put the tab layout on top of the content in Z order so their skin can make
    // a seamless overlap over the border. Control which side they are layouted
    // to by calling SetLayoutOrder.
    m_root_layout.AddChild(&m_content_root);
    m_root_layout.AddChild(&m_tab_layout);
    m_root_layout.SetAxis(AXIS_Y);
    m_root_layout.SetGravity(WIDGET_GRAVITY_ALL);
    m_root_layout.SetLayoutDistribution(LAYOUT_DISTRIBUTION_AVAILABLE);
    m_root_layout.SetLayoutOrder(LAYOUT_ORDER_TOP_TO_BOTTOM);
    m_root_layout.SetSkinBg(TBIDC("TBTabContainer.rootlayout"));
    m_root_layout.SetID("root_layout");

    m_tab_layout.SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_CENTER);
    m_tab_layout.SetSkinBg(TBIDC("TBTabContainer.tablayout_x"));
    m_tab_layout.SetLayoutPosition(LAYOUT_POSITION_RIGHT_BOTTOM);
    m_tab_layout.SetID("tab_layout");

    m_content_root.SetGravity(WIDGET_GRAVITY_ALL);
    m_content_root.SetSkinBg(TBIDC("TBTabContainer.container"));
    m_content_root.SetID("content_root");
}

TBTabContainer::~TBTabContainer()
{
    m_root_layout.RemoveChild(&m_content_root);
    m_root_layout.RemoveChild(&m_tab_layout);
    RemoveChild(&m_root_layout);
}

void TBTabContainer::SetAxis(AXIS axis)
{
    m_root_layout.SetAxis(axis);
    m_tab_layout.SetAxis(axis == AXIS_X ? AXIS_Y : AXIS_X);
    m_tab_layout.SetSkinBg(axis == AXIS_X ? TBIDC("TBTabContainer.tablayout_y") :
                                            TBIDC("TBTabContainer.tablayout_x"));
}

void TBTabContainer::SetValue(int index)
{
    if (index == m_current_page || !GetNumPages())
        return;

    m_current_page = index;

    // Update the pages visibility and tabs pressed value.
    index = 0;
    TBWidget *page = m_content_root.GetFirstChild();
    TBWidget *tab = m_tab_layout.GetFirstChild();
    for (   ; page && tab; page = page->GetNext(), tab = tab->GetNext(), index++)
    {
        bool active = index == m_current_page;
        page->SetVisibilility(active ? WIDGET_VISIBILITY_VISIBLE : WIDGET_VISIBILITY_INVISIBLE);
        tab->SetValue(active ? 1 : 0);

        if (active)
        {
            if (page->GetVisibility() == WIDGET_VISIBILITY_GONE)
                continue;

            TBRect contentRect = m_content_root.GetRect();
            TBRect pageRect = page->GetRect();

            if (contentRect.w != pageRect.w || contentRect.h != pageRect.w)
            {
                contentRect.x = contentRect.y = 0;
                page->SetRect(contentRect);
            }
        }
    }

    TBWidgetEvent ev(EVENT_TYPE_TAB_CHANGED);
    InvokeEvent(ev);
}

int TBTabContainer::GetNumPages()
{
    int count = 0;
    for (TBWidget *tab = m_tab_layout.GetFirstChild(); tab; tab = tab->GetNext())
        count++;

    if (!count)
        m_current_page = -1;

    return count;
}

TBWidget *TBTabContainer::GetCurrentPageWidget() const
{
    if (m_current_page == -1)
        return nullptr;

    return m_content_root.GetChildFromIndex(m_current_page);
}

void TBTabContainer::SetAlignment(TB_ALIGN align)
{
    bool horizontal = (align == TB_ALIGN_TOP || align == TB_ALIGN_BOTTOM);
    bool reverse = (align == TB_ALIGN_TOP || align == TB_ALIGN_LEFT);
    SetAxis(horizontal ? AXIS_Y : AXIS_X);
    m_root_layout.SetLayoutOrder(reverse ? LAYOUT_ORDER_TOP_TO_BOTTOM : LAYOUT_ORDER_BOTTOM_TO_TOP);
    m_tab_layout.SetLayoutPosition(reverse ? LAYOUT_POSITION_RIGHT_BOTTOM : LAYOUT_POSITION_LEFT_TOP);
    m_align = align;
}

bool TBTabContainer::OnEvent(const TBWidgetEvent &ev)
{
    if ((ev.type == EVENT_TYPE_CLICK || ev.type == EVENT_TYPE_POINTER_DOWN) &&
            ev.target->GetID() == TBIDC("tab") &&
            ev.target->GetParent() == &m_tab_layout)
    {
        int clicked_index = m_tab_layout.GetIndexFromChild(ev.target);
        SetValue(clicked_index);
        return true;
    }
    return false;
}

void TBTabContainer::OnProcess()
{
    if (m_need_page_update)
    {
        m_need_page_update = false;
        // Force update value
        int current_page = m_current_page;
        m_current_page = -1;
        SetValue(current_page);
    }
}

}; // namespace tb
<commit_msg>Take padding into account for TabContainer<commit_after>// ================================================================================
// ==      This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås      ==
// ==                     See tb_core.h for more information.                    ==
// ================================================================================

#include "tb_tab_container.h"
#include <assert.h>

namespace tb {

// == TBTabLayout =======================================================================

void TBTabLayout::OnChildAdded(TBWidget *child)
{
    if (TBButton *button = TBSafeCast<TBButton>(child))
    {
        button->SetSqueezable(true);
        button->SetSkinBg(TBIDC("TBTabContainer.tab"));
        button->SetID(TBIDC("tab"));
    }
}

PreferredSize TBTabLayout::OnCalculatePreferredContentSize(const SizeConstraints &constraints)
{
    PreferredSize ps = TBLayout::OnCalculatePreferredContentSize(constraints);
    // Make sure the number of tabs doesn't grow parents.
    // It is only the content that should do that. The tabs
    // will scroll anyway.
    if (GetAxis() == AXIS_X)
        ps.min_w = MIN(ps.min_w, 1);
    else
        ps.min_h = MIN(ps.min_h, 1);
    return ps;
}

// == TBTabContainer ====================================================================

TBTabContainer::TBTabContainer()
    : m_need_page_update(true)
    , m_current_page(-1)
    , m_align(TB_ALIGN_TOP)
{
    AddChild(&m_root_layout);
    // Put the tab layout on top of the content in Z order so their skin can make
    // a seamless overlap over the border. Control which side they are layouted
    // to by calling SetLayoutOrder.
    m_root_layout.AddChild(&m_content_root);
    m_root_layout.AddChild(&m_tab_layout);
    m_root_layout.SetAxis(AXIS_Y);
    m_root_layout.SetGravity(WIDGET_GRAVITY_ALL);
    m_root_layout.SetLayoutDistribution(LAYOUT_DISTRIBUTION_AVAILABLE);
    m_root_layout.SetLayoutOrder(LAYOUT_ORDER_TOP_TO_BOTTOM);
    m_root_layout.SetSkinBg(TBIDC("TBTabContainer.rootlayout"));
    m_root_layout.SetID("root_layout");

    m_tab_layout.SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_CENTER);
    m_tab_layout.SetSkinBg(TBIDC("TBTabContainer.tablayout_x"));
    m_tab_layout.SetLayoutPosition(LAYOUT_POSITION_RIGHT_BOTTOM);
    m_tab_layout.SetID("tab_layout");

    m_content_root.SetGravity(WIDGET_GRAVITY_ALL);
    m_content_root.SetSkinBg(TBIDC("TBTabContainer.container"));
    m_content_root.SetID("content_root");
}

TBTabContainer::~TBTabContainer()
{
    m_root_layout.RemoveChild(&m_content_root);
    m_root_layout.RemoveChild(&m_tab_layout);
    RemoveChild(&m_root_layout);
}

void TBTabContainer::SetAxis(AXIS axis)
{
    m_root_layout.SetAxis(axis);
    m_tab_layout.SetAxis(axis == AXIS_X ? AXIS_Y : AXIS_X);
    m_tab_layout.SetSkinBg(axis == AXIS_X ? TBIDC("TBTabContainer.tablayout_y") :
                                            TBIDC("TBTabContainer.tablayout_x"));
}

void TBTabContainer::SetValue(int index)
{
    if (index == m_current_page || !GetNumPages())
        return;

    m_current_page = index;

    // Update the pages visibility and tabs pressed value.
    index = 0;
    TBWidget *page = m_content_root.GetFirstChild();
    TBWidget *tab = m_tab_layout.GetFirstChild();
    for (   ; page && tab; page = page->GetNext(), tab = tab->GetNext(), index++)
    {
        bool active = index == m_current_page;
        page->SetVisibilility(active ? WIDGET_VISIBILITY_VISIBLE : WIDGET_VISIBILITY_INVISIBLE);
        tab->SetValue(active ? 1 : 0);

        if (active)
        {
            if (page->GetVisibility() == WIDGET_VISIBILITY_GONE)
                continue;

            TBRect contentRect = m_content_root.GetRect();
            TBSkinElement* skin = m_content_root.GetSkinBgElement();
            contentRect = contentRect.Shrink(skin->padding_left, skin->padding_top, skin->padding_right, skin->padding_bottom);

            TBRect pageRect = page->GetRect();

            if (contentRect.w != pageRect.w || contentRect.h != pageRect.h)
            {
                contentRect.x = skin->padding_left;
                contentRect.y = skin->padding_right;
                page->SetRect(contentRect);
            }
        }
    }

    TBWidgetEvent ev(EVENT_TYPE_TAB_CHANGED);
    InvokeEvent(ev);
}

int TBTabContainer::GetNumPages()
{
    int count = 0;
    for (TBWidget *tab = m_tab_layout.GetFirstChild(); tab; tab = tab->GetNext())
        count++;

    if (!count)
        m_current_page = -1;

    return count;
}

TBWidget *TBTabContainer::GetCurrentPageWidget() const
{
    if (m_current_page == -1)
        return nullptr;

    return m_content_root.GetChildFromIndex(m_current_page);
}

void TBTabContainer::SetAlignment(TB_ALIGN align)
{
    bool horizontal = (align == TB_ALIGN_TOP || align == TB_ALIGN_BOTTOM);
    bool reverse = (align == TB_ALIGN_TOP || align == TB_ALIGN_LEFT);
    SetAxis(horizontal ? AXIS_Y : AXIS_X);
    m_root_layout.SetLayoutOrder(reverse ? LAYOUT_ORDER_TOP_TO_BOTTOM : LAYOUT_ORDER_BOTTOM_TO_TOP);
    m_tab_layout.SetLayoutPosition(reverse ? LAYOUT_POSITION_RIGHT_BOTTOM : LAYOUT_POSITION_LEFT_TOP);
    m_align = align;
}

bool TBTabContainer::OnEvent(const TBWidgetEvent &ev)
{
    if ((ev.type == EVENT_TYPE_CLICK || ev.type == EVENT_TYPE_POINTER_DOWN) &&
            ev.target->GetID() == TBIDC("tab") &&
            ev.target->GetParent() == &m_tab_layout)
    {
        int clicked_index = m_tab_layout.GetIndexFromChild(ev.target);
        SetValue(clicked_index);
        return true;
    }
    return false;
}

void TBTabContainer::OnProcess()
{
    if (m_need_page_update)
    {
        m_need_page_update = false;
        // Force update value
        int current_page = m_current_page;
        m_current_page = -1;
        SetValue(current_page);
    }
}

}; // namespace tb
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

//  Software Guide : BeginCommandLineArgs
//    INPUT: {ADS40RoiSmall.png}
//    OUTPUT: {TextureOutput.tif}, {pretty_TextureOutput.png}
//    2 1 1
//  Software Guide : EndCommandLineArgs

#include "itkExceptionObject.h"
#include "otbImage.h"
#include "itkVector.h"
#include "itkConstNeighborhoodIterator.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"

#include "otbTextureFunctors.h"
#include "otbFunctionWithNeighborhoodToImageFilter.h"
#include "otbTextureImageFunction.h"

int main(int argc, char * argv[])
{
  // Parse command line parameters
  if ( argc != 7 )
  {
    std::cerr << "Usage: " << argv[0] << " <inputImage> ";
    std::cerr << " <outputImage> <outputRescaled> ";
    std::cerr << " <radius> <xOffset> <yOffset> ";
    std::cerr << std::endl;
    return EXIT_FAILURE;
  }

  const char* infname   = argv[1];
  const char* outfname  = argv[2];
  const char* outprettyfname  = argv[3];

  const unsigned int radius  =  static_cast<unsigned int>(atoi(argv[4]));
  const unsigned int xOffset =  static_cast<unsigned int>(atoi(argv[5]));
  const unsigned int yOffset =  static_cast<unsigned int>(atoi(argv[6]));

  typedef double PixelType;
  const int Dimension = 2;
  typedef otb::Image<PixelType,Dimension> ImageType;
  typedef itk::ConstNeighborhoodIterator<ImageType>  IteratorType;
  typedef itk::Vector< PixelType > VectorType;

  typedef otb::Functor::ContrastTextureFunctor<PixelType, PixelType> FunctorType;

  typedef otb::TextureImageFunction<ImageType, FunctorType> FunctionType;
  typedef otb::FunctionWithNeighborhoodToImageFilter<ImageType,
                                          ImageType, FunctionType> FilterType;
  typedef ImageType::OffsetType OffsetType;
  typedef otb::ImageFileReader<ImageType>  ReaderType;
  typedef otb::ImageFileWriter<ImageType> WriterType;

  // Instantiating object
  FilterType::Pointer textureFilter = FilterType::New();
  ReaderType::Pointer reader  = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(infname);
  writer->SetFileName(outfname);

  textureFilter->SetInput(reader->GetOutput());
  ImageType::SizeType tRadius;
  tRadius[0] = radius;
  tRadius[1] = radius;
  textureFilter->SetRadius(tRadius);
  OffsetType offset;
  offset[0] =  xOffset;
  offset[1] =  yOffset;

  textureFilter->SetOffset(offset);
  writer->SetInput(textureFilter->GetOutput());

  writer->Update();

 // Pretty image creation for printing

  typedef otb::Image<unsigned char, Dimension>                                           OutputPrettyImageType;
  typedef otb::ImageFileWriter<OutputPrettyImageType>                                    WriterPrettyOutputType;
  typedef itk::RescaleIntensityImageFilter< ImageType, OutputPrettyImageType>      RescalerOutputType;

  RescalerOutputType::Pointer     outputRescaler     = RescalerOutputType::New();
  WriterPrettyOutputType::Pointer prettyOutputWriter = WriterPrettyOutputType::New();
  outputRescaler->SetInput( textureFilter->GetOutput() );
  outputRescaler->SetOutputMinimum(0);
  outputRescaler->SetOutputMaximum(255);
  prettyOutputWriter->SetFileName( outprettyfname );
  prettyOutputWriter->SetInput( outputRescaler->GetOutput() );

  prettyOutputWriter->Update();

  return EXIT_SUCCESS;
}
<commit_msg>ENH: remove useless type<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

//  Software Guide : BeginCommandLineArgs
//    INPUT: {ADS40RoiSmall.png}
//    OUTPUT: {TextureOutput.tif}, {pretty_TextureOutput.png}
//    2 1 1
//  Software Guide : EndCommandLineArgs

#include "itkExceptionObject.h"
#include "otbImage.h"
#include "itkVector.h"
#include "itkConstNeighborhoodIterator.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"

#include "otbTextureFunctors.h"
#include "otbFunctionWithNeighborhoodToImageFilter.h"
#include "otbTextureImageFunction.h"

int main(int argc, char * argv[])
{
  // Parse command line parameters
  if ( argc != 7 )
  {
    std::cerr << "Usage: " << argv[0] << " <inputImage> ";
    std::cerr << " <outputImage> <outputRescaled> ";
    std::cerr << " <radius> <xOffset> <yOffset> ";
    std::cerr << std::endl;
    return EXIT_FAILURE;
  }

  const char* infname   = argv[1];
  const char* outfname  = argv[2];
  const char* outprettyfname  = argv[3];

  const unsigned int radius  =  static_cast<unsigned int>(atoi(argv[4]));
  const unsigned int xOffset =  static_cast<unsigned int>(atoi(argv[5]));
  const unsigned int yOffset =  static_cast<unsigned int>(atoi(argv[6]));

  typedef double PixelType;
  const int Dimension = 2;
  typedef otb::Image<PixelType,Dimension> ImageType;
  typedef itk::ConstNeighborhoodIterator<ImageType>  IteratorType;

  typedef otb::Functor::ContrastTextureFunctor<PixelType, PixelType> FunctorType;
  typedef otb::TextureImageFunction<ImageType, FunctorType> FunctionType;
  typedef otb::FunctionWithNeighborhoodToImageFilter<ImageType,
                                          ImageType, FunctionType> FilterType;
  typedef ImageType::OffsetType OffsetType;
  typedef otb::ImageFileReader<ImageType>  ReaderType;
  typedef otb::ImageFileWriter<ImageType> WriterType;

  // Instantiating object
  FilterType::Pointer textureFilter = FilterType::New();
  ReaderType::Pointer reader  = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(infname);
  writer->SetFileName(outfname);

  textureFilter->SetInput(reader->GetOutput());
  ImageType::SizeType tRadius;
  tRadius[0] = radius;
  tRadius[1] = radius;
  textureFilter->SetRadius(tRadius);
  OffsetType offset;
  offset[0] =  xOffset;
  offset[1] =  yOffset;

  textureFilter->SetOffset(offset);
  writer->SetInput(textureFilter->GetOutput());

  writer->Update();

 // Pretty image creation for printing

  typedef otb::Image<unsigned char, Dimension>                                           OutputPrettyImageType;
  typedef otb::ImageFileWriter<OutputPrettyImageType>                                    WriterPrettyOutputType;
  typedef itk::RescaleIntensityImageFilter< ImageType, OutputPrettyImageType>      RescalerOutputType;

  RescalerOutputType::Pointer     outputRescaler     = RescalerOutputType::New();
  WriterPrettyOutputType::Pointer prettyOutputWriter = WriterPrettyOutputType::New();
  outputRescaler->SetInput( textureFilter->GetOutput() );
  outputRescaler->SetOutputMinimum(0);
  outputRescaler->SetOutputMaximum(255);
  prettyOutputWriter->SetFileName( outprettyfname );
  prettyOutputWriter->SetInput( outputRescaler->GetOutput() );

  prettyOutputWriter->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>