<commit_before>/*
 * Copyright (c) 2015-2016, Technische Universität Dresden, Germany
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
 *    and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef INCLUDE_NITRO_BROKEN_OPTIONS_PARSER_HPP
#define INCLUDE_NITRO_BROKEN_OPTIONS_PARSER_HPP

#include <nitro/broken_options/argument.hpp>
#include <nitro/broken_options/exception.hpp>
#include <nitro/broken_options/option/group.hpp>
#include <nitro/broken_options/option/multi_option.hpp>
#include <nitro/broken_options/option/option.hpp>
#include <nitro/broken_options/option/toggle.hpp>
#include <nitro/broken_options/options.hpp>

#include <nitro/except/raise.hpp>

#include <iostream>
#include <map>
#include <string>
#include <vector>

namespace nitro
{
namespace broken_options
{

    class parser
    {
    public:
        parser(const std::string& app_name = std::string("main"),
               const std::string& about = std::string(""))
        : app_name_(app_name), about_(about), arguments_("arguments")
        {
        }

    public:
        broken_options::option& option(const std::string& name,
                                       const std::string& description = std::string(""))
        {
            if (multi_options_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine multi_option as option. Name: ", name);
            }

            if (toggles_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine toggle as multi_option. Name: ", name);
            }

            if (options_.count(name) == 0)
            {
                auto res = options_.emplace(std::piecewise_construct, std::forward_as_tuple(name),
                                            std::forward_as_tuple(name, description));
                arguments_.add(res.first->second);
            }
            return options_.at(name);
        }

        broken_options::multi_option& multi_option(const std::string& name,
                                                   const std::string& description = std::string(""))
        {
            if (options_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine option as multi_option. Name: ", name);
            }

            if (toggles_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine toggle as multi_option. Name: ", name);
            }

            if (multi_options_.count(name) == 0)
            {
                auto res =
                    multi_options_.emplace(std::piecewise_construct, std::forward_as_tuple(name),
                                           std::forward_as_tuple(name, description));
                arguments_.add(res.first->second);
            }
            return multi_options_.at(name);
        }

        broken_options::toggle& toggle(const std::string& name,
                                       const std::string& description = std::string(""))
        {
            if (options_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine option as multi_option. Name: ", name);
            }

            if (multi_options_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine multi_option as option. Name: ", name);
            }

            if (toggles_.count(name) == 0)
            {
                auto res = toggles_.emplace(std::piecewise_construct, std::forward_as_tuple(name),
                                            std::forward_as_tuple(name, description));
                arguments_.add(res.first->second);
            }
            return toggles_.at(name);
        }

        void ignore_unknown(bool ignore = true)
        {
            force_positional_ = ignore;
        }

        options parse(int argc, const char* const argv[])
        {
            for (auto& option : options_)
            {
                option.second.update();
            }

            for (auto& option : multi_options_)
            {
                option.second.update();
            }

            for (auto& option : toggles_)
            {
                option.second.update();
            }

            bool only_positionals = false;
            std::vector<std::string> positionals;

            for (int i = 1; i < argc; i++)
            {
                argument current_arg(argv[i]);

                if (current_arg.is_double_dash())
                {
                    only_positionals = true;

                    continue;
                }

                if (only_positionals || current_arg.is_value())
                {
                    positionals.push_back(current_arg.data());

                    continue;
                }

                bool match_found = false;
                for (auto& option : options_)
                {

                    if (current_arg.has_value())
                    {
                        if (option.second.matches(current_arg.name()))
                        {
                            match_found = true;

                            option.second.update_value(current_arg);

                            break;
                        }
                    }
                    else
                    {
                        if (option.second.matches(current_arg.data()))
                        {
                            match_found = true;

                            option.second.update_value(std::string(argv[++i]));

                            break;
                        }
                    }
                }

                for (auto& option : multi_options_)
                {
                    if (match_found)
                    {
                        // could already be set in previous loop
                        break;
                    }

                    if (current_arg.has_value())
                    {
                        if (option.second.matches(current_arg.name()))
                        {
                            match_found = true;

                            option.second.update_value(current_arg);

                            break;
                        }
                    }
                    else
                    {
                        if (option.second.matches(current_arg.name()))
                        {
                            match_found = true;

                            option.second.update_value(std::string(argv[++i]));

                            break;
                        }
                    }
                }

                for (auto& option : toggles_)
                {
                    if (option.second.matches(current_arg.name()))
                    {
                        match_found = true;
                        option.second.update_value(current_arg);
                    }
                }

                if (force_positional_)
                {
                    positionals.push_back(current_arg.name());

                    argument next_argument(argv[++i]);
                    if (next_argument.is_value())
                    {
                        positionals.emplace_back(next_argument.data());
                    }

                    continue;
                }

                if (!match_found)
                {
                    raise<parsing_error>("Argument '", current_arg.data(),
                                         "' could not be parsed.");
                }
            }

            for (auto& option : options_)
            {
                option.second.check();
            }

            for (auto& option : multi_options_)
            {
                option.second.check();
            }

            for (auto& option : toggles_)
            {
                option.second.check();
            }

            return options(options_, multi_options_, toggles_, positionals);
        }

    public:
        std::ostream& usage(std::ostream& s = std::cout, bool print_default_group = true)
        {
            std::string short_list;
            std::string option_list;

            for (auto& toggle : toggles_)
            {
                if (toggle.second.has_short_name())
                {
                    short_list += toggle.second.short_name();
                }
            }

            s << "usage: " << app_name_;

            if (!short_list.empty())
            {
                std::sort(short_list.begin(), short_list.end());
                s << " [-" << short_list << "]";
            }

            for (auto& opt : options_)
            {
                if (opt.second.has_default())
                {
                    option_list += " [--" + opt.second.name() + "]";
                }
                else
                {
                    option_list += " --" + opt.second.name();
                }
            }

            for (auto& mopt : multi_options_)
            {
                if (mopt.second.has_default())
                {
                    option_list += " [--" + mopt.second.name() + "]";
                }
                else
                {
                    option_list += " --" + mopt.second.name();
                }
            }

            if (!option_list.empty())
            {
                s << option_list;
            }

            s << std::endl << std::endl;

            if (!about_.empty())
            {
                s << about_ << std::endl << std::endl;
            }

            if (print_default_group)
            {
                arguments_.usage(s);
            }

            return s;
        }

    private:
        std::string app_name_;
        std::string about_;

        std::map<std::string, broken_options::option> options_;
        std::map<std::string, broken_options::multi_option> multi_options_;
        std::map<std::string, broken_options::toggle> toggles_;

        group arguments_;

        bool force_positional_ = false;
    };
} // namespace broken_options
} // namespace nitro

#endif // INCLUDE_NITRO_BROKEN_OPTIONS_PARSER_HPP
<commit_msg>Fix positional parsing when ignore_unknown() is set<commit_after>/*
 * Copyright (c) 2015-2016, Technische Universität Dresden, Germany
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
 *    and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef INCLUDE_NITRO_BROKEN_OPTIONS_PARSER_HPP
#define INCLUDE_NITRO_BROKEN_OPTIONS_PARSER_HPP

#include <nitro/broken_options/argument.hpp>
#include <nitro/broken_options/exception.hpp>
#include <nitro/broken_options/option/group.hpp>
#include <nitro/broken_options/option/multi_option.hpp>
#include <nitro/broken_options/option/option.hpp>
#include <nitro/broken_options/option/toggle.hpp>
#include <nitro/broken_options/options.hpp>

#include <nitro/except/raise.hpp>

#include <iostream>
#include <map>
#include <string>
#include <vector>

namespace nitro
{
namespace broken_options
{

    class parser
    {
    public:
        parser(const std::string& app_name = std::string("main"),
               const std::string& about = std::string(""))
        : app_name_(app_name), about_(about), arguments_("arguments")
        {
        }

    public:
        broken_options::option& option(const std::string& name,
                                       const std::string& description = std::string(""))
        {
            if (multi_options_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine multi_option as option. Name: ", name);
            }

            if (toggles_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine toggle as multi_option. Name: ", name);
            }

            if (options_.count(name) == 0)
            {
                auto res = options_.emplace(std::piecewise_construct, std::forward_as_tuple(name),
                                            std::forward_as_tuple(name, description));
                arguments_.add(res.first->second);
            }
            return options_.at(name);
        }

        broken_options::multi_option& multi_option(const std::string& name,
                                                   const std::string& description = std::string(""))
        {
            if (options_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine option as multi_option. Name: ", name);
            }

            if (toggles_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine toggle as multi_option. Name: ", name);
            }

            if (multi_options_.count(name) == 0)
            {
                auto res =
                    multi_options_.emplace(std::piecewise_construct, std::forward_as_tuple(name),
                                           std::forward_as_tuple(name, description));
                arguments_.add(res.first->second);
            }
            return multi_options_.at(name);
        }

        broken_options::toggle& toggle(const std::string& name,
                                       const std::string& description = std::string(""))
        {
            if (options_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine option as multi_option. Name: ", name);
            }

            if (multi_options_.count(name) > 0)
            {
                raise<parser_error>("Trying to redefine multi_option as option. Name: ", name);
            }

            if (toggles_.count(name) == 0)
            {
                auto res = toggles_.emplace(std::piecewise_construct, std::forward_as_tuple(name),
                                            std::forward_as_tuple(name, description));
                arguments_.add(res.first->second);
            }
            return toggles_.at(name);
        }

        void ignore_unknown(bool ignore = true)
        {
            force_positional_ = ignore;
        }

        options parse(int argc, const char* const argv[])
        {
            for (auto& option : options_)
            {
                option.second.update();
            }

            for (auto& option : multi_options_)
            {
                option.second.update();
            }

            for (auto& option : toggles_)
            {
                option.second.update();
            }

            bool only_positionals = false;
            std::vector<std::string> positionals;

            for (int i = 1; i < argc; i++)
            {
                argument current_arg(argv[i]);

                if (current_arg.is_double_dash())
                {
                    only_positionals = true;

                    continue;
                }

                if (only_positionals || current_arg.is_value())
                {
                    positionals.push_back(current_arg.data());

                    continue;
                }

                bool match_found = false;
                for (auto& option : options_)
                {

                    if (current_arg.has_value())
                    {
                        if (option.second.matches(current_arg.name()))
                        {
                            match_found = true;

                            option.second.update_value(current_arg);

                            break;
                        }
                    }
                    else
                    {
                        if (option.second.matches(current_arg.data()))
                        {
                            match_found = true;

                            option.second.update_value(std::string(argv[++i]));

                            break;
                        }
                    }
                }

                for (auto& option : multi_options_)
                {
                    if (match_found)
                    {
                        // could already be set in previous loop
                        break;
                    }

                    if (current_arg.has_value())
                    {
                        if (option.second.matches(current_arg.name()))
                        {
                            match_found = true;

                            option.second.update_value(current_arg);

                            break;
                        }
                    }
                    else
                    {
                        if (option.second.matches(current_arg.name()))
                        {
                            match_found = true;

                            option.second.update_value(std::string(argv[++i]));

                            break;
                        }
                    }
                }

                for (auto& option : toggles_)
                {
                    if (option.second.matches(current_arg.name()))
                    {
                        match_found = true;
                        option.second.update_value(current_arg);
                    }
                }

                if (force_positional_)
                {
                    positionals.push_back(current_arg.name());

                    if (i < argc - 1)
                    {
                        argument next_argument(argv[++i]);
                        if (next_argument.is_value())
                        {
                            positionals.emplace_back(next_argument.data());
                        }
                    }

                    continue;
                }

                if (!match_found)
                {
                    raise<parsing_error>("Argument '", current_arg.data(),
                                         "' could not be parsed.");
                }
            }

            for (auto& option : options_)
            {
                option.second.check();
            }

            for (auto& option : multi_options_)
            {
                option.second.check();
            }

            for (auto& option : toggles_)
            {
                option.second.check();
            }

            return options(options_, multi_options_, toggles_, positionals);
        }

    public:
        std::ostream& usage(std::ostream& s = std::cout, bool print_default_group = true)
        {
            std::string short_list;
            std::string option_list;

            for (auto& toggle : toggles_)
            {
                if (toggle.second.has_short_name())
                {
                    short_list += toggle.second.short_name();
                }
            }

            s << "usage: " << app_name_;

            if (!short_list.empty())
            {
                std::sort(short_list.begin(), short_list.end());
                s << " [-" << short_list << "]";
            }

            for (auto& opt : options_)
            {
                if (opt.second.has_default())
                {
                    option_list += " [--" + opt.second.name() + "]";
                }
                else
                {
                    option_list += " --" + opt.second.name();
                }
            }

            for (auto& mopt : multi_options_)
            {
                if (mopt.second.has_default())
                {
                    option_list += " [--" + mopt.second.name() + "]";
                }
                else
                {
                    option_list += " --" + mopt.second.name();
                }
            }

            if (!option_list.empty())
            {
                s << option_list;
            }

            s << std::endl << std::endl;

            if (!about_.empty())
            {
                s << about_ << std::endl << std::endl;
            }

            if (print_default_group)
            {
                arguments_.usage(s);
            }

            return s;
        }

    private:
        std::string app_name_;
        std::string about_;

        std::map<std::string, broken_options::option> options_;
        std::map<std::string, broken_options::multi_option> multi_options_;
        std::map<std::string, broken_options::toggle> toggles_;

        group arguments_;

        bool force_positional_ = false;
    };
} // namespace broken_options
} // namespace nitro

#endif // INCLUDE_NITRO_BROKEN_OPTIONS_PARSER_HPP
<|endoftext|>


<commit_before>/*************************************************************************/
/*  file_access_windows.cpp                                              */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#ifdef WINDOWS_ENABLED

#include "file_access_windows.h"
#include "os/os.h"
#include "shlwapi.h"
#include <windows.h>

#include "print_string.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <tchar.h>
#include <wchar.h>

#ifdef _MSC_VER
#define S_ISREG(m) ((m)&_S_IFREG)
#endif

void FileAccessWindows::check_errors() const {

	ERR_FAIL_COND(!f);

	if (feof(f)) {

		last_error = ERR_FILE_EOF;
	}
}

Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {

	path_src = p_path;
	path = fix_path(p_path);
	if (f)
		close();

	const wchar_t *mode_string;

	if (p_mode_flags == READ)
		mode_string = L"rb";
	else if (p_mode_flags == WRITE)
		mode_string = L"wb";
	else if (p_mode_flags == READ_WRITE)
		mode_string = L"rb+";
	else if (p_mode_flags == WRITE_READ)
		mode_string = L"wb+";
	else
		return ERR_INVALID_PARAMETER;

	/* pretty much every implementation that uses fopen as primary
	   backend supports utf8 encoding */

	struct _stat st;
	if (_wstat(path.c_str(), &st) == 0) {

		if (!S_ISREG(st.st_mode))
			return ERR_FILE_CANT_OPEN;
	};

	if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) {
		save_path = path;
		path = path + ".tmp";
		//print_line("saving instead to "+path);
	}

	f = _wfopen(path.c_str(), mode_string);

	if (f == NULL) {
		last_error = ERR_FILE_CANT_OPEN;
		return ERR_FILE_CANT_OPEN;
	} else {
		last_error = OK;
		flags = p_mode_flags;
		return OK;
	}
}
void FileAccessWindows::close() {

	if (!f)
		return;

	fclose(f);
	f = NULL;

	if (save_path != "") {

		//unlink(save_path.utf8().get_data());
		//print_line("renaming..");
		//_wunlink(save_path.c_str()); //unlink if exists
		//int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());

		bool rename_error = true;
		int attempts = 4;
		while (rename_error && attempts) {
		// This workaround of trying multiple times is added to deal with paranoid Windows
		// antiviruses that love reading just written files even if they are not executable, thus
		// locking the file and preventing renaming from happening.

#ifdef UWP_ENABLED
			// UWP has no PathFileExists, so we check attributes instead
			DWORD fileAttr;

			fileAttr = GetFileAttributesW(save_path.c_str());
			if (INVALID_FILE_ATTRIBUTES == fileAttr) {
#else
			if (!PathFileExistsW(save_path.c_str())) {
#endif
				//creating new file
				rename_error = _wrename((save_path + ".tmp").c_str(), save_path.c_str()) != 0;
			} else {
				//atomic replace for existing file
				rename_error = !ReplaceFileW(save_path.c_str(), (save_path + ".tmp").c_str(), NULL, 2 | 4, NULL, NULL);
			}
			if (rename_error && close_fail_notify) {
				close_fail_notify(save_path);
			}
			if (rename_error) {
				attempts--;
				OS::get_singleton()->delay_usec(1000000); //wait 100msec and try again
			}
		}

		save_path = "";
		if (rename_error) {
			ERR_EXPLAIN("Safe save failed. This may be a permissions problem, but also may happen because you are running a paranoid antivirus. If this is the case, please switch to Windows Defender or disable the 'safe save' option in editor settings. This makes it work, but increases the risk of file corruption in a crash.");
		}
		ERR_FAIL_COND(rename_error);
	}
}

String FileAccessWindows::get_path() const {

	return path_src;
}

String FileAccessWindows::get_path_absolute() const {

	return path;
}

bool FileAccessWindows::is_open() const {

	return (f != NULL);
}
void FileAccessWindows::seek(size_t p_position) {

	ERR_FAIL_COND(!f);
	last_error = OK;
	if (fseek(f, p_position, SEEK_SET))
		check_errors();
}
void FileAccessWindows::seek_end(int64_t p_position) {

	ERR_FAIL_COND(!f);
	if (fseek(f, p_position, SEEK_END))
		check_errors();
}
size_t FileAccessWindows::get_position() const {

	size_t aux_position = 0;
	aux_position = ftell(f);
	if (!aux_position) {
		check_errors();
	};
	return aux_position;
}
size_t FileAccessWindows::get_len() const {

	ERR_FAIL_COND_V(!f, 0);

	size_t pos = get_position();
	fseek(f, 0, SEEK_END);
	int size = get_position();
	fseek(f, pos, SEEK_SET);

	return size;
}

bool FileAccessWindows::eof_reached() const {

	check_errors();
	return last_error == ERR_FILE_EOF;
}

uint8_t FileAccessWindows::get_8() const {

	ERR_FAIL_COND_V(!f, 0);
	uint8_t b;
	if (fread(&b, 1, 1, f) == 0) {
		check_errors();
		b = '\0';
	};

	return b;
}

int FileAccessWindows::get_buffer(uint8_t *p_dst, int p_length) const {

	ERR_FAIL_COND_V(!f, -1);
	int read = fread(p_dst, 1, p_length, f);
	check_errors();
	return read;
};

Error FileAccessWindows::get_error() const {

	return last_error;
}

void FileAccessWindows::flush() {

	ERR_FAIL_COND(!f);
	fflush(f);
}

void FileAccessWindows::store_8(uint8_t p_dest) {

	ERR_FAIL_COND(!f);
	fwrite(&p_dest, 1, 1, f);
}

void FileAccessWindows::store_buffer(const uint8_t *p_src, int p_length) {
	ERR_FAIL_COND(!f);
	ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length);
}

bool FileAccessWindows::file_exists(const String &p_name) {

	FILE *g;
	//printf("opening file %s\n", p_fname.c_str());
	String filename = fix_path(p_name);
	g = _wfopen(filename.c_str(), L"rb");
	if (g == NULL) {

		return false;
	} else {

		fclose(g);
		return true;
	}
}

uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {

	String file = fix_path(p_file);
	if (file.ends_with("/") && file != "/")
		file = file.substr(0, file.length() - 1);

	struct _stat st;
	int rv = _wstat(file.c_str(), &st);

	if (rv == 0) {

		return st.st_mtime;
	} else {
		print_line("no access to " + file);
	}

	ERR_FAIL_V(0);
};

FileAccessWindows::FileAccessWindows() {

	f = NULL;
	flags = 0;
	last_error = OK;
}
FileAccessWindows::~FileAccessWindows() {

	close();
}

#endif
<commit_msg>Trigger IO error only after exhausting attempts<commit_after>/*************************************************************************/
/*  file_access_windows.cpp                                              */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#ifdef WINDOWS_ENABLED

#include "file_access_windows.h"
#include "os/os.h"
#include "shlwapi.h"
#include <windows.h>

#include "print_string.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <tchar.h>
#include <wchar.h>

#ifdef _MSC_VER
#define S_ISREG(m) ((m)&_S_IFREG)
#endif

void FileAccessWindows::check_errors() const {

	ERR_FAIL_COND(!f);

	if (feof(f)) {

		last_error = ERR_FILE_EOF;
	}
}

Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {

	path_src = p_path;
	path = fix_path(p_path);
	if (f)
		close();

	const wchar_t *mode_string;

	if (p_mode_flags == READ)
		mode_string = L"rb";
	else if (p_mode_flags == WRITE)
		mode_string = L"wb";
	else if (p_mode_flags == READ_WRITE)
		mode_string = L"rb+";
	else if (p_mode_flags == WRITE_READ)
		mode_string = L"wb+";
	else
		return ERR_INVALID_PARAMETER;

	/* pretty much every implementation that uses fopen as primary
	   backend supports utf8 encoding */

	struct _stat st;
	if (_wstat(path.c_str(), &st) == 0) {

		if (!S_ISREG(st.st_mode))
			return ERR_FILE_CANT_OPEN;
	};

	if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) {
		save_path = path;
		path = path + ".tmp";
		//print_line("saving instead to "+path);
	}

	f = _wfopen(path.c_str(), mode_string);

	if (f == NULL) {
		last_error = ERR_FILE_CANT_OPEN;
		return ERR_FILE_CANT_OPEN;
	} else {
		last_error = OK;
		flags = p_mode_flags;
		return OK;
	}
}
void FileAccessWindows::close() {

	if (!f)
		return;

	fclose(f);
	f = NULL;

	if (save_path != "") {

		//unlink(save_path.utf8().get_data());
		//print_line("renaming..");
		//_wunlink(save_path.c_str()); //unlink if exists
		//int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str());

		bool rename_error = true;
		int attempts = 4;
		while (rename_error && attempts) {
		// This workaround of trying multiple times is added to deal with paranoid Windows
		// antiviruses that love reading just written files even if they are not executable, thus
		// locking the file and preventing renaming from happening.

#ifdef UWP_ENABLED
			// UWP has no PathFileExists, so we check attributes instead
			DWORD fileAttr;

			fileAttr = GetFileAttributesW(save_path.c_str());
			if (INVALID_FILE_ATTRIBUTES == fileAttr) {
#else
			if (!PathFileExistsW(save_path.c_str())) {
#endif
				//creating new file
				rename_error = _wrename((save_path + ".tmp").c_str(), save_path.c_str()) != 0;
			} else {
				//atomic replace for existing file
				rename_error = !ReplaceFileW(save_path.c_str(), (save_path + ".tmp").c_str(), NULL, 2 | 4, NULL, NULL);
			}
			if (rename_error) {
				attempts--;
				OS::get_singleton()->delay_usec(1000000); //wait 100msec and try again
			}
		}

		if (rename_error) {
			if (close_fail_notify) {
				close_fail_notify(save_path);
			}

			ERR_EXPLAIN("Safe save failed. This may be a permissions problem, but also may happen because you are running a paranoid antivirus. If this is the case, please switch to Windows Defender or disable the 'safe save' option in editor settings. This makes it work, but increases the risk of file corruption in a crash.");
		}

		save_path = "";

		ERR_FAIL_COND(rename_error);
	}
}

String FileAccessWindows::get_path() const {

	return path_src;
}

String FileAccessWindows::get_path_absolute() const {

	return path;
}

bool FileAccessWindows::is_open() const {

	return (f != NULL);
}
void FileAccessWindows::seek(size_t p_position) {

	ERR_FAIL_COND(!f);
	last_error = OK;
	if (fseek(f, p_position, SEEK_SET))
		check_errors();
}
void FileAccessWindows::seek_end(int64_t p_position) {

	ERR_FAIL_COND(!f);
	if (fseek(f, p_position, SEEK_END))
		check_errors();
}
size_t FileAccessWindows::get_position() const {

	size_t aux_position = 0;
	aux_position = ftell(f);
	if (!aux_position) {
		check_errors();
	};
	return aux_position;
}
size_t FileAccessWindows::get_len() const {

	ERR_FAIL_COND_V(!f, 0);

	size_t pos = get_position();
	fseek(f, 0, SEEK_END);
	int size = get_position();
	fseek(f, pos, SEEK_SET);

	return size;
}

bool FileAccessWindows::eof_reached() const {

	check_errors();
	return last_error == ERR_FILE_EOF;
}

uint8_t FileAccessWindows::get_8() const {

	ERR_FAIL_COND_V(!f, 0);
	uint8_t b;
	if (fread(&b, 1, 1, f) == 0) {
		check_errors();
		b = '\0';
	};

	return b;
}

int FileAccessWindows::get_buffer(uint8_t *p_dst, int p_length) const {

	ERR_FAIL_COND_V(!f, -1);
	int read = fread(p_dst, 1, p_length, f);
	check_errors();
	return read;
};

Error FileAccessWindows::get_error() const {

	return last_error;
}

void FileAccessWindows::flush() {

	ERR_FAIL_COND(!f);
	fflush(f);
}

void FileAccessWindows::store_8(uint8_t p_dest) {

	ERR_FAIL_COND(!f);
	fwrite(&p_dest, 1, 1, f);
}

void FileAccessWindows::store_buffer(const uint8_t *p_src, int p_length) {
	ERR_FAIL_COND(!f);
	ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length);
}

bool FileAccessWindows::file_exists(const String &p_name) {

	FILE *g;
	//printf("opening file %s\n", p_fname.c_str());
	String filename = fix_path(p_name);
	g = _wfopen(filename.c_str(), L"rb");
	if (g == NULL) {

		return false;
	} else {

		fclose(g);
		return true;
	}
}

uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {

	String file = fix_path(p_file);
	if (file.ends_with("/") && file != "/")
		file = file.substr(0, file.length() - 1);

	struct _stat st;
	int rv = _wstat(file.c_str(), &st);

	if (rv == 0) {

		return st.st_mtime;
	} else {
		print_line("no access to " + file);
	}

	ERR_FAIL_V(0);
};

FileAccessWindows::FileAccessWindows() {

	f = NULL;
	flags = 0;
	last_error = OK;
}
FileAccessWindows::~FileAccessWindows() {

	close();
}

#endif
<|endoftext|>


<commit_before>#ifdef(WIN32)
#define CPL_DISABLE_DLL
#endif
#include "ogrsf_frmts.h"

int main(int argc,char * argv[])
{
  OGRSFDriverRegistrar::Open(argv[1], FALSE);
  return 0;
}
<commit_msg>COMP: Disabling dll import from ogr<commit_after>#ifdef WIN32
#define CPL_DISABLE_DLL
#endif
#include "ogrsf_frmts.h"

int main(int argc,char * argv[])
{
  OGRSFDriverRegistrar::Open(argv[1], FALSE);
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>cstylecast plugin: ignore templates, improve message<commit_after><|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_NETWORK_PROTOCOL_ADDRESS_HPP
#define LIBBITCOIN_NETWORK_PROTOCOL_ADDRESS_HPP

#include <memory>
#include <bitcoin/bitcoin/define.hpp>
#include <bitcoin/bitcoin/error.hpp>
#include <bitcoin/bitcoin/message/address.hpp>
#include <bitcoin/bitcoin/message/network_address.hpp>
#include <bitcoin/bitcoin/network/channel.hpp>
#include <bitcoin/bitcoin/network/protocol_base.hpp>
#include <bitcoin/bitcoin/network/hosts.hpp>
#include <bitcoin/bitcoin/utility/threadpool.hpp>

namespace libbitcoin {
namespace network {

/**
 * Address protocol.
 * Attach this to a node immediately following handshake completion.
 */
class BC_API protocol_address
  : public protocol_base
{
public:
    /**
     * Start an address protocol instance.
     * @param[in]  peer   The channel on which to start the protocol.
     * @param[in]  pool   The thread pool used by the protocol.
     * @param[in]  hosts  The address pool that this class populates.
     * @param[in]  self   The address that represents us to peers.
     */
    protocol_address(channel::ptr peer, threadpool& pool, hosts& hosts,
        const message::network_address& self);

private:
    std::shared_ptr<protocol_address> shared();

    void handle_receive_address(const code& ec,
        const message::address& address);
    void handle_receive_get_address(const code& ec,
        const message::get_address& message);
    void handle_send_address(const code& ec) const;
    void handle_send_get_address(const code& ec) const;
    void handle_store_addresses(const code& ec) const;

    hosts& hosts_;
    const message::address self_;
};

} // namespace network
} // namespace libbitcoin

#endif
<commit_msg>Remove dead code.<commit_after>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_NETWORK_PROTOCOL_ADDRESS_HPP
#define LIBBITCOIN_NETWORK_PROTOCOL_ADDRESS_HPP

#include <memory>
#include <bitcoin/bitcoin/define.hpp>
#include <bitcoin/bitcoin/error.hpp>
#include <bitcoin/bitcoin/message/address.hpp>
#include <bitcoin/bitcoin/message/network_address.hpp>
#include <bitcoin/bitcoin/network/channel.hpp>
#include <bitcoin/bitcoin/network/protocol_base.hpp>
#include <bitcoin/bitcoin/network/hosts.hpp>
#include <bitcoin/bitcoin/utility/threadpool.hpp>

namespace libbitcoin {
namespace network {

/**
 * Address protocol.
 * Attach this to a node immediately following handshake completion.
 */
class BC_API protocol_address
  : public protocol_base
{
public:
    /**
     * Start an address protocol instance.
     * @param[in]  peer   The channel on which to start the protocol.
     * @param[in]  pool   The thread pool used by the protocol.
     * @param[in]  hosts  The address pool that this class populates.
     * @param[in]  self   The address that represents us to peers.
     */
    protocol_address(channel::ptr peer, threadpool& pool, hosts& hosts,
        const message::network_address& self);

private:
    void handle_receive_address(const code& ec,
        const message::address& address);
    void handle_receive_get_address(const code& ec,
        const message::get_address& message);
    void handle_send_address(const code& ec) const;
    void handle_send_get_address(const code& ec) const;
    void handle_store_addresses(const code& ec) const;

    hosts& hosts_;
    const message::address self_;
};

} // namespace network
} // namespace libbitcoin

#endif
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_CORE_MAIN_MENU_MENU_HPP
#define RJ_CORE_MAIN_MENU_MENU_HPP

#include "basic_component.hpp"
#include "items.hpp"
#include "level_squares.hpp"
#include <rectojump/global/common.hpp>

#include <mlk/signals_slots/slot.h>
#include <mlk/types/types.h>

namespace rj
{
	template<typename State_Enum, State_Enum start_state>
	class submenu_manager
	{
		using bc_ptr = mlk::sptr<basic_component>;

		State_Enum m_current_state{start_state};
		std::map<State_Enum, bc_ptr> m_components;

	public:
		submenu_manager() = default;

		void update_current_state(dur duration)
		{this->current()->update(duration);}

		void render_current_state()
		{this->current()->render();}

		void event_up()
		{this->current()->on_key_up();}

		void event_down()
		{this->current()->on_key_down();}

		void event_current()
		{this->current()->call_current_event();}

		template<typename Basic_Component_Ptr>
		void add_menu(State_Enum state, const Basic_Component_Ptr& bc)
		{m_components[state] = bc;}

		void switch_state(State_Enum new_state)
		{m_current_state = new_state;}

	private:
		bc_ptr& current() noexcept
		{return m_components[m_current_state];}
	};
}

#endif // RJ_CORE_MAIN_MENU_MENU_HPP
<commit_msg>handling states with a std::stack<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_CORE_MAIN_MENU_MENU_HPP
#define RJ_CORE_MAIN_MENU_MENU_HPP

#include "basic_component.hpp"
#include "items.hpp"
#include "level_squares.hpp"
#include <rectojump/global/common.hpp>

#include <mlk/signals_slots/slot.h>
#include <mlk/types/types.h>

#include <stack>

namespace rj
{
	template<typename State_Enum, State_Enum start_state>
	class submenu_manager
	{
		using bc_ptr = mlk::sptr<basic_component>;

		std::stack<State_Enum> m_state_stack;
		std::map<State_Enum, bc_ptr> m_components;

	public:
		submenu_manager()
		{m_state_stack.push(start_state);}

		void update_current_state(dur duration)
		{this->current()->update(duration);}

		void render_current_state()
		{this->current()->render();}

		void event_up()
		{this->current()->on_key_up();}

		void event_down()
		{this->current()->on_key_down();}

		void event_current()
		{this->current()->call_current_event();}

		template<typename Basic_Component_Ptr>
		void add_menu(State_Enum state, const Basic_Component_Ptr& bc)
		{m_components[state] = bc;}

		void switch_state(State_Enum new_state) noexcept
		{m_state_stack.push(new_state);}

		void activate_prev_state() noexcept
		{
			if(m_state_stack.size() == 1)
				return;
			m_state_stack.pop();
		}

		State_Enum get_current_state() const noexcept
		{return m_state_stack.top();}

	private:
		bc_ptr& current() noexcept
		{return m_components[this->get_current_state()];}
	};
}

#endif // RJ_CORE_MAIN_MENU_MENU_HPP
<|endoftext|>


<commit_before>#include <Sound.h>
#include <Display.h>
#include <SDL.h>
#include <SDL_mixer.h>

#include <hx/Thread.h>

namespace nme
{

bool gSDLIsInit = false;

class SDLSoundChannel;

bool sChannelsInit = false;
enum { sMaxChannels = 8 };

bool sUsedChannel[sMaxChannels];
bool sDoneChannel[sMaxChannels];
void *sUsedMusic = 0;
bool sDoneMusic = false;
enum { STEREO_SAMPLES = 2 };

unsigned int  sSoundPos = 0;

void onChannelDone(int inChannel)
{
   if (sUsedChannel[inChannel])
      sDoneChannel[inChannel] = true;
}

void onMusicDone()
{
   if (sUsedMusic)
      sDoneMusic = true;
}

void  onPostMix(void *udata, Uint8 *stream, int len)
{
   sSoundPos += len / sizeof(short) / STEREO_SAMPLES ;
}

static bool Init()
{
   if (!gSDLIsInit)
   {
      ELOG("Please init Stage before creating sound.");
      return false;
   }

   if (!sChannelsInit)
   {
      sChannelsInit = true;
      for(int i=0;i<sMaxChannels;i++)
      {
         sUsedChannel[i] = false;
         sDoneChannel[i] = false;
      }
      Mix_ChannelFinished(onChannelDone);
      Mix_HookMusicFinished(onMusicDone);
      Mix_SetPostMix(onPostMix,0);
   }

   return sChannelsInit;
}

// ---  Using "Mix_Chunk" API ----------------------------------------------------

class SDLSoundChannel : public SoundChannel
{
  enum { BUF_SIZE = (1<<17) };

public:
   SDLSoundChannel(Object *inSound, Mix_Chunk *inChunk, double inStartTime, int inLoops,
                  const SoundTransform &inTransform)
   {
      mChunk = inChunk;
      mDynamicBuffer = 0;
      mSound = inSound;
      mSound->IncRef();

      mChannel = -1;

      // Allocate myself a channel
      if (mChunk)
      {
         for(int i=0;i<sMaxChannels;i++)
            if (!sUsedChannel[i])
            {
               IncRef();
               sDoneChannel[i] = false;
               sUsedChannel[i] = true;
               mChannel = i;
               break;
            }
      }

      if (mChannel>=0)
      {
         Mix_PlayChannel( mChannel , mChunk, inLoops<0 ? -1 : inLoops==0 ? 0 : inLoops-1 );
         Mix_Volume( mChannel, inTransform.volume*MIX_MAX_VOLUME );
         // Mix_SetPanning
      }
   }

   SDLSoundChannel(const ByteArray &inBytes, const SoundTransform &inTransform)
   {
      Mix_QuerySpec(&mFrequency, &mFormat, &mChannels);
      if (mFrequency!=44100)
         ELOG("Warning - Frequency mismatch %d",mFrequency);
      if (mFormat!=32784)
         ELOG("Warning - Format mismatch    %d",mFormat);
      if (mChannels!=2)
         ELOG("Warning - channe mismatch    %d",mChannels);

      mChunk = 0;
      mDynamicBuffer = new short[BUF_SIZE * STEREO_SAMPLES];
      memset(mDynamicBuffer,0,BUF_SIZE*sizeof(short));
      mSound = 0;
      mChannel = -1;
      mDynamicChunk.allocated = 0;
      mDynamicChunk.abuf = (Uint8 *)mDynamicBuffer;
      mDynamicChunk.alen = BUF_SIZE * sizeof(short) * STEREO_SAMPLES; // bytes
      mDynamicChunk.volume = MIX_MAX_VOLUME;
	  #ifndef WEBOS
	   mDynamicChunk.length_ticks = 0;
	  #endif
      mDynamicFillPos = 0;
      mDynamicStartPos = 0;
      mDynamicDataDue = 0;

      // Allocate myself a channel
      for(int i=0;i<sMaxChannels;i++)
         if (!sUsedChannel[i])
         {
            IncRef();
            sDoneChannel[i] = false;
            sUsedChannel[i] = true;
            mChannel = i;
            break;
         }

      if (mChannel>=0)
      {
         FillBuffer(inBytes);
         // Just once ...
         if (mDynamicFillPos<1024)
         {
            mDynamicDone = true;
            mDynamicChunk.alen = mDynamicFillPos * sizeof(short) * STEREO_SAMPLES;
            Mix_PlayChannel( mChannel , &mDynamicChunk,  0 );
         }
         else
         {
            mDynamicDone = false;
            // TODO: Lock?
            Mix_PlayChannel( mChannel , &mDynamicChunk,  -1 );
            mDynamicStartPos = sSoundPos;
         }

         Mix_Volume( mChannel, inTransform.volume*MIX_MAX_VOLUME );
      }
   }

   void FillBuffer(const ByteArray &inBytes)
   {
      int time_samples = inBytes.Size()/sizeof(float)/STEREO_SAMPLES;
      const float *buffer = (const float *)inBytes.Bytes();
      enum { MASK = BUF_SIZE - 1 };

      for(int i=0;i<time_samples;i++)
      {
         int mono_pos =  (i+mDynamicFillPos) & MASK;
         mDynamicBuffer[ mono_pos<<1 ] = *buffer++ * ((1<<15)-1);
         mDynamicBuffer[ (mono_pos<<1) + 1 ] = *buffer++ * ((1<<15)-1);
      }

      if (mDynamicFillPos<(sSoundPos-mDynamicStartPos))
         ELOG("Too slow - FillBuffer %d / %d)", mDynamicFillPos, (sSoundPos-mDynamicStartPos) );
      mDynamicFillPos += time_samples;
      if (time_samples<1024 && !mDynamicDone)
      {
         mDynamicDone = true;
         for(int i=0;i<2048;i++)
         {
            int mono_pos =  (i+mDynamicFillPos) & MASK;
            mDynamicBuffer[ mono_pos<<1 ] = 0;
            mDynamicBuffer[ (mono_pos<<1) + 1 ] = 0;
         }

         int samples_left = (int)mDynamicFillPos - (int)(sSoundPos-mDynamicStartPos);
         int ticks_left = samples_left*1000/44100;
         //printf("Expire in %d (%d)\n", samples_left, ticks_left );
         Mix_ExpireChannel(mChannel, ticks_left>0 ? ticks_left : 1 );
      }
   }

   ~SDLSoundChannel()
   {
      delete [] mDynamicBuffer;

      if (mSound)
         mSound->DecRef();
   }

   void CheckDone()
   {
      if (mChannel>=0 && sDoneChannel[mChannel])
      {
         sDoneChannel[mChannel] = false;
         int c = mChannel;
         mChannel = -1;
         DecRef();
         sUsedChannel[c] = 0;
      }
   }

   bool isComplete()
   {
      CheckDone();
      return mChannel < 0;
   }
   double getLeft() { return 1; }
   double getRight() { return 1; }
   double getPosition() { return 1; }
   void stop()
   {
      if (mChannel>=0)
         Mix_HaltChannel(mChannel);
   }
   void setTransform(const SoundTransform &inTransform)
   {
      if (mChannel>=0)
         Mix_Volume( mChannel, inTransform.volume*MIX_MAX_VOLUME );
   }

   double getDataPosition()
   {
      return (sSoundPos-mDynamicStartPos)*1000.0/mFrequency;
   }
   bool needsData()
   {
      if (!mDynamicBuffer || mDynamicDone)
         return false;

      if (mDynamicDataDue<=sSoundPos)
      {
         mDynamicDone = true;
         return true;
      }

      return false;

   }

   void addData(const ByteArray &inBytes)
   {
      mDynamicDone = false;
      mDynamicDataDue = mDynamicFillPos + mDynamicStartPos;
      FillBuffer(inBytes);
   }

   Object    *mSound;
   Mix_Chunk *mChunk;
   int       mChannel;

   Mix_Chunk mDynamicChunk;
   short    *mDynamicBuffer;
   unsigned int  mDynamicFillPos;
   unsigned int  mDynamicStartPos;
   unsigned int  mDynamicDataDue;
   bool      mDynamicDone;
   int       mFrequency;
   Uint16    mFormat;
   int       mChannels;
};

SoundChannel *SoundChannel::Create(const ByteArray &inBytes,const SoundTransform &inTransform)
{
   if (!Init())
      return 0;
   return new SDLSoundChannel(inBytes,inTransform);
}

class SDLSound : public Sound
{
public:
   SDLSound(const std::string &inFilename)
   {
      IncRef();

      #ifdef HX_MACOS
      char name[1024];
      GetBundleFilename(inFilename.c_str(),name,1024);
      #else
      const char *name = inFilename.c_str();
      #endif

      mChunk = Mix_LoadWAV(name);
      if ( mChunk == NULL )
      {
         mError = SDL_GetError();
         // ELOG("Error %s (%s)", mError.c_str(), name );
      }
   }
   ~SDLSound()
   {
      if (mChunk)
         Mix_FreeChunk( mChunk );
   }
   double getLength()
   {
      if (mChunk==0) return 0;
      #if defined(DYNAMIC_SDL) || defined(WEBOS)
      // ?
      return 0.0;
      #else
	  return 0.0;
      //return mChunk->length_ticks;
      #endif
   }
   // Will return with one ref...
   SoundChannel *openChannel(double startTime, int loops, const SoundTransform &inTransform)
   {
      if (!mChunk)
         return 0;
      return new SDLSoundChannel(this,mChunk,startTime, loops,inTransform);
   }
   int getBytesLoaded() { return mChunk ? mChunk->alen : 0; }
   int getBytesTotal() { return mChunk ? mChunk->alen : 0; }
   bool ok() { return mChunk; }
   std::string getError() { return mError; }

   std::string mError;
   Mix_Chunk *mChunk;
};

// ---  Using "Mix_Music" API ----------------------------------------------------

class SDLMusicChannel : public SoundChannel
{
public:
   SDLMusicChannel(Object *inSound, Mix_Music *inMusic, double inStartTime, int inLoops,
                  const SoundTransform &inTransform)
   {
      mMusic = inMusic;
      mSound = inSound;
      mSound->IncRef();

      mPlaying = false;
      if (mMusic)
      {
         mPlaying = true;
         sUsedMusic = this;
         sDoneMusic = false;
         IncRef();
         Mix_PlayMusic( mMusic, inLoops<0 ? -1 : inLoops==0 ? 0 : inLoops-1 );
         Mix_VolumeMusic( inTransform.volume*MIX_MAX_VOLUME );
         // Mix_SetPanning
      }
   }
   ~SDLMusicChannel()
   {
      mSound->DecRef();
   }

   void CheckDone()
   {
      if (mPlaying && (sDoneMusic || (sUsedMusic!=this)) )
      {
         mPlaying = false;
         if (sUsedMusic == this)
         {
            sUsedMusic = 0;
            sDoneMusic = false;
         }
         DecRef();
      }
   }

   bool isComplete()
   {
      CheckDone();
      return !mPlaying;
   }
   double getLeft() { return 1; }
   double getRight() { return 1; }
   double getPosition() { return 1; }
   void stop()
   {
      if (mMusic)
         Mix_HaltMusic();
   }
   void setTransform(const SoundTransform &inTransform)
   {
      if (mMusic>=0)
         Mix_VolumeMusic( inTransform.volume*MIX_MAX_VOLUME );
   }

   bool      mPlaying;
   Object    *mSound;
   Mix_Music *mMusic;
};

class SDLMusic : public Sound
{
public:
   SDLMusic(const std::string &inFilename)
   {
      IncRef();

      #ifdef HX_MACOS
      char name[1024];
      GetBundleFilename(inFilename.c_str(),name,1024);
      #else
      const char *name = inFilename.c_str();
      #endif

      mMusic = Mix_LoadMUS(name);
      if ( mMusic == NULL )
      {
         mError = SDL_GetError();
         ELOG("Error in music %s (%s)", mError.c_str(), name );
      }
   }
   ~SDLMusic()
   {
      if (mMusic)
         Mix_FreeMusic( mMusic );
   }
   double getLength()
   {
      if (mMusic==0) return 0;
      // TODO:
      return 60000;
   }
   // Will return with one ref...
   SoundChannel *openChannel(double startTime, int loops, const SoundTransform &inTransform)
   {
      if (!mMusic)
         return 0;
      return new SDLMusicChannel(this,mMusic,startTime, loops,inTransform);
   }
   int getBytesLoaded() { return mMusic ? 100 : 0; }
   int getBytesTotal() { return mMusic ? 100 : 0; }
   bool ok() { return mMusic; }
   std::string getError() { return mError; }

   std::string mError;
   Mix_Music *mMusic;
};

// --- External Interface -----------------------------------------------------------

Sound *Sound::Create(const std::string &inFilename,bool inForceMusic)
{
   if (!Init())
      return 0;
   Sound *sound = inForceMusic ? 0 :  new SDLSound(inFilename);
   if (!sound || !sound->ok())
   {
      if (sound) sound->DecRef();
      sound = new SDLMusic(inFilename);
   }
   return sound;
}

}
<commit_msg>stub in SDL playback from buffer<commit_after>#include <Sound.h>
#include <Display.h>
#include <SDL.h>
#include <SDL_mixer.h>

#include <hx/Thread.h>

namespace nme
{

bool gSDLIsInit = false;

class SDLSoundChannel;

bool sChannelsInit = false;
enum { sMaxChannels = 8 };

bool sUsedChannel[sMaxChannels];
bool sDoneChannel[sMaxChannels];
void *sUsedMusic = 0;
bool sDoneMusic = false;
enum { STEREO_SAMPLES = 2 };

unsigned int  sSoundPos = 0;

void onChannelDone(int inChannel)
{
   if (sUsedChannel[inChannel])
      sDoneChannel[inChannel] = true;
}

void onMusicDone()
{
   if (sUsedMusic)
      sDoneMusic = true;
}

void  onPostMix(void *udata, Uint8 *stream, int len)
{
   sSoundPos += len / sizeof(short) / STEREO_SAMPLES ;
}

static bool Init()
{
   if (!gSDLIsInit)
   {
      ELOG("Please init Stage before creating sound.");
      return false;
   }

   if (!sChannelsInit)
   {
      sChannelsInit = true;
      for(int i=0;i<sMaxChannels;i++)
      {
         sUsedChannel[i] = false;
         sDoneChannel[i] = false;
      }
      Mix_ChannelFinished(onChannelDone);
      Mix_HookMusicFinished(onMusicDone);
      Mix_SetPostMix(onPostMix,0);
   }

   return sChannelsInit;
}

// ---  Using "Mix_Chunk" API ----------------------------------------------------

class SDLSoundChannel : public SoundChannel
{
  enum { BUF_SIZE = (1<<17) };

public:
   SDLSoundChannel(Object *inSound, Mix_Chunk *inChunk, double inStartTime, int inLoops,
                  const SoundTransform &inTransform)
   {
      mChunk = inChunk;
      mDynamicBuffer = 0;
      mSound = inSound;
      mSound->IncRef();

      mChannel = -1;

      // Allocate myself a channel
      if (mChunk)
      {
         for(int i=0;i<sMaxChannels;i++)
            if (!sUsedChannel[i])
            {
               IncRef();
               sDoneChannel[i] = false;
               sUsedChannel[i] = true;
               mChannel = i;
               break;
            }
      }

      if (mChannel>=0)
      {
         Mix_PlayChannel( mChannel , mChunk, inLoops<0 ? -1 : inLoops==0 ? 0 : inLoops-1 );
         Mix_Volume( mChannel, inTransform.volume*MIX_MAX_VOLUME );
         // Mix_SetPanning
      }
   }

   SDLSoundChannel(const ByteArray &inBytes, const SoundTransform &inTransform)
   {
      Mix_QuerySpec(&mFrequency, &mFormat, &mChannels);
      if (mFrequency!=44100)
         ELOG("Warning - Frequency mismatch %d",mFrequency);
      if (mFormat!=32784)
         ELOG("Warning - Format mismatch    %d",mFormat);
      if (mChannels!=2)
         ELOG("Warning - channe mismatch    %d",mChannels);

      mChunk = 0;
      mDynamicBuffer = new short[BUF_SIZE * STEREO_SAMPLES];
      memset(mDynamicBuffer,0,BUF_SIZE*sizeof(short));
      mSound = 0;
      mChannel = -1;
      mDynamicChunk.allocated = 0;
      mDynamicChunk.abuf = (Uint8 *)mDynamicBuffer;
      mDynamicChunk.alen = BUF_SIZE * sizeof(short) * STEREO_SAMPLES; // bytes
      mDynamicChunk.volume = MIX_MAX_VOLUME;
	  #ifndef WEBOS
	   mDynamicChunk.length_ticks = 0;
	  #endif
      mDynamicFillPos = 0;
      mDynamicStartPos = 0;
      mDynamicDataDue = 0;

      // Allocate myself a channel
      for(int i=0;i<sMaxChannels;i++)
         if (!sUsedChannel[i])
         {
            IncRef();
            sDoneChannel[i] = false;
            sUsedChannel[i] = true;
            mChannel = i;
            break;
         }

      if (mChannel>=0)
      {
         FillBuffer(inBytes);
         // Just once ...
         if (mDynamicFillPos<1024)
         {
            mDynamicDone = true;
            mDynamicChunk.alen = mDynamicFillPos * sizeof(short) * STEREO_SAMPLES;
            Mix_PlayChannel( mChannel , &mDynamicChunk,  0 );
         }
         else
         {
            mDynamicDone = false;
            // TODO: Lock?
            Mix_PlayChannel( mChannel , &mDynamicChunk,  -1 );
            mDynamicStartPos = sSoundPos;
         }

         Mix_Volume( mChannel, inTransform.volume*MIX_MAX_VOLUME );
      }
   }

   void FillBuffer(const ByteArray &inBytes)
   {
      int time_samples = inBytes.Size()/sizeof(float)/STEREO_SAMPLES;
      const float *buffer = (const float *)inBytes.Bytes();
      enum { MASK = BUF_SIZE - 1 };

      for(int i=0;i<time_samples;i++)
      {
         int mono_pos =  (i+mDynamicFillPos) & MASK;
         mDynamicBuffer[ mono_pos<<1 ] = *buffer++ * ((1<<15)-1);
         mDynamicBuffer[ (mono_pos<<1) + 1 ] = *buffer++ * ((1<<15)-1);
      }

      if (mDynamicFillPos<(sSoundPos-mDynamicStartPos))
         ELOG("Too slow - FillBuffer %d / %d)", mDynamicFillPos, (sSoundPos-mDynamicStartPos) );
      mDynamicFillPos += time_samples;
      if (time_samples<1024 && !mDynamicDone)
      {
         mDynamicDone = true;
         for(int i=0;i<2048;i++)
         {
            int mono_pos =  (i+mDynamicFillPos) & MASK;
            mDynamicBuffer[ mono_pos<<1 ] = 0;
            mDynamicBuffer[ (mono_pos<<1) + 1 ] = 0;
         }

         int samples_left = (int)mDynamicFillPos - (int)(sSoundPos-mDynamicStartPos);
         int ticks_left = samples_left*1000/44100;
         //printf("Expire in %d (%d)\n", samples_left, ticks_left );
         Mix_ExpireChannel(mChannel, ticks_left>0 ? ticks_left : 1 );
      }
   }

   ~SDLSoundChannel()
   {
      delete [] mDynamicBuffer;

      if (mSound)
         mSound->DecRef();
   }

   void CheckDone()
   {
      if (mChannel>=0 && sDoneChannel[mChannel])
      {
         sDoneChannel[mChannel] = false;
         int c = mChannel;
         mChannel = -1;
         DecRef();
         sUsedChannel[c] = 0;
      }
   }

   bool isComplete()
   {
      CheckDone();
      return mChannel < 0;
   }
   double getLeft() { return 1; }
   double getRight() { return 1; }
   double getPosition() { return 1; }
   void stop()
   {
      if (mChannel>=0)
         Mix_HaltChannel(mChannel);
   }
   void setTransform(const SoundTransform &inTransform)
   {
      if (mChannel>=0)
         Mix_Volume( mChannel, inTransform.volume*MIX_MAX_VOLUME );
   }

   double getDataPosition()
   {
      return (sSoundPos-mDynamicStartPos)*1000.0/mFrequency;
   }
   bool needsData()
   {
      if (!mDynamicBuffer || mDynamicDone)
         return false;

      if (mDynamicDataDue<=sSoundPos)
      {
         mDynamicDone = true;
         return true;
      }

      return false;

   }

   void addData(const ByteArray &inBytes)
   {
      mDynamicDone = false;
      mDynamicDataDue = mDynamicFillPos + mDynamicStartPos;
      FillBuffer(inBytes);
   }

   Object    *mSound;
   Mix_Chunk *mChunk;
   int       mChannel;

   Mix_Chunk mDynamicChunk;
   short    *mDynamicBuffer;
   unsigned int  mDynamicFillPos;
   unsigned int  mDynamicStartPos;
   unsigned int  mDynamicDataDue;
   bool      mDynamicDone;
   int       mFrequency;
   Uint16    mFormat;
   int       mChannels;
};

SoundChannel *SoundChannel::Create(const ByteArray &inBytes,const SoundTransform &inTransform)
{
   if (!Init())
      return 0;
   return new SDLSoundChannel(inBytes,inTransform);
}

class SDLSound : public Sound
{
public:
   SDLSound(const std::string &inFilename)
   {
      IncRef();

      #ifdef HX_MACOS
      char name[1024];
      GetBundleFilename(inFilename.c_str(),name,1024);
      #else
      const char *name = inFilename.c_str();
      #endif

      mChunk = Mix_LoadWAV(name);
      if ( mChunk == NULL )
      {
         mError = SDL_GetError();
         // ELOG("Error %s (%s)", mError.c_str(), name );
      }
   }
   ~SDLSound()
   {
      if (mChunk)
         Mix_FreeChunk( mChunk );
   }
   double getLength()
   {
      if (mChunk==0) return 0;
      #if defined(DYNAMIC_SDL) || defined(WEBOS)
      // ?
      return 0.0;
      #else
	  return 0.0;
      //return mChunk->length_ticks;
      #endif
   }
   // Will return with one ref...
   SoundChannel *openChannel(double startTime, int loops, const SoundTransform &inTransform)
   {
      if (!mChunk)
         return 0;
      return new SDLSoundChannel(this,mChunk,startTime, loops,inTransform);
   }
   int getBytesLoaded() { return mChunk ? mChunk->alen : 0; }
   int getBytesTotal() { return mChunk ? mChunk->alen : 0; }
   bool ok() { return mChunk; }
   std::string getError() { return mError; }

   std::string mError;
   Mix_Chunk *mChunk;
};

// ---  Using "Mix_Music" API ----------------------------------------------------

class SDLMusicChannel : public SoundChannel
{
public:
   SDLMusicChannel(Object *inSound, Mix_Music *inMusic, double inStartTime, int inLoops,
                  const SoundTransform &inTransform)
   {
      mMusic = inMusic;
      mSound = inSound;
      mSound->IncRef();

      mPlaying = false;
      if (mMusic)
      {
         mPlaying = true;
         sUsedMusic = this;
         sDoneMusic = false;
         IncRef();
         Mix_PlayMusic( mMusic, inLoops<0 ? -1 : inLoops==0 ? 0 : inLoops-1 );
         Mix_VolumeMusic( inTransform.volume*MIX_MAX_VOLUME );
         // Mix_SetPanning
      }
   }
   ~SDLMusicChannel()
   {
      mSound->DecRef();
   }

   void CheckDone()
   {
      if (mPlaying && (sDoneMusic || (sUsedMusic!=this)) )
      {
         mPlaying = false;
         if (sUsedMusic == this)
         {
            sUsedMusic = 0;
            sDoneMusic = false;
         }
         DecRef();
      }
   }

   bool isComplete()
   {
      CheckDone();
      return !mPlaying;
   }
   double getLeft() { return 1; }
   double getRight() { return 1; }
   double getPosition() { return 1; }
   void stop()
   {
      if (mMusic)
         Mix_HaltMusic();
   }
   void setTransform(const SoundTransform &inTransform)
   {
      if (mMusic>=0)
         Mix_VolumeMusic( inTransform.volume*MIX_MAX_VOLUME );
   }

   bool      mPlaying;
   Object    *mSound;
   Mix_Music *mMusic;
};

class SDLMusic : public Sound
{
public:
   SDLMusic(const std::string &inFilename)
   {
      IncRef();

      #ifdef HX_MACOS
      char name[1024];
      GetBundleFilename(inFilename.c_str(),name,1024);
      #else
      const char *name = inFilename.c_str();
      #endif

      mMusic = Mix_LoadMUS(name);
      if ( mMusic == NULL )
      {
         mError = SDL_GetError();
         ELOG("Error in music %s (%s)", mError.c_str(), name );
      }
   }
   ~SDLMusic()
   {
      if (mMusic)
         Mix_FreeMusic( mMusic );
   }
   double getLength()
   {
      if (mMusic==0) return 0;
      // TODO:
      return 60000;
   }
   // Will return with one ref...
   SoundChannel *openChannel(double startTime, int loops, const SoundTransform &inTransform)
   {
      if (!mMusic)
         return 0;
      return new SDLMusicChannel(this,mMusic,startTime, loops,inTransform);
   }
   int getBytesLoaded() { return mMusic ? 100 : 0; }
   int getBytesTotal() { return mMusic ? 100 : 0; }
   bool ok() { return mMusic; }
   std::string getError() { return mError; }

   std::string mError;
   Mix_Music *mMusic;
};

// --- External Interface -----------------------------------------------------------

Sound *Sound::Create(const std::string &inFilename,bool inForceMusic)
{
   if (!Init())
      return 0;
   Sound *sound = inForceMusic ? 0 :  new SDLSound(inFilename);
   if (!sound || !sound->ok())
   {
      if (sound) sound->DecRef();
      sound = new SDLMusic(inFilename);
   }
   return sound;
}

Sound *Sound::Create(unsigned char *inData, int len, bool inForceMusic) {
   if (!Init())
      return 0;
   Sound *sound=0;/* = inForceMusic ? 0 :  new SDLSound(inFilename);
   if (!sound || !sound->ok())
   {
      if (sound) sound->DecRef();
      sound = new SDLMusic(inFilename);
   }*/
   return sound;
}

}
<|endoftext|>


<commit_before>#include "ColouredOutputStreamUpdater.h"
#include <pcl/common/centroid.h>
#include <pcl/common/transforms.h>
#include <future>
#include <pcl/filters/voxel_grid.h>
#include <opencv2/imgproc/imgproc.hpp>

#include "stdafx.h"
#include <atlstr.h>
#include <cmath>

ColouredOutputStreamUpdater::ColouredOutputStreamUpdater()
{
}

static const int            PATCHDIVISIONSHIFT = 2 ;
static const UINT16         VISIBILITY_MAX_THRESHHOLD = 50;
ColouredOutputStreamUpdater::~ColouredOutputStreamUpdater()
{
}

void ColouredOutputStreamUpdater::initialize(ICoordinateMapper* m_pCoordinateMapper, int depthWidth, int depthHeight, int colorWidth, int colorHeight)
{
	OutputStreamsUpdaterStragedy::initialize(m_pCoordinateMapper, depthWidth, depthHeight, colorWidth, colorHeight);
	m_pDepthVisibilityTestMap = std::vector<UINT16>((colorWidth >> PATCHDIVISIONSHIFT) * (colorHeight >> PATCHDIVISIONSHIFT));
	m_pColorCoordinates = std::vector<ColorSpacePoint>(depthWidth * depthHeight);
}

void printMessage(std::string msg)
{
	auto msgCstring = CString(msg.c_str());
	msgCstring += L"\n";
	//OutputDebugString(msgCstring);

}
HRESULT ColouredOutputStreamUpdater::updateOutputStreams(IFaceModel* faceModel, IFaceAlignment* faceAlignment, int bufferSize,
	CameraSpacePoint* detectedHDFacePointsCamSpace, ColorSpacePoint* detectedHDFacePointsColorSpace, RGBQUAD* colorBuffer, UINT16* depthBuffer)
{

	HRESULT hr = faceModel->CalculateVerticesForAlignment(faceAlignment, bufferSize, detectedHDFacePointsCamSpace);
	if (SUCCEEDED(hr)){
		hr = m_pCoordinateMapper->MapCameraPointsToColorSpace(bufferSize, detectedHDFacePointsCamSpace, bufferSize, detectedHDFacePointsColorSpace);
	}
	if (SUCCEEDED(hr)){
		CameraSpacePoint boundingBoxPointTopLeft;
		CameraSpacePoint boundingBoxPointBottomRight;
		std::vector<cv::Point2f> hdFacePointsInColorSpaceSpaceOpenCV;

		std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();

		auto hdFaceCloud = extractClolouredFaceHDPoinCloudAndBoundingBox(bufferSize, detectedHDFacePointsCamSpace, detectedHDFacePointsColorSpace,
			boundingBoxPointTopLeft, boundingBoxPointBottomRight, hdFacePointsInColorSpaceSpaceOpenCV, colorBuffer);

		pcl::PointCloud<pcl::PointXYZRGB>::Ptr hdFaceRawDepthCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
		bool isCorrectFrame = extractColouredDepthCloudFromBoundingBox(boundingBoxPointTopLeft, boundingBoxPointBottomRight,
			hdFacePointsInColorSpaceSpaceOpenCV, colorBuffer, depthBuffer, hdFaceRawDepthCloud);
		if (!isCorrectFrame){
			return hr;
		}

		Eigen::Vector4f centroid;
		pcl::compute3DCentroid(*hdFaceCloud, centroid);
		Eigen::Vector3f center(-centroid.x(), -centroid.y(), -centroid.z());
		Eigen::Matrix4f m = Eigen::Affine3f(Eigen::Translation3f(center)).matrix();

		pcl::transformPointCloud(*hdFaceCloud, *hdFaceCloud, m);
		pcl::transformPointCloud(*hdFaceRawDepthCloud, *hdFaceRawDepthCloud, m);

		if (!cloudsUpdated.empty()){
			std::vector<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> updatedClouds;
			updatedClouds.push_back(hdFaceCloud);
			auto fullDepthCloud = convertDepthBufferToPointCloud(colorBuffer, depthBuffer);
			updatedClouds.push_back(fullDepthCloud);
			cloudsUpdated(updatedClouds);
		}
		if (!cloudUpdated[0].empty()){
			cloudUpdated[0](hdFaceCloud);
		}

		if (!cloudUpdated[1].empty()){
			cloudUpdated[1](hdFaceRawDepthCloud);
		}
		if (!cloudUpdated[2].empty()){
			auto fullDepthCloud = convertDepthBufferToPointCloud(colorBuffer, depthBuffer);
			cloudUpdated[2](fullDepthCloud);
		}

	}
	return hr;
}

pcl::PointCloud<pcl::PointXYZRGB>::Ptr ColouredOutputStreamUpdater::extractClolouredFaceHDPoinCloudAndBoundingBox(int bufferSize, CameraSpacePoint* cameraSpacePoints,
	ColorSpacePoint* colorSpacePoints, CameraSpacePoint& camTopLeftBack, CameraSpacePoint& camBottomRightBack, std::vector<cv::Point2f>& hdFacePointsInColorSpaceSpaceOpenCV,
	RGBQUAD* colorBuffer)
{
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud <pcl::PointXYZRGB>());
	cloud->is_dense = false;
	float bottom	=	 FLT_MAX;
	float top		= -	 FLT_MAX;
	float right		= -	 FLT_MAX;
	float left		=	 FLT_MAX;
	float back		=  - FLT_MAX;
	std::vector<cv::Point2f> ellipsePoints;
	for (int i = 0; i < bufferSize; i++){
		const auto& cameraSpacePoint = *cameraSpacePoints;
		const auto& colorSpacePoint = *colorSpacePoints;
		pcl::PointXYZRGB point;
		point.x = cameraSpacePoint.X;
		point.y = cameraSpacePoint.Y;
		point.z = cameraSpacePoint.Z;

		int colorX = static_cast<int>(std::floor(colorSpacePoint.X + 0.5f));
		int colorY = static_cast<int>(std::floor(colorSpacePoint.Y + 0.5f));

		if (colorY > m_colorHeight || colorX > m_colorWidth || colorY < 0 || colorX < 0)
			continue;

		hdFacePointsInColorSpaceSpaceOpenCV.push_back(cv::Point2f(colorX, colorY));

		bottom = std::min(point.y, bottom);
		top = std::max(point.y, top);
		right = std::max(point.x, right);
		left = std::min(point.x, left);
		back = std::max(point.z, back);

		int colorImageIndex = ((m_colorWidth * colorY) + colorX);
		RGBQUAD pixel = colorBuffer[colorImageIndex];
		point.r = pixel.rgbRed;
		point.g = pixel.rgbGreen;
		point.b = pixel.rgbBlue;

		cloud->push_back(point);

		cameraSpacePoints++;
		colorSpacePoints++;
	}

	camTopLeftBack.X = left;
	camTopLeftBack.Y = top;
	camTopLeftBack.Z = back;

	camBottomRightBack.X = right;
	camBottomRightBack.Y = bottom;
	camBottomRightBack.Z = back;

	return cloud;
}

bool ColouredOutputStreamUpdater::extractColouredDepthCloudFromBoundingBox(CameraSpacePoint camTopLeftBack, CameraSpacePoint camBottomRightBack,
	std::vector<cv::Point2f>& hdFacePointsInColorSpaceSpaceOpenCV, RGBQUAD* colorBuffer, UINT16* depthBuffer, pcl::PointCloud<pcl::PointXYZRGB>::Ptr depthCloud)
{

	DepthSpacePoint depthTopLeftBack;
	m_pCoordinateMapper->MapCameraPointToDepthSpace(camTopLeftBack, &depthTopLeftBack);

	DepthSpacePoint depthBottomRightBack;
	m_pCoordinateMapper->MapCameraPointToDepthSpace(camBottomRightBack, &depthBottomRightBack);

	cv::vector<cv::Point2f> hullPoints;
	if (!isValidDepthPoint(depthTopLeftBack) || !isValidDepthPoint(depthBottomRightBack)){
		return false;
	}

	cv::convexHull(hdFacePointsInColorSpaceSpaceOpenCV, hullPoints);
	for (int x = static_cast<int>(depthTopLeftBack.X); x < static_cast<int>(depthBottomRightBack.X); x++){
		for (int y = static_cast<int>(depthTopLeftBack.Y); y < static_cast<int>(depthBottomRightBack.Y); y++){

			pcl::PointXYZRGB point;
			DepthSpacePoint depthPoint;
			depthPoint.X = static_cast<float>(x);
			depthPoint.Y = static_cast<float>(y);

			UINT16 depthOfCurrentPoint = depthBuffer[y * m_depthWidth + x];

			ColorSpacePoint colorPoint;
			HRESULT hr = m_pCoordinateMapper->MapDepthPointToColorSpace(depthPoint, depthOfCurrentPoint, &colorPoint);
			if (FAILED(hr)){
				continue;
			}
			int colorPixelMidX = static_cast<int>(std::floor(colorPoint.X + 0.5f));
			int colorPixelMidY = static_cast<int>(std::floor(colorPoint.Y + 0.5f));
			auto result = cv::pointPolygonTest(hullPoints, cv::Point2f(colorPoint.X, colorPoint.Y), false);
			if (result < 0){
				continue;
			}

			bool isInColor = false;
			if ((0 <= colorPixelMidX) && (colorPixelMidX < m_colorWidth) && (0 <= colorPixelMidY) && (colorPixelMidY < m_colorHeight)){
				RGBQUAD color = colorBuffer[colorPixelMidY * m_colorWidth + colorPixelMidX];
				point.b = color.rgbBlue;
				point.g = color.rgbGreen;
				point.r = color.rgbRed;
				isInColor = true;
			}

			CameraSpacePoint camPoint;

			hr = m_pCoordinateMapper->MapDepthPointToCameraSpace(depthPoint, depthOfCurrentPoint, &camPoint);

			if (FAILED(hr)){
				continue;
			}
			bool isInDepth = false;
			if ((0 <= colorPixelMidX) && (colorPixelMidX < m_colorWidth) && (0 <= colorPixelMidY) && (colorPixelMidY < m_colorHeight)){
				point.x = camPoint.X;
				point.y = camPoint.Y;
				point.z = camPoint.Z;
				isInDepth = true;
			}

			if (point.x < camTopLeftBack.X || point.x > camBottomRightBack.X)
				continue;

			if (isInColor && isInDepth){
				depthCloud->push_back(point);
			}
		}
	}

	return true;
}

pcl::PointCloud<pcl::PointXYZRGB>::Ptr ColouredOutputStreamUpdater::convertDepthBufferToPointCloud(RGBQUAD* colorBuffer, UINT16* depthBuffer)
{

	if (m_pDepthVisibilityTestMap.size() == 0 || m_pColorCoordinates.size() == 0){
		return nullptr;
	}

	HRESULT hr;
	auto depthBufferSize = m_depthWidth * m_depthHeight;
	hr = m_pCoordinateMapper->MapDepthFrameToColorSpace(depthBufferSize, depthBuffer,
		depthBufferSize, m_pColorCoordinates.data());

	if (FAILED(hr))
	{
		return nullptr;
	}
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr pointCloud(new pcl::PointCloud<pcl::PointXYZRGB>());
	pointCloud->width = static_cast<uint32_t>(m_depthWidth);
	pointCloud->height = static_cast<uint32_t>(m_depthHeight);
	pointCloud->is_dense = false;

	// construct dense depth points visibility test map so we can test for depth points that are invisible in color space
	const UINT16* const pDepthEnd = depthBuffer + depthBufferSize;
	auto pColorPoint = m_pColorCoordinates.begin();

	const UINT testMapWidth = UINT(m_colorWidth >> PATCHDIVISIONSHIFT);
	const UINT testMapHeight = UINT(m_colorHeight >> PATCHDIVISIONSHIFT);

	ZeroMemory(m_pDepthVisibilityTestMap.data(), testMapWidth * testMapHeight * sizeof(UINT16));

	for (const UINT16* pDepth = depthBuffer; pDepth < pDepthEnd; pDepth++, pColorPoint++)
	{
		const UINT patchColorX = UINT(pColorPoint->X + 0.5f) >> PATCHDIVISIONSHIFT;
		const UINT patchColorY = UINT(pColorPoint->Y + 0.5f) >> PATCHDIVISIONSHIFT;
		if (patchColorX < testMapWidth && patchColorY < testMapHeight)
		{
			const UINT currentPatchIndex = patchColorY * testMapWidth + patchColorX;
			const UINT16 oldDepth = m_pDepthVisibilityTestMap[currentPatchIndex];
			const UINT16 newDepth = *pDepth;
			if (!oldDepth || oldDepth > newDepth)
			{
				m_pDepthVisibilityTestMap[currentPatchIndex] = newDepth;
			}
		}
	}

	for (int yDepthHeight = 0; yDepthHeight < m_depthHeight; yDepthHeight++)
	{
		const UINT testMapWidth = UINT(m_colorWidth >> PATCHDIVISIONSHIFT);

		UINT destIndex = yDepthHeight * m_depthWidth;
		for (UINT xDepthWidth = 0; xDepthWidth < m_depthWidth; ++xDepthWidth, ++destIndex)
		{
			const ColorSpacePoint colorPoint = m_pColorCoordinates[destIndex];
			const UINT colorX = (UINT)(colorPoint.X + 0.5f);
			const UINT colorY = (UINT)(colorPoint.Y + 0.5f);
			if (colorX < m_colorWidth && colorY < m_colorHeight)
			{
				const UINT16 depthValue = depthBuffer[destIndex];
				const UINT testX = colorX >> PATCHDIVISIONSHIFT;
				const UINT testY = colorY >> PATCHDIVISIONSHIFT;
				const UINT testIdx = testY * testMapWidth + testX;
				const UINT16 depthTestValue = m_pDepthVisibilityTestMap[testIdx];

				auto testDiff = std::abs(depthValue - depthTestValue);
				if (testDiff < VISIBILITY_MAX_THRESHHOLD)
				{
					// calculate index into color array
					const UINT colorIndex = colorX + (colorY * m_colorWidth);
					auto pixelColor = colorBuffer[colorIndex];

					DepthSpacePoint depthPoint;
					depthPoint.X = static_cast<float>(xDepthWidth);
					depthPoint.Y = static_cast<float>(yDepthHeight);

					CameraSpacePoint camPoint;
					hr = m_pCoordinateMapper->MapDepthPointToCameraSpace(depthPoint, depthValue, &camPoint);

					if (FAILED(hr)){
						continue;
					}

					pcl::PointXYZRGB point;
					point.x = camPoint.X;
					point.y = camPoint.Y;
					point.z = camPoint.Z;

					point.b = pixelColor.rgbBlue;
					point.g = pixelColor.rgbGreen;
					point.r = pixelColor.rgbRed;

					pointCloud->push_back(point);
				}
			}
		}
	};

	return pointCloud;
}<commit_msg>cleanup<commit_after>#include "ColouredOutputStreamUpdater.h"
#include <pcl/common/centroid.h>
#include <pcl/common/transforms.h>
#include <future>
#include <pcl/filters/voxel_grid.h>
#include <opencv2/imgproc/imgproc.hpp>

#include "stdafx.h"
#include <atlstr.h>
#include <cmath>

ColouredOutputStreamUpdater::ColouredOutputStreamUpdater()
{
}

static const int            PATCHDIVISIONSHIFT = 2 ;
static const UINT16         VISIBILITY_MAX_THRESHHOLD = 50;
ColouredOutputStreamUpdater::~ColouredOutputStreamUpdater()
{
}

void ColouredOutputStreamUpdater::initialize(ICoordinateMapper* m_pCoordinateMapper, int depthWidth, int depthHeight, int colorWidth, int colorHeight)
{
	OutputStreamsUpdaterStragedy::initialize(m_pCoordinateMapper, depthWidth, depthHeight, colorWidth, colorHeight);
	m_pDepthVisibilityTestMap = std::vector<UINT16>((colorWidth >> PATCHDIVISIONSHIFT) * (colorHeight >> PATCHDIVISIONSHIFT));
	m_pColorCoordinates = std::vector<ColorSpacePoint>(depthWidth * depthHeight);
}

void printMessage(std::string msg)
{
	auto msgCstring = CString(msg.c_str());
	msgCstring += L"\n";
	//OutputDebugString(msgCstring);

}
HRESULT ColouredOutputStreamUpdater::updateOutputStreams(IFaceModel* faceModel, IFaceAlignment* faceAlignment, int bufferSize,
	CameraSpacePoint* detectedHDFacePointsCamSpace, ColorSpacePoint* detectedHDFacePointsColorSpace, RGBQUAD* colorBuffer, UINT16* depthBuffer)
{

	HRESULT hr = faceModel->CalculateVerticesForAlignment(faceAlignment, bufferSize, detectedHDFacePointsCamSpace);
	if (SUCCEEDED(hr)){
		hr = m_pCoordinateMapper->MapCameraPointsToColorSpace(bufferSize, detectedHDFacePointsCamSpace, bufferSize, detectedHDFacePointsColorSpace);
	}
	if (SUCCEEDED(hr)){
		CameraSpacePoint boundingBoxPointTopLeft;
		CameraSpacePoint boundingBoxPointBottomRight;
		std::vector<cv::Point2f> hdFacePointsInColorSpaceSpaceOpenCV;

		std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();

		auto hdFaceCloud = extractClolouredFaceHDPoinCloudAndBoundingBox(bufferSize, detectedHDFacePointsCamSpace, detectedHDFacePointsColorSpace,
			boundingBoxPointTopLeft, boundingBoxPointBottomRight, hdFacePointsInColorSpaceSpaceOpenCV, colorBuffer);

		pcl::PointCloud<pcl::PointXYZRGB>::Ptr hdFaceRawDepthCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
		bool isCorrectFrame = extractColouredDepthCloudFromBoundingBox(boundingBoxPointTopLeft, boundingBoxPointBottomRight,
			hdFacePointsInColorSpaceSpaceOpenCV, colorBuffer, depthBuffer, hdFaceRawDepthCloud);
		if (!isCorrectFrame){
			return hr;
		}

		Eigen::Vector4f centroid;
		pcl::compute3DCentroid(*hdFaceCloud, centroid);
		Eigen::Vector3f center(-centroid.x(), -centroid.y(), -centroid.z());
		Eigen::Matrix4f m = Eigen::Affine3f(Eigen::Translation3f(center)).matrix();

		pcl::transformPointCloud(*hdFaceCloud, *hdFaceCloud, m);
		pcl::transformPointCloud(*hdFaceRawDepthCloud, *hdFaceRawDepthCloud, m);

		if (!cloudsUpdated.empty()){
			std::vector<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> updatedClouds;
			updatedClouds.push_back(hdFaceCloud);
			auto fullDepthCloud = convertDepthBufferToPointCloud(colorBuffer, depthBuffer);
			updatedClouds.push_back(fullDepthCloud);
			cloudsUpdated(updatedClouds);
		}
		if (!cloudUpdated[0].empty()){
			cloudUpdated[0](hdFaceCloud);
		}

		if (!cloudUpdated[1].empty()){
			cloudUpdated[1](hdFaceRawDepthCloud);
		}
		if (!cloudUpdated[2].empty()){
			auto fullDepthCloud = convertDepthBufferToPointCloud(colorBuffer, depthBuffer);
			cloudUpdated[2](fullDepthCloud);
		}

	}
	return hr;
}

pcl::PointCloud<pcl::PointXYZRGB>::Ptr ColouredOutputStreamUpdater::extractClolouredFaceHDPoinCloudAndBoundingBox(int bufferSize, CameraSpacePoint* cameraSpacePoints,
	ColorSpacePoint* colorSpacePoints, CameraSpacePoint& camTopLeftBack, CameraSpacePoint& camBottomRightBack, std::vector<cv::Point2f>& hdFacePointsInColorSpaceSpaceOpenCV,
	RGBQUAD* colorBuffer)
{
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud <pcl::PointXYZRGB>());
	cloud->is_dense = false;
	float bottom	=	 FLT_MAX;
	float top		= -	 FLT_MAX;
	float right		= -	 FLT_MAX;
	float left		=	 FLT_MAX;
	float back		=  - FLT_MAX;
	std::vector<cv::Point2f> ellipsePoints;
	for (int i = 0; i < bufferSize; i++){
		const auto& cameraSpacePoint = *cameraSpacePoints;
		const auto& colorSpacePoint = *colorSpacePoints;
		pcl::PointXYZRGB point;
		point.x = cameraSpacePoint.X;
		point.y = cameraSpacePoint.Y;
		point.z = cameraSpacePoint.Z;

		int colorX = static_cast<int>(std::floor(colorSpacePoint.X + 0.5f));
		int colorY = static_cast<int>(std::floor(colorSpacePoint.Y + 0.5f));

		if (colorY > m_colorHeight || colorX > m_colorWidth || colorY < 0 || colorX < 0)
			continue;

		hdFacePointsInColorSpaceSpaceOpenCV.push_back(cv::Point2f(colorX, colorY));

		bottom = std::min(point.y, bottom);
		top = std::max(point.y, top);
		right = std::max(point.x, right);
		left = std::min(point.x, left);
		back = std::max(point.z, back);

		int colorImageIndex = ((m_colorWidth * colorY) + colorX);
		RGBQUAD pixel = colorBuffer[colorImageIndex];
		point.r = pixel.rgbRed;
		point.g = pixel.rgbGreen;
		point.b = pixel.rgbBlue;

		cloud->push_back(point);

		cameraSpacePoints++;
		colorSpacePoints++;
	}

	camTopLeftBack.X = left;
	camTopLeftBack.Y = top;
	camTopLeftBack.Z = back;

	camBottomRightBack.X = right;
	camBottomRightBack.Y = bottom;
	camBottomRightBack.Z = back;

	return cloud;
}

bool ColouredOutputStreamUpdater::extractColouredDepthCloudFromBoundingBox(CameraSpacePoint camTopLeftBack, CameraSpacePoint camBottomRightBack,
	std::vector<cv::Point2f>& hdFacePointsInColorSpaceSpaceOpenCV, RGBQUAD* colorBuffer, UINT16* depthBuffer, pcl::PointCloud<pcl::PointXYZRGB>::Ptr depthCloud)
{

	DepthSpacePoint depthTopLeftBack;
	m_pCoordinateMapper->MapCameraPointToDepthSpace(camTopLeftBack, &depthTopLeftBack);

	DepthSpacePoint depthBottomRightBack;
	m_pCoordinateMapper->MapCameraPointToDepthSpace(camBottomRightBack, &depthBottomRightBack);

	cv::vector<cv::Point2f> hullPoints;
	if (!isValidDepthPoint(depthTopLeftBack) || !isValidDepthPoint(depthBottomRightBack)){
		return false;
	}

	cv::convexHull(hdFacePointsInColorSpaceSpaceOpenCV, hullPoints);
	for (int x = static_cast<int>(depthTopLeftBack.X); x < static_cast<int>(depthBottomRightBack.X); x++){
		for (int y = static_cast<int>(depthTopLeftBack.Y); y < static_cast<int>(depthBottomRightBack.Y); y++){

			pcl::PointXYZRGB point;
			DepthSpacePoint depthPoint;
			depthPoint.X = static_cast<float>(x);
			depthPoint.Y = static_cast<float>(y);

			UINT16 depthOfCurrentPoint = depthBuffer[y * m_depthWidth + x];

			ColorSpacePoint colorPoint;
			HRESULT hr = m_pCoordinateMapper->MapDepthPointToColorSpace(depthPoint, depthOfCurrentPoint, &colorPoint);
			if (FAILED(hr)){
				continue;
			}
			int colorPixelMidX = static_cast<int>(std::floor(colorPoint.X + 0.5f));
			int colorPixelMidY = static_cast<int>(std::floor(colorPoint.Y + 0.5f));
			auto result = cv::pointPolygonTest(hullPoints, cv::Point2f(colorPoint.X, colorPoint.Y), false);
			if (result < 0){
				continue;
			}

			bool isInColor = false;
			if ((0 <= colorPixelMidX) && (colorPixelMidX < m_colorWidth) && (0 <= colorPixelMidY) && (colorPixelMidY < m_colorHeight)){
				RGBQUAD color = colorBuffer[colorPixelMidY * m_colorWidth + colorPixelMidX];
				point.b = color.rgbBlue;
				point.g = color.rgbGreen;
				point.r = color.rgbRed;
				isInColor = true;
			}

			CameraSpacePoint camPoint;

			hr = m_pCoordinateMapper->MapDepthPointToCameraSpace(depthPoint, depthOfCurrentPoint, &camPoint);

			if (FAILED(hr)){
				continue;
			}
			bool isInDepth = false;
			if ((0 <= colorPixelMidX) && (colorPixelMidX < m_colorWidth) && (0 <= colorPixelMidY) && (colorPixelMidY < m_colorHeight)){
				point.x = camPoint.X;
				point.y = camPoint.Y;
				point.z = camPoint.Z;
				isInDepth = true;
			}

			if (point.x < camTopLeftBack.X || point.x > camBottomRightBack.X)
				continue;

			if (isInColor && isInDepth){
				depthCloud->push_back(point);
			}
		}
	}

	return true;
}

pcl::PointCloud<pcl::PointXYZRGB>::Ptr ColouredOutputStreamUpdater::convertDepthBufferToPointCloud(RGBQUAD* colorBuffer, UINT16* depthBuffer)
{

	if (m_pDepthVisibilityTestMap.size() == 0 || m_pColorCoordinates.size() == 0){
		return nullptr;
	}

	HRESULT hr;
	auto depthBufferSize = m_depthWidth * m_depthHeight;
	hr = m_pCoordinateMapper->MapDepthFrameToColorSpace(depthBufferSize, depthBuffer,
		depthBufferSize, m_pColorCoordinates.data());

	if (FAILED(hr))
	{
		return nullptr;
	}
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr pointCloud(new pcl::PointCloud<pcl::PointXYZRGB>());
	pointCloud->width = static_cast<uint32_t>(m_depthWidth);
	pointCloud->height = static_cast<uint32_t>(m_depthHeight);
	pointCloud->is_dense = false;

	const UINT16* const pDepthEnd = depthBuffer + depthBufferSize;
	auto pColorPoint = m_pColorCoordinates.begin();

	const UINT testMapWidth = UINT(m_colorWidth >> PATCHDIVISIONSHIFT);
	const UINT testMapHeight = UINT(m_colorHeight >> PATCHDIVISIONSHIFT);

	ZeroMemory(m_pDepthVisibilityTestMap.data(), testMapWidth * testMapHeight * sizeof(UINT16));

	for (const UINT16* pDepth = depthBuffer; pDepth < pDepthEnd; pDepth++, pColorPoint++)
	{
		const UINT patchColorX = UINT(pColorPoint->X + 0.5f) >> PATCHDIVISIONSHIFT;
		const UINT patchColorY = UINT(pColorPoint->Y + 0.5f) >> PATCHDIVISIONSHIFT;
		if (patchColorX < testMapWidth && patchColorY < testMapHeight)
		{
			const UINT currentPatchIndex = patchColorY * testMapWidth + patchColorX;
			const UINT16 oldDepth = m_pDepthVisibilityTestMap[currentPatchIndex];
			const UINT16 newDepth = *pDepth;
			if (!oldDepth || oldDepth > newDepth)
			{
				m_pDepthVisibilityTestMap[currentPatchIndex] = newDepth;
			}
		}
	}

	for (int yDepthHeight = 0; yDepthHeight < m_depthHeight; yDepthHeight++)
	{
		const UINT testMapWidth = UINT(m_colorWidth >> PATCHDIVISIONSHIFT);

		UINT destIndex = yDepthHeight * m_depthWidth;
		for (UINT xDepthWidth = 0; xDepthWidth < m_depthWidth; ++xDepthWidth, ++destIndex)
		{
			const ColorSpacePoint colorPoint = m_pColorCoordinates[destIndex];
			const UINT colorX = (UINT)(colorPoint.X + 0.5f);
			const UINT colorY = (UINT)(colorPoint.Y + 0.5f);
			if (colorX < m_colorWidth && colorY < m_colorHeight)
			{
				const UINT16 depthValue = depthBuffer[destIndex];
				const UINT testX = colorX >> PATCHDIVISIONSHIFT;
				const UINT testY = colorY >> PATCHDIVISIONSHIFT;
				const UINT testIdx = testY * testMapWidth + testX;
				const UINT16 depthTestValue = m_pDepthVisibilityTestMap[testIdx];

				auto testDiff = std::abs(depthValue - depthTestValue);
				if (testDiff < VISIBILITY_MAX_THRESHHOLD)
				{
					const UINT colorIndex = colorX + (colorY * m_colorWidth);
					auto pixelColor = colorBuffer[colorIndex];

					DepthSpacePoint depthPoint;
					depthPoint.X = static_cast<float>(xDepthWidth);
					depthPoint.Y = static_cast<float>(yDepthHeight);

					CameraSpacePoint camPoint;
					hr = m_pCoordinateMapper->MapDepthPointToCameraSpace(depthPoint, depthValue, &camPoint);

					if (FAILED(hr)){
						continue;
					}

					pcl::PointXYZRGB point;
					point.x = camPoint.X;
					point.y = camPoint.Y;
					point.z = camPoint.Z;

					point.b = pixelColor.rgbBlue;
					point.g = pixelColor.rgbGreen;
					point.r = pixelColor.rgbRed;

					pointCloud->push_back(point);
				}
			}
		}
	};

	return pointCloud;
}<|endoftext|>