<commit_before>/*
** Copyright 2012 Merethis
**
** This file is part of Centreon Clib.
**
** Centreon Clib is free software: you can redistribute it
** and/or modify it under the terms of the GNU Affero General Public
** License as published by the Free Software Foundation, either version
** 3 of the License, or (at your option) any later version.
**
** Centreon Clib 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 Centreon Clib. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cerrno>
#include <cstdlib>
#include <cstring>
#ifdef _WIN32
#  include <direct.h>
#  include <io.h>
#  include <windows.h>
#else
#  include <dirent.h>
#  include <unistd.h>
#endif // _WIN32
#include "com/centreon/exceptions/basic.hh"
#include "com/centreon/io/directory_entry.hh"

#ifdef _WIN32
#  define getcwd _getcwd
#endif // _WIN32

using namespace com::centreon::io;

/**
 *  Constructor.
 *
 *  @param[in] path  The directory path.
 */
directory_entry::directory_entry(char const* path)
  : _entry(path) {

}

/**
 *  Constructor.
 *
 *  @param[in] path  The directory path.
 */
directory_entry::directory_entry(std::string const& path)
  : _entry(path) {

}

/**
 *  Copy constructor.
 *
 *  @param[in] right  The object to copy.
 */
directory_entry::directory_entry(directory_entry const& right) {
  _internal_copy(right);
}

/**
 *  Copy operator.
 *
 *  @param[in] right  The object to copy.
 *
 *  @return This object.
 */
directory_entry& directory_entry::operator=(directory_entry const& right) {
  _internal_copy(right);
  return (*this);
}

/**
 *  Equal operator.
 *
 *  @param[in] right  The object to compare.
 *
 *  @return True if is the same object, owtherwise false.
 */
bool directory_entry::operator==(directory_entry const& right) const throw () {
  return (_entry == right._entry);
}

/**
 *  Not equal operator.
 *
 *  @param[in] right  The object to compare.
 *
 *  @return True if is not the same object, owtherwise false.
 */
bool directory_entry::operator!=(directory_entry const& right) const throw () {
  return (!operator==(right));
}

/**
 *  Destructor.
 */
directory_entry::~directory_entry() throw () {

}

/**
 *  Get the current directory path.
 *
 *  @return The current directory path.
 */
std::string directory_entry::current_path() {
  char* buffer(getcwd(NULL, 0));
  if (!buffer)
    throw (basic_error() << "current path failed");
  std::string path(buffer);
  free(buffer);
  return (path);
}

/**
 *  Get the directory information.
 *
 *  @return The directory entry.
 */
file_entry const& directory_entry::entry() const throw () {
  return (_entry);
}

/**
 *  Get the list of all entry into a directory.
 *
 *  @param[in] filter  An optional filter.
 *
 *  @return The file entry list.
 */
std::list<file_entry> const& directory_entry::entry_list(
                                                std::string const& filter) {
  _entry_lst.clear();
  char const* filter_ptr(filter.empty() ? NULL : filter.c_str());

#ifdef _WIN32
  WIN32_FIND_DATA ffd;
  HANDLE hwd(FindFirstFile(_entry.path().c_str(), &ffd));
  if (hwd == INVALID_HANDLE_VALUE)
    throw (basic_error() << "open directory failed");

  do {
    if (!filter_ptr || _nmatch(ffd.cFileName, filter_ptr))
      _entry_lst.push_back(file_entry(ffd.cFileName));
  } while (FindNextFile(hwd, &ffd) != 0);
  DWORD error(GetLastError());
  FindClose(hwd);
  if (error != ERROR_NO_MORE_FILES)
    throw (basic_error() << "parse directory failed");
#else
  DIR* dir(opendir(_entry.path().c_str()));
  if (!dir) {
    char const* msg(strerror(errno));
    throw (basic_error() << "open directory failed: " << msg);
  }

  dirent entry;
  dirent* result;
  while (true) {
    if (readdir_r(dir, &entry, &result)) {
      closedir(dir);
      throw (basic_error() << "parse directory failed");
    }
    if (!result)
      break;
    if (!filter_ptr || _nmatch(entry.d_name, filter_ptr))
      _entry_lst.push_back(file_entry(entry.d_name));
  }
  closedir(dir);
#endif // _WIN32

  return (_entry_lst);
}

/**
 *  Internal copy.
 *
 *  @param[in] right  The object to copy.
 */
void directory_entry::_internal_copy(directory_entry const& right) {
  if (this != &right) {
    _entry = right._entry;
    _entry_lst = right._entry_lst;
  }
}

/**
 *  Check if a string match a pattern.
 *
 *  @param[in] str      The string to check.
 *  @param[in] pattern  The partter to match.
 *
 *  @return 1 on success, otherwiswe 0.
 */
int directory_entry::_nmatch(char const* str, char const* pattern) {
  if (!*str && !*pattern)
    return (1);
  if (*str == *pattern)
    return (_nmatch(str + 1, pattern + 1));
  return (*pattern == '*'
          ? (*str
             ? _nmatch(str + 1, pattern)
             : 0) + _nmatch(str, pattern + 1)
          : 0);
}
<commit_msg>Fix directory entry list files.<commit_after>/*
** Copyright 2012 Merethis
**
** This file is part of Centreon Clib.
**
** Centreon Clib is free software: you can redistribute it
** and/or modify it under the terms of the GNU Affero General Public
** License as published by the Free Software Foundation, either version
** 3 of the License, or (at your option) any later version.
**
** Centreon Clib 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 Centreon Clib. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cerrno>
#include <cstdlib>
#include <cstring>
#ifdef _WIN32
#  include <direct.h>
#  include <io.h>
#  include <windows.h>
#else
#  include <dirent.h>
#  include <unistd.h>
#endif // _WIN32
#include "com/centreon/exceptions/basic.hh"
#include "com/centreon/io/directory_entry.hh"

#ifdef _WIN32
#  define getcwd _getcwd
#endif // _WIN32

using namespace com::centreon::io;

/**
 *  Constructor.
 *
 *  @param[in] path  The directory path.
 */
directory_entry::directory_entry(char const* path)
  : _entry(path) {

}

/**
 *  Constructor.
 *
 *  @param[in] path  The directory path.
 */
directory_entry::directory_entry(std::string const& path)
  : _entry(path) {

}

/**
 *  Copy constructor.
 *
 *  @param[in] right  The object to copy.
 */
directory_entry::directory_entry(directory_entry const& right) {
  _internal_copy(right);
}

/**
 *  Copy operator.
 *
 *  @param[in] right  The object to copy.
 *
 *  @return This object.
 */
directory_entry& directory_entry::operator=(directory_entry const& right) {
  _internal_copy(right);
  return (*this);
}

/**
 *  Equal operator.
 *
 *  @param[in] right  The object to compare.
 *
 *  @return True if is the same object, owtherwise false.
 */
bool directory_entry::operator==(directory_entry const& right) const throw () {
  return (_entry == right._entry);
}

/**
 *  Not equal operator.
 *
 *  @param[in] right  The object to compare.
 *
 *  @return True if is not the same object, owtherwise false.
 */
bool directory_entry::operator!=(directory_entry const& right) const throw () {
  return (!operator==(right));
}

/**
 *  Destructor.
 */
directory_entry::~directory_entry() throw () {

}

/**
 *  Get the current directory path.
 *
 *  @return The current directory path.
 */
std::string directory_entry::current_path() {
  char* buffer(getcwd(NULL, 0));
  if (!buffer)
    throw (basic_error() << "current path failed");
  std::string path(buffer);
  free(buffer);
  return (path);
}

/**
 *  Get the directory information.
 *
 *  @return The directory entry.
 */
file_entry const& directory_entry::entry() const throw () {
  return (_entry);
}

/**
 *  Get the list of all entry into a directory.
 *
 *  @param[in] filter  An optional filter.
 *
 *  @return The file entry list.
 */
std::list<file_entry> const& directory_entry::entry_list(
                                                std::string const& filter) {
  _entry_lst.clear();
  char const* filter_ptr(filter.empty() ? NULL : filter.c_str());

#ifdef _WIN32
  WIN32_FIND_DATA ffd;
  HANDLE hwd(FindFirstFile(_entry.path().c_str(), &ffd));
  if (hwd == INVALID_HANDLE_VALUE)
    throw (basic_error() << "open directory failed");

  do {
    if (!filter_ptr || _nmatch(ffd.cFileName, filter_ptr))
      _entry_lst.push_back(file_entry(ffd.cFileName));
  } while (FindNextFile(hwd, &ffd) != 0);
  DWORD error(GetLastError());
  FindClose(hwd);
  if (error != ERROR_NO_MORE_FILES)
    throw (basic_error() << "parse directory failed");
#else
  DIR* dir(opendir(_entry.path().c_str()));
  if (!dir) {
    char const* msg(strerror(errno));
    throw (basic_error() << "open directory failed: " << msg);
  }

  dirent entry;
  dirent* result;
  while (true) {
    if (readdir_r(dir, &entry, &result)) {
      closedir(dir);
      throw (basic_error() << "parse directory failed");
    }
    if (!result)
      break;
    if (!filter_ptr || _nmatch(entry.d_name, filter_ptr))
      _entry_lst.push_back(file_entry(_entry.path() + "/" + entry.d_name));
  }
  closedir(dir);
#endif // _WIN32

  return (_entry_lst);
}

/**
 *  Internal copy.
 *
 *  @param[in] right  The object to copy.
 */
void directory_entry::_internal_copy(directory_entry const& right) {
  if (this != &right) {
    _entry = right._entry;
    _entry_lst = right._entry_lst;
  }
}

/**
 *  Check if a string match a pattern.
 *
 *  @param[in] str      The string to check.
 *  @param[in] pattern  The partter to match.
 *
 *  @return 1 on success, otherwiswe 0.
 */
int directory_entry::_nmatch(char const* str, char const* pattern) {
  if (!*str && !*pattern)
    return (1);
  if (*str == *pattern)
    return (_nmatch(str + 1, pattern + 1));
  return (*pattern == '*'
          ? (*str
             ? _nmatch(str + 1, pattern)
             : 0) + _nmatch(str, pattern + 1)
          : 0);
}
<|endoftext|>


<commit_before>#include <openspace/util/openspacemodule.h>
#include <openspace/documentation/documentation.h>
#include <modules/skybrowser/skybrowsermodule.h>
#include <modules/skybrowser/include/utility.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/misc/dictionaryluaformatter.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/fmt.h>
#include <ghoul/glm.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
#include <fstream>
#include <sstream>
#include <modules/skybrowser/include/screenspaceskybrowser.h>
#include <modules/skybrowser/include/screenspaceskytarget.h>
#include <modules/base/rendering/screenspaceimagelocal.h>
#include <modules/base/rendering/renderableplaneimagelocal.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/util/camera.h>
#include <thread>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <limits>

namespace {
	constexpr const char _loggerCat[] = "SkyBrowserModule";
} // namespace

namespace openspace::skybrowser::luascriptfunctions {

	int selectImage(lua_State* L) {
		// Load image
		ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::selectImage");
		const int i = ghoul::lua::value<int>(L, 1);

		ScreenSpaceSkyBrowser* browser = dynamic_cast<ScreenSpaceSkyBrowser*>(global::renderEngine->screenSpaceRenderable("SkyBrowser1"));
		SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
		const ImageData& resultImage = module->getWWTDataHandler()->getLoadedImages()[i];
		// Load image collection, if it isn't loaded already
        // TODO: Update or remove with new WWT API
		const std::vector<ImageCollection>& collections = module->getWWTDataHandler()->getAllImageCollectionUrls();
		auto it = std::find_if(collections.begin(), collections.end(), [&](const ImageCollection& coll) {
				return coll.name == resultImage.collection;
			});
		if (!it->loaded) {
			browser->sendMessageToWWT(browser->createMessageForLoadingWWTImgColl(it->url));
		}
        LINFO("Loading image " + resultImage.name);
		browser->sendMessageToWWT(browser->createMessageForSettingForegroundWWT(resultImage.name));
        browser->sendMessageToWWT(browser->createMessageForSettingForegroundOpacityWWT(100));

		// Only move target if the image has coordinates
		if (resultImage.hasCoords) {
            // Animate the target to the image coord position
            // In WWT, the definition of ZoomLevel is: VFOV = ZoomLevel / 6
            if (browser->getSkyTarget()) {
                browser->getSkyTarget()->unlock();
                browser->getSkyTarget()->startAnimation(resultImage.celestCoords, resultImage.zoomLevel / 6);
            }
		}
		return 0;
	}

    int moveCircleToHoverImage(lua_State* L) {
        // Load image
        ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::moveCircleToHoverImage");
        const int i = ghoul::lua::value<int>(L, 1);
        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
        const ImageData& resultImage = module->getWWTDataHandler()->getLoadedImages()[i];

        // Only move and show circle if the image has coordinates
        if (resultImage.hasCoords) {
            // Make circle visible
            ScreenSpaceImageLocal* hoverCircle = dynamic_cast<ScreenSpaceImageLocal*>(global::renderEngine->screenSpaceRenderable("HoverCircle"));
            hoverCircle->property("Enabled")->set(true);
            // Calculate coords for the circle and translate
            glm::vec3 imageCoordsScreenSpace = skybrowser::J2000SphericalToScreenSpace(resultImage.celestCoords);
            hoverCircle->property("CartesianPosition")->set(imageCoordsScreenSpace);
        }

        return 0;
    }

    int disableHoverCircle(lua_State* L) {
        ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::disableHoverCircle");
        ScreenSpaceImageLocal* hoverCircle = dynamic_cast<ScreenSpaceImageLocal*>(global::renderEngine->screenSpaceRenderable("HoverCircle"));
        hoverCircle->property("Enabled")->set(false);

        return 0;
    }

    int lockTarget(lua_State* L) {
        ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::lockTarget");
        const int i = ghoul::lua::value<int>(L, 1);
        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
        std::vector<ScreenSpaceSkyBrowser*> browsers = module->getSkyBrowsers();
        ScreenSpaceSkyTarget* target = browsers[i]->getSkyTarget();
        if (i < browsers.size()) {
            ScreenSpaceSkyTarget* target = browsers[i]->getSkyTarget();
            if (target) {
                target->lock();
            }
        }
        return 0;
    }

    int unlockTarget(lua_State* L) {
        ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::unlockTarget");
        const int i = ghoul::lua::value<int>(L, 1);
        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
        std::vector<ScreenSpaceSkyBrowser*> browsers = module->getSkyBrowsers();
        if (i < browsers.size()) {
            ScreenSpaceSkyTarget* target = browsers[i]->getSkyTarget();
            if (target) {
                target->unlock();
            }
        }
        return 0;
    }

	int followCamera(lua_State* L) {
		// Load images from url
		ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::followCamera");
        LINFO("Loading images from url");
		SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
		std::string root = "https://raw.githubusercontent.com/WorldWideTelescope/wwt-web-client/master/assets/webclient-explore-root.wtml";
        std::string hubble = "http://www.worldwidetelescope.org/wwtweb/catalog.aspx?W=hubble";

		module->getWWTDataHandler()->loadWTMLCollectionsFromURL(hubble, "root");
		LINFO(std::to_string( module->getWWTDataHandler()->loadAllImagesFromXMLs()));

		return 1;
	}

	int moveBrowser(lua_State* L) {
		// Load images from local directory
		ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::moveBrowser");
		SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
		module->getWWTDataHandler()->loadWTMLCollectionsFromDirectory(absPath("${MODULE_SKYBROWSER}/WWTimagedata/"));
		std::string noOfLoadedImgs = std::to_string(module->getWWTDataHandler()->loadAllImagesFromXMLs());
		LINFO("Loaded " + noOfLoadedImgs + " WorldWide Telescope images.");

		ScreenSpaceSkyBrowser* browser = dynamic_cast<ScreenSpaceSkyBrowser*>(global::renderEngine->screenSpaceRenderable("SkyBrowser1"));
        // Load all image collection urls
		//const std::vector<std::string>& imageUrls = module->getWWTDataHandler()->getAllImageCollectionUrls();
		//for (const std::string url : imageUrls) {
		//    browser->sendMessageToWWT(browser->createMessageForLoadingWWTImgColl(url));
		//}
		std::string root = "https://raw.githubusercontent.com/WorldWideTelescope/wwt-web-client/master/assets/webclient-explore-root.wtml";
        std::string hubble = "http://www.worldwidetelescope.org/wwtweb/catalog.aspx?W=hubble";
		browser->sendMessageToWWT(browser->createMessageForLoadingWWTImgColl(hubble));
		return 1;
	}

	int getListOfImages(lua_State* L) {
		// Send image list to GUI
		ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfImages");
		SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
		// If no data has been loaded yet, load it!
		if (module->getWWTDataHandler()->getLoadedImages().size() == 0) {
            // Read from disc
			//moveBrowser(L);
            // Read from URL
			 followCamera(L);
		}

        // Create Lua table to send to the GUI
		const std::vector<ImageData>& images = module->getWWTDataHandler()->getLoadedImages();
        lua_newtable(L);

		for (int i = 0; i < images.size(); i++) {
            std::string name = images[i].name != "" ? images[i].name : "undefined";
            std::string url = images[i].thumbnailUrl != "" ? images[i].thumbnailUrl : "undefined";

            // Index for current ImageData
            ghoul::lua::push(L, i + 1);
            lua_newtable(L);
            // Push ("Key", value)
            ghoul::lua::push(L, "Name", name);
            lua_settable(L, -3);
            ghoul::lua::push(L, "Thumbnail", url);
            lua_settable(L, -3);
            ghoul::lua::push(L, "RA", images[i].celestCoords.x);
            lua_settable(L, -3);
            ghoul::lua::push(L, "Dec", images[i].celestCoords.y);
            lua_settable(L, -3);
            ghoul::lua::push(L, "HasCoords", images[i].hasCoords);
            lua_settable(L, -3);
            ghoul::lua::push(L, "Credits", images[i].credits);
            lua_settable(L, -3);
            ghoul::lua::push(L, "CreditsUrl", images[i].creditsUrl);
            lua_settable(L, -3);
            ghoul::lua::push(L, "Index", i);
            lua_settable(L, -3);
            // Set table for the current ImageData
            lua_settable(L, -3);
		}

		return 1;
	}

    int getTargetData(lua_State* L) {
        // Send image list to GUI
        ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getTargetData");

        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();

        lua_newtable(L);
        int index = 1;
        // Pass data for all the browsers and the corresponding targets
        std::vector<ScreenSpaceSkyBrowser*> browsers = module->getSkyBrowsers();

        for (int i = 0; i < browsers.size(); i++) {
            // Only add browsers that have an initialized target
            ScreenSpaceSkyTarget* target = browsers[i]->getSkyTarget();
            if (target) {
                glm::dvec3 coords = target->getTargetDirectionGalactic();
                glm::dvec2 celestCoords = skybrowser::galacticCartesianToJ2000(coords);
                // Convert color to vector so ghoul can read it
                glm::ivec3 color = browsers[i]->_borderColor.value();
                std::vector<int> colorVec = { color.r, color.g, color.b };

                ghoul::lua::push(L, index);
                index++;
                lua_newtable(L);
                // Push ("Key", value)
                ghoul::lua::push(L, "FOV", browsers[i]->fieldOfView());
                lua_settable(L, -3);
                ghoul::lua::push(L, "RA", celestCoords.x);
                lua_settable(L, -3);
                ghoul::lua::push(L, "Dec", celestCoords.y);
                lua_settable(L, -3);
                ghoul::lua::push(L, "Color", colorVec);
                lua_settable(L, -3);

                // Set table for the current ImageData
                lua_settable(L, -3);
            }
        }

        return 1;
    }
	int adjustCamera(lua_State* L) {
		ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::adjustCamera");
		return 0;
	}

}

<commit_msg>Send window FOV and direction to GUI<commit_after>#include <openspace/util/openspacemodule.h>
#include <openspace/documentation/documentation.h>
#include <modules/skybrowser/skybrowsermodule.h>
#include <modules/skybrowser/include/utility.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/misc/dictionaryluaformatter.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/fmt.h>
#include <ghoul/glm.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
#include <fstream>
#include <sstream>
#include <modules/skybrowser/include/screenspaceskybrowser.h>
#include <modules/skybrowser/include/screenspaceskytarget.h>
#include <modules/base/rendering/screenspaceimagelocal.h>
#include <modules/base/rendering/renderableplaneimagelocal.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/util/camera.h>
#include <thread>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <limits>

namespace {
	constexpr const char _loggerCat[] = "SkyBrowserModule";
} // namespace

namespace openspace::skybrowser::luascriptfunctions {

	int selectImage(lua_State* L) {
		// Load image
		ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::selectImage");
		const int i = ghoul::lua::value<int>(L, 1);

		ScreenSpaceSkyBrowser* browser = dynamic_cast<ScreenSpaceSkyBrowser*>(global::renderEngine->screenSpaceRenderable("SkyBrowser1"));
		SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
		const ImageData& resultImage = module->getWWTDataHandler()->getLoadedImages()[i];
		// Load image collection, if it isn't loaded already
        // TODO: Update or remove with new WWT API
		const std::vector<ImageCollection>& collections = module->getWWTDataHandler()->getAllImageCollectionUrls();
		auto it = std::find_if(collections.begin(), collections.end(), [&](const ImageCollection& coll) {
				return coll.name == resultImage.collection;
			});
		if (!it->loaded) {
			browser->sendMessageToWWT(browser->createMessageForLoadingWWTImgColl(it->url));
		}
        LINFO("Loading image " + resultImage.name);
		browser->sendMessageToWWT(browser->createMessageForSettingForegroundWWT(resultImage.name));
        browser->sendMessageToWWT(browser->createMessageForSettingForegroundOpacityWWT(100));

		// Only move target if the image has coordinates
		if (resultImage.hasCoords) {
            // Animate the target to the image coord position
            // In WWT, the definition of ZoomLevel is: VFOV = ZoomLevel / 6
            if (browser->getSkyTarget()) {
                browser->getSkyTarget()->unlock();
                browser->getSkyTarget()->startAnimation(resultImage.celestCoords, resultImage.zoomLevel / 6);
            }
		}
		return 0;
	}

    int moveCircleToHoverImage(lua_State* L) {
        // Load image
        ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::moveCircleToHoverImage");
        const int i = ghoul::lua::value<int>(L, 1);
        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
        const ImageData& resultImage = module->getWWTDataHandler()->getLoadedImages()[i];

        // Only move and show circle if the image has coordinates
        if (resultImage.hasCoords) {
            // Make circle visible
            ScreenSpaceImageLocal* hoverCircle = dynamic_cast<ScreenSpaceImageLocal*>(global::renderEngine->screenSpaceRenderable("HoverCircle"));
            hoverCircle->property("Enabled")->set(true);
            // Calculate coords for the circle and translate
            glm::vec3 imageCoordsScreenSpace = skybrowser::J2000SphericalToScreenSpace(resultImage.celestCoords);
            hoverCircle->property("CartesianPosition")->set(imageCoordsScreenSpace);
        }

        return 0;
    }

    int disableHoverCircle(lua_State* L) {
        ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::disableHoverCircle");
        ScreenSpaceImageLocal* hoverCircle = dynamic_cast<ScreenSpaceImageLocal*>(global::renderEngine->screenSpaceRenderable("HoverCircle"));
        hoverCircle->property("Enabled")->set(false);

        return 0;
    }

    int lockTarget(lua_State* L) {
        ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::lockTarget");
        const int i = ghoul::lua::value<int>(L, 1);
        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
        std::vector<ScreenSpaceSkyBrowser*> browsers = module->getSkyBrowsers();
        ScreenSpaceSkyTarget* target = browsers[i]->getSkyTarget();
        if (i < browsers.size()) {
            ScreenSpaceSkyTarget* target = browsers[i]->getSkyTarget();
            if (target) {
                target->lock();
            }
        }
        return 0;
    }

    int unlockTarget(lua_State* L) {
        ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::unlockTarget");
        const int i = ghoul::lua::value<int>(L, 1);
        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
        std::vector<ScreenSpaceSkyBrowser*> browsers = module->getSkyBrowsers();
        if (i < browsers.size()) {
            ScreenSpaceSkyTarget* target = browsers[i]->getSkyTarget();
            if (target) {
                target->unlock();
            }
        }
        return 0;
    }

	int followCamera(lua_State* L) {
		// Load images from url
		ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::followCamera");
        LINFO("Loading images from url");
		SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
		std::string root = "https://raw.githubusercontent.com/WorldWideTelescope/wwt-web-client/master/assets/webclient-explore-root.wtml";
        std::string hubble = "http://www.worldwidetelescope.org/wwtweb/catalog.aspx?W=hubble";

		module->getWWTDataHandler()->loadWTMLCollectionsFromURL(hubble, "root");
		LINFO(std::to_string( module->getWWTDataHandler()->loadAllImagesFromXMLs()));

		return 1;
	}

	int moveBrowser(lua_State* L) {
		// Load images from local directory
		ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::moveBrowser");
		SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
		module->getWWTDataHandler()->loadWTMLCollectionsFromDirectory(absPath("${MODULE_SKYBROWSER}/WWTimagedata/"));
		std::string noOfLoadedImgs = std::to_string(module->getWWTDataHandler()->loadAllImagesFromXMLs());
		LINFO("Loaded " + noOfLoadedImgs + " WorldWide Telescope images.");

		ScreenSpaceSkyBrowser* browser = dynamic_cast<ScreenSpaceSkyBrowser*>(global::renderEngine->screenSpaceRenderable("SkyBrowser1"));
        // Load all image collection urls
		//const std::vector<std::string>& imageUrls = module->getWWTDataHandler()->getAllImageCollectionUrls();
		//for (const std::string url : imageUrls) {
		//    browser->sendMessageToWWT(browser->createMessageForLoadingWWTImgColl(url));
		//}
		std::string root = "https://raw.githubusercontent.com/WorldWideTelescope/wwt-web-client/master/assets/webclient-explore-root.wtml";
        std::string hubble = "http://www.worldwidetelescope.org/wwtweb/catalog.aspx?W=hubble";
		browser->sendMessageToWWT(browser->createMessageForLoadingWWTImgColl(hubble));
		return 1;
	}

	int getListOfImages(lua_State* L) {
		// Send image list to GUI
		ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfImages");
		SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
		// If no data has been loaded yet, load it!
		if (module->getWWTDataHandler()->getLoadedImages().size() == 0) {
            // Read from disc
			//moveBrowser(L);
            // Read from URL
			 followCamera(L);
		}

        // Create Lua table to send to the GUI
		const std::vector<ImageData>& images = module->getWWTDataHandler()->getLoadedImages();
        lua_newtable(L);

		for (int i = 0; i < images.size(); i++) {
            std::string name = images[i].name != "" ? images[i].name : "undefined";
            std::string url = images[i].thumbnailUrl != "" ? images[i].thumbnailUrl : "undefined";

            // Index for current ImageData
            ghoul::lua::push(L, i + 1);
            lua_newtable(L);
            // Push ("Key", value)
            ghoul::lua::push(L, "Name", name);
            lua_settable(L, -3);
            ghoul::lua::push(L, "Thumbnail", url);
            lua_settable(L, -3);
            ghoul::lua::push(L, "RA", images[i].celestCoords.x);
            lua_settable(L, -3);
            ghoul::lua::push(L, "Dec", images[i].celestCoords.y);
            lua_settable(L, -3);
            ghoul::lua::push(L, "HasCoords", images[i].hasCoords);
            lua_settable(L, -3);
            ghoul::lua::push(L, "Credits", images[i].credits);
            lua_settable(L, -3);
            ghoul::lua::push(L, "CreditsUrl", images[i].creditsUrl);
            lua_settable(L, -3);
            ghoul::lua::push(L, "Index", i);
            lua_settable(L, -3);
            // Set table for the current ImageData
            lua_settable(L, -3);
		}

		return 1;
	}

    int getTargetData(lua_State* L) {
        // Send image list to GUI
        ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getTargetData");

        SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();

        lua_newtable(L);
        int index = 1;

        // Add the window data for OpenSpace
        ghoul::lua::push(L, index);
        index++;
        lua_newtable(L);
        // Calculate camera view direction in celestial spherical coordinates
        glm::dvec3 viewDir = global::navigationHandler->camera()->viewDirectionWorldSpace();
        glm::dvec2 viewDirCelest = skybrowser::galacticCartesianToJ2000(viewDir);
        // Convert to vector so ghoul can read it
        std::vector<double> viewDirCelestVec = { viewDirCelest.x, viewDirCelest.y };
        // Calculate the smallest FOV of vertical and horizontal
        float HFOV = global::windowDelegate->getHorizFieldOfView();
        glm::vec2 windowRatio = global::windowDelegate->currentWindowSize();
        float VFOV = HFOV * (windowRatio.y / windowRatio.x);
        double FOV = std::min(HFOV, VFOV);
        // Push window data
        ghoul::lua::push(L, "WindowHFOV", FOV);
        lua_settable(L, -3);
        ghoul::lua::push(L, "WindowDirection", viewDirCelestVec);
        lua_settable(L, -3);
        // Set table for the current ImageData
        lua_settable(L, -3);

        // Pass data for all the browsers and the corresponding targets
        std::vector<ScreenSpaceSkyBrowser*> browsers = module->getSkyBrowsers();

        for (int i = 0; i < browsers.size(); i++) {
            // Only add browsers that have an initialized target
            ScreenSpaceSkyTarget* target = browsers[i]->getSkyTarget();
            if (target) {
                glm::dvec3 coords = target->getTargetDirectionGalactic();
                glm::dvec2 celestCoords = skybrowser::galacticCartesianToJ2000(coords);
                // Convert color to vector so ghoul can read it
                glm::ivec3 color = browsers[i]->_borderColor.value();
                std::vector<int> colorVec = { color.r, color.g, color.b };

                ghoul::lua::push(L, index);
                index++;
                lua_newtable(L);
                // Push ("Key", value)
                ghoul::lua::push(L, "FOV", browsers[i]->fieldOfView());
                lua_settable(L, -3);
                ghoul::lua::push(L, "RA", celestCoords.x);
                lua_settable(L, -3);
                ghoul::lua::push(L, "Dec", celestCoords.y);
                lua_settable(L, -3);
                ghoul::lua::push(L, "Color", colorVec);
                lua_settable(L, -3);

                // Set table for the current target
                lua_settable(L, -3);
            }
        }

        return 1;
    }
	int adjustCamera(lua_State* L) {
		ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::adjustCamera");
		return 0;
	}

}

<|endoftext|>


<commit_before>// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "m2ts/webm2pes.h"

#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <string>
#include <vector>

#include "gtest/gtest.h"

#include "common/file_util.h"
#include "common/libwebm_util.h"
#include "m2ts/vpxpes_parser.h"
#include "testing/test_util.h"

namespace {

class Webm2PesTests : public ::testing::Test {
 public:
  // Constants for validating known values from input data.
  const std::uint8_t kMinVideoStreamId = 0xE0;
  const std::uint8_t kMaxVideoStreamId = 0xEF;
  const int kPesHeaderSize = 6;
  const int kPesOptionalHeaderStartOffset = kPesHeaderSize;
  const int kPesOptionalHeaderSize = 9;
  const int kPesOptionalHeaderMarkerValue = 0x2;
  const int kWebm2PesOptHeaderRemainingSize = 6;
  const int kBcmvHeaderSize = 10;

  Webm2PesTests() = default;
  ~Webm2PesTests() = default;

  void CreateAndLoadTestInput() {
    libwebm::Webm2Pes converter(input_file_name_, temp_file_name_.name());
    ASSERT_TRUE(converter.ConvertToFile());
    ASSERT_TRUE(parser_.Open(pes_file_name()));
  }

  bool VerifyPacketStartCode(const libwebm::VpxPesParser::PesHeader& header) {
    // PES packets all start with the byte sequence 0x0 0x0 0x1.
    if (header.start_code[0] != 0 || header.start_code[1] != 0 ||
        header.start_code[2] != 1) {
      return false;
    }
    return true;
  }

  const std::string& pes_file_name() const { return temp_file_name_.name(); }
  libwebm::VpxPesParser* parser() { return &parser_; }

 private:
  const libwebm::TempFileDeleter temp_file_name_;
  const std::string input_file_name_ =
      test::GetTestFilePath("bbb_480p_vp9_opus_1second.webm");
  libwebm::VpxPesParser parser_;
};

TEST_F(Webm2PesTests, CreatePesFile) { CreateAndLoadTestInput(); }

TEST_F(Webm2PesTests, CanParseFirstPacket) {
  CreateAndLoadTestInput();
  libwebm::VpxPesParser::PesHeader header;
  libwebm::VideoFrame frame;
  ASSERT_TRUE(parser()->ParseNextPacket(&header, &frame));
  EXPECT_TRUE(VerifyPacketStartCode(header));

  //   9 bytes: PES optional header
  //  10 bytes: BCMV Header
  //  83 bytes: frame
  // 102 bytes total in packet length field:
  const std::size_t kPesPayloadLength = 102;
  EXPECT_EQ(kPesPayloadLength, header.packet_length);

  EXPECT_GE(header.stream_id, kMinVideoStreamId);
  EXPECT_LE(header.stream_id, kMaxVideoStreamId);

  // Test PesOptionalHeader values.
  EXPECT_EQ(kPesOptionalHeaderMarkerValue, header.opt_header.marker);
  EXPECT_EQ(kWebm2PesOptHeaderRemainingSize, header.opt_header.remaining_size);
  EXPECT_EQ(0, header.opt_header.scrambling);
  EXPECT_EQ(0, header.opt_header.priority);
  EXPECT_EQ(0, header.opt_header.data_alignment);
  EXPECT_EQ(0, header.opt_header.copyright);
  EXPECT_EQ(0, header.opt_header.original);
  EXPECT_EQ(1, header.opt_header.has_pts);
  EXPECT_EQ(0, header.opt_header.has_dts);
  EXPECT_EQ(0, header.opt_header.unused_fields);

  // Test the BCMV header.
  // Note: The length field of the BCMV header includes its own length.
  const std::size_t kBcmvBaseLength = 10;
  const std::size_t kFirstFrameLength = 83;
  const libwebm::VpxPesParser::BcmvHeader kFirstBcmvHeader(kFirstFrameLength +
                                                           kBcmvBaseLength);
  EXPECT_TRUE(header.bcmv_header.Valid());
  EXPECT_EQ(kFirstBcmvHeader, header.bcmv_header);

  // Parse the next packet to confirm correct parse and consumption of payload.
  EXPECT_TRUE(parser()->ParseNextPacket(&header, &frame));
}

}  // namespace

int main(int argc, char* argv[]) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>webm2pes: Add test for mux/demux of large input.<commit_after>// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "m2ts/webm2pes.h"

#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>

#include "gtest/gtest.h"

#include "common/file_util.h"
#include "common/libwebm_util.h"
#include "m2ts/vpxpes_parser.h"
#include "testing/test_util.h"

namespace {

class Webm2PesTests : public ::testing::Test {
 public:
  // Constants for validating known values from input data.
  const std::uint8_t kMinVideoStreamId = 0xE0;
  const std::uint8_t kMaxVideoStreamId = 0xEF;
  const int kPesHeaderSize = 6;
  const int kPesOptionalHeaderStartOffset = kPesHeaderSize;
  const int kPesOptionalHeaderSize = 9;
  const int kPesOptionalHeaderMarkerValue = 0x2;
  const int kWebm2PesOptHeaderRemainingSize = 6;
  const int kBcmvHeaderSize = 10;

  Webm2PesTests() = default;
  ~Webm2PesTests() = default;

  void CreateAndLoadTestInput() {
    libwebm::Webm2Pes converter(input_file_name_, temp_file_name_.name());
    ASSERT_TRUE(converter.ConvertToFile());
    ASSERT_TRUE(parser_.Open(pes_file_name()));
  }

  bool VerifyPacketStartCode(const libwebm::VpxPesParser::PesHeader& header) {
    // PES packets all start with the byte sequence 0x0 0x0 0x1.
    if (header.start_code[0] != 0 || header.start_code[1] != 0 ||
        header.start_code[2] != 1) {
      return false;
    }
    return true;
  }

  const std::string& pes_file_name() const { return temp_file_name_.name(); }
  libwebm::VpxPesParser* parser() { return &parser_; }

 private:
  const libwebm::TempFileDeleter temp_file_name_;
  const std::string input_file_name_ =
      test::GetTestFilePath("bbb_480p_vp9_opus_1second.webm");
  libwebm::VpxPesParser parser_;
};

TEST_F(Webm2PesTests, CreatePesFile) { CreateAndLoadTestInput(); }

TEST_F(Webm2PesTests, CanParseFirstPacket) {
  CreateAndLoadTestInput();
  libwebm::VpxPesParser::PesHeader header;
  libwebm::VideoFrame frame;
  ASSERT_TRUE(parser()->ParseNextPacket(&header, &frame));
  EXPECT_TRUE(VerifyPacketStartCode(header));

  //   9 bytes: PES optional header
  //  10 bytes: BCMV Header
  //  83 bytes: frame
  // 102 bytes total in packet length field:
  const std::size_t kPesPayloadLength = 102;
  EXPECT_EQ(kPesPayloadLength, header.packet_length);

  EXPECT_GE(header.stream_id, kMinVideoStreamId);
  EXPECT_LE(header.stream_id, kMaxVideoStreamId);

  // Test PesOptionalHeader values.
  EXPECT_EQ(kPesOptionalHeaderMarkerValue, header.opt_header.marker);
  EXPECT_EQ(kWebm2PesOptHeaderRemainingSize, header.opt_header.remaining_size);
  EXPECT_EQ(0, header.opt_header.scrambling);
  EXPECT_EQ(0, header.opt_header.priority);
  EXPECT_EQ(0, header.opt_header.data_alignment);
  EXPECT_EQ(0, header.opt_header.copyright);
  EXPECT_EQ(0, header.opt_header.original);
  EXPECT_EQ(1, header.opt_header.has_pts);
  EXPECT_EQ(0, header.opt_header.has_dts);
  EXPECT_EQ(0, header.opt_header.unused_fields);

  // Test the BCMV header.
  // Note: The length field of the BCMV header includes its own length.
  const std::size_t kBcmvBaseLength = 10;
  const std::size_t kFirstFrameLength = 83;
  const libwebm::VpxPesParser::BcmvHeader kFirstBcmvHeader(kFirstFrameLength +
                                                           kBcmvBaseLength);
  EXPECT_TRUE(header.bcmv_header.Valid());
  EXPECT_EQ(kFirstBcmvHeader, header.bcmv_header);

  // Parse the next packet to confirm correct parse and consumption of payload.
  EXPECT_TRUE(parser()->ParseNextPacket(&header, &frame));
}

TEST_F(Webm2PesTests, CanMuxLargeBuffers) {
  const std::size_t kBufferSize = 100 * 1024;
  const std::int64_t kFakeTimestamp = libwebm::kNanosecondsPerSecond;
  libwebm::VideoFrame fake_frame(kFakeTimestamp, libwebm::VideoFrame::kVP9);
  ASSERT_TRUE(fake_frame.Init(kBufferSize));
  std::memset(fake_frame.buffer().data.get(), 0x80, kBufferSize);
  ASSERT_TRUE(fake_frame.SetBufferLength(kBufferSize));
  libwebm::PacketDataBuffer pes_packet_buffer;
  ASSERT_TRUE(
      libwebm::Webm2Pes::WritePesPacket(fake_frame, &pes_packet_buffer));

  // TODO(tomfinegan): Change VpxPesParser so it can read from a buffer, and get
  // rid of this extra step.
  libwebm::FilePtr pes_file(std::fopen(pes_file_name().c_str(), "wb"),
                            libwebm::FILEDeleter());
  ASSERT_EQ(pes_packet_buffer.size(),
            fwrite(&pes_packet_buffer[0], 1, pes_packet_buffer.size(),
                   pes_file.get()));
  fclose(pes_file.get());
  pes_file.release();

  libwebm::VpxPesParser parser;
  ASSERT_TRUE(parser.Open(pes_file_name()));
  libwebm::VpxPesParser::PesHeader header;
  libwebm::VideoFrame parsed_frame;
  ASSERT_TRUE(parser.ParseNextPacket(&header, &parsed_frame));
  EXPECT_EQ(fake_frame.nanosecond_pts(), parsed_frame.nanosecond_pts());
  EXPECT_EQ(fake_frame.buffer().length, parsed_frame.buffer().length);
  EXPECT_EQ(0, std::memcmp(fake_frame.buffer().data.get(),
                           parsed_frame.buffer().data.get(), kBufferSize));
}

}  // namespace

int main(int argc, char* argv[]) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include <Scene/Member/cMatching.h>
#include "cinder/gl/gl.h"
#include <Utility/cInput.h>
#include <string>
#include <Network.hpp>
using namespace Network;
using namespace Network::Packet::Event;
using namespace Network::Packet::Request;
using namespace Network::Packet::Response;
void drawRect(const ci::vec2& pos, const ci::vec2& size, const ci::ColorA& color)
{
	ci::gl::color(color);
	ci::gl::drawSolidRect(ci::Rectf(ci::vec2(pos.x - size.x / 2.0f, pos.y - size.y / 2.0f),
		                  ci::vec2(pos.x + size.x / 2.0f, pos.y + size.y / 2.0f)));
}

bool BoxToMouse(const ci::vec2& posA, const ci::vec2& sizeA, const ci::vec2& mousePos)
{
	if (posA.x - sizeA.x / 2 > mousePos.x )return false;
	if (posA.x + sizeA.x / 2 < mousePos.x)return false;
	if (posA.y - sizeA.y / 2 > mousePos.y)return false;
	if (posA.y + sizeA.y / 2 < mousePos.y)return false;

	return true;
}

namespace Scene
{
namespace Member
{
	void cMatching::setup()
	{
		mClassState = ClassState::NOT;
		mWaitClassState = ClassState::NOT;
		mPhaseState = PhaseState::NOT_IN_ROOM;
		mCanSend = true;
	}

	void cMatching::shutDown()
	{

	}

	void cMatching::update(float deltaTime)
	{
		makeRoom();
		inRoom();
	}

	void cMatching::makeRoom()
	{
		if (mPhaseState != PhaseState::NOT_IN_ROOM)return;

		if (mWaitClassState == ClassState::NOT)
		{
			while (!cResponseManager::getInstance()->mResMakeRoom.empty())
			{
				auto resMakeRoom = cResponseManager::getInstance()->mResMakeRoom.top();
				cResponseManager::getInstance()->mResMakeRoom.pop();
				continue;
			}

			if (ENV->pushKey(ci::app::KeyEvent::KEY_z))
			{
				mCanSend = false;
				cUDPManager::getInstance()->send(cNetworkHandle("127.0.0.1", 25565), new cReqMakeRoom(100));
				mWaitClassState = ClassState::MASTER;
			}

			else if (ENV->pushKey(ci::app::KeyEvent::KEY_x))
			{
				cUDPManager::getInstance()->send(cNetworkHandle("127.0.0.1", 25565), new cReqInRoom(100));
				mCanSend = false;
				mWaitClassState = ClassState::CLIENT;
			}
		}
		else if (mWaitClassState == ClassState::CLIENT)
		{
			while (!cResponseManager::getInstance()->mResInRoom.empty())
			{
				auto resMakeRoom = cResponseManager::getInstance()->mResInRoom.top();
				if (resMakeRoom.mFlag = false)
				{
					mWaitClassState == ClassState::NOT;
					mCanSend = true;
					cResponseManager::getInstance()->mResInRoom.pop();
					continue;
				}

				mWaitClassState == ClassState::NOT;
				mCanSend = true;
				mClassState = ClassState::CLIENT;
				cResponseManager::getInstance()->mResInRoom.pop();
				continue;
			}

		}

		else if (mWaitClassState == ClassState::MASTER)
		{
			while (!cResponseManager::getInstance()->mResMakeRoom.empty())
			{
				auto resMakeRoom = cResponseManager::getInstance()->mResMakeRoom.top();
				if (resMakeRoom.mFlag = false)
				{
					mWaitClassState == ClassState::NOT;
					mCanSend = true;
					cResponseManager::getInstance()->mResMakeRoom.pop();
					continue;
				}

				mWaitClassState == ClassState::NOT;
				mCanSend = true;
				mClassState = ClassState::MASTER;
				cResponseManager::getInstance()->mResMakeRoom.pop();
				continue;
			}
		}
	}
	void cMatching::inRoom()
	{

	}

	void cMatching::draw()
	{

	}
	void cMatching::draw2D()
	{
		switch (mPhaseState)
		{
		case PhaseState::NOT_IN_ROOM:
			drawRect(ci::vec2(-300, -100), ci::vec2(200,100),ci::ColorA(1,0,0,1));
			drawRect(ci::vec2(300, -100), ci::vec2(200, 100), ci::ColorA(1, 0, 0, 1));
			break;
		case PhaseState::IN_ROOM:

			break;
		}
	}
	void cMatching::resize()
	{

	}
}
}
<commit_msg>update<commit_after>#include <Scene/Member/cMatching.h>
#include "cinder/gl/gl.h"
#include <Utility/cInput.h>
#include <string>
#include <Network.hpp>
using namespace Network;
using namespace Network::Packet::Event;
using namespace Network::Packet::Request;
using namespace Network::Packet::Response;
void drawRect(const ci::vec2& pos, const ci::vec2& size, const ci::ColorA& color)
{
	ci::gl::color(color);
	ci::gl::drawSolidRect(ci::Rectf(ci::vec2(pos.x - size.x / 2.0f, pos.y - size.y / 2.0f),
		                  ci::vec2(pos.x + size.x / 2.0f, pos.y + size.y / 2.0f)));
}

bool BoxToMouse(const ci::vec2& posA, const ci::vec2& sizeA, const ci::vec2& mousePos)
{
	if (posA.x - sizeA.x / 2 > mousePos.x )return false;
	if (posA.x + sizeA.x / 2 < mousePos.x)return false;
	if (posA.y - sizeA.y / 2 > mousePos.y)return false;
	if (posA.y + sizeA.y / 2 < mousePos.y)return false;

	return true;
}

namespace Scene
{
namespace Member
{
	void cMatching::setup()
	{
		mClassState = ClassState::NOT;
		mWaitClassState = ClassState::NOT;
		mPhaseState = PhaseState::NOT_IN_ROOM;
		mCanSend = true;
	}

	void cMatching::shutDown()
	{

	}

	void cMatching::update(float deltaTime)
	{
		makeRoom();
		inRoom();
	}

	void cMatching::makeRoom()
	{
		if (mPhaseState != PhaseState::NOT_IN_ROOM)return;

		if (mWaitClassState == ClassState::NOT)
		{
			while (!cResponseManager::getInstance()->mResMakeRoom.empty())
			{
				auto resMakeRoom = cResponseManager::getInstance()->mResMakeRoom.top();
				cResponseManager::getInstance()->mResMakeRoom.pop();
				continue;
			}

			if (ENV->pushKey(ci::app::KeyEvent::KEY_z))
			{
				mCanSend = false;
				cUDPManager::getInstance()->send(cNetworkHandle("127.0.0.1", 25565), new cReqMakeRoom(100));
				mWaitClassState = ClassState::MASTER;
			}

			else if (ENV->pushKey(ci::app::KeyEvent::KEY_x))
			{
				cUDPManager::getInstance()->send(cNetworkHandle("127.0.0.1", 25565), new cReqInRoom(100));
				mCanSend = false;
				mWaitClassState = ClassState::CLIENT;
			}
		}
		else if (mWaitClassState == ClassState::CLIENT)
		{
			while (!cResponseManager::getInstance()->mResInRoom.empty())
			{
				auto resMakeRoom = cResponseManager::getInstance()->mResInRoom.top();
				if (resMakeRoom.mFlag = false)
				{
					mWaitClassState = ClassState::NOT;
					mCanSend = true;
					cResponseManager::getInstance()->mResInRoom.pop();
					continue;
				}

				mWaitClassState = ClassState::NOT;
				mCanSend = true;
				mClassState = ClassState::CLIENT;
				cResponseManager::getInstance()->mResInRoom.pop();
				continue;
			}

		}

		else if (mWaitClassState == ClassState::MASTER)
		{
			while (!cResponseManager::getInstance()->mResMakeRoom.empty())
			{
				auto resMakeRoom = cResponseManager::getInstance()->mResMakeRoom.top();
				if (resMakeRoom.mFlag = false)
				{
					mWaitClassState = ClassState::NOT;
					mCanSend = true;
					cResponseManager::getInstance()->mResMakeRoom.pop();
					continue;
				}

				mWaitClassState = ClassState::NOT;
				mCanSend = true;
				mClassState = ClassState::MASTER;
				cResponseManager::getInstance()->mResMakeRoom.pop();
				continue;
			}
		}
	}
	void cMatching::inRoom()
	{

	}

	void cMatching::draw()
	{

	}
	void cMatching::draw2D()
	{
		switch (mPhaseState)
		{
		case PhaseState::NOT_IN_ROOM:
			drawRect(ci::vec2(-300, -100), ci::vec2(200,100),ci::ColorA(1,0,0,1));
			drawRect(ci::vec2(300, -100), ci::vec2(200, 100), ci::ColorA(1, 0, 0, 1));
			break;
		case PhaseState::IN_ROOM:

			break;
		}
	}
	void cMatching::resize()
	{

	}
}
}
<|endoftext|>


<commit_before>/*
 * SearchNormal.cpp
 *
 *  Created on: 25 Oct 2015
 *      Author: hieu
 */

#include "Search.h"
#include <algorithm>
#include <boost/foreach.hpp>
#include "Stack.h"
#include "../Manager.h"
#include "../../InputPathsBase.h"
#include "../../TargetPhrases.h"
#include "../../Phrase.h"
#include "../../System.h"
#include "../../Sentence.h"

using namespace std;

namespace Moses2
{

SearchNormal::SearchNormal(Manager &mgr)
:Search(mgr)
,m_stacks(mgr)
{
	// TODO Auto-generated constructor stub

}

SearchNormal::~SearchNormal() {
	// TODO Auto-generated destructor stub
}

void SearchNormal::Decode()
{
	// init stacks
	m_stacks.Init(mgr, mgr.GetInput().GetSize() + 1);

	const Bitmap &initBitmap = mgr.GetBitmaps().GetInitialBitmap();
	Hypothesis *initHypo = Hypothesis::Create(mgr.GetSystemPool(), mgr);
	initHypo->Init(mgr, mgr.GetInputPaths().GetBlank(), mgr.GetInitPhrase(), initBitmap);
	initHypo->EmptyHypothesisState(mgr.GetInput());

	m_stacks.Add(initHypo, mgr.GetHypoRecycle(), mgr.arcLists);

	for (size_t stackInd = 0; stackInd < m_stacks.GetSize(); ++stackInd) {
		Decode(stackInd);
		//cerr << m_stacks << endl;

		// delete stack to save mem
		if (stackInd < m_stacks.GetSize() - 1) {
			m_stacks.Delete(stackInd);
		}
		//cerr << m_stacks << endl;
	}
}

void SearchNormal::Decode(size_t stackInd)
{
  Stack &stack = m_stacks[stackInd];
  if (&stack == &m_stacks.Back()) {
	  // last stack. don't do anythin
	  return;
  }

  std::vector<const HypothesisBase*> hypos = stack.GetBestHyposAndPrune(mgr.system.stackSize, mgr.GetHypoRecycle());

	const InputPaths &paths = mgr.GetInputPaths();

	BOOST_FOREACH(const InputPathBase *path, paths) {
	  BOOST_FOREACH(const HypothesisBase *hypo, hypos) {
			Extend(*static_cast<const Hypothesis*>(hypo), *static_cast<const InputPath*>(path));
	  }
	}
}

void SearchNormal::Extend(const Hypothesis &hypo, const InputPath &path)
{
	const Bitmap &hypoBitmap = hypo.GetBitmap();
	const Range &hypoRange = hypo.GetInputPath().range;
	const Range &pathRange = path.range;

	if (!CanExtend(hypoBitmap, hypoRange.GetEndPos(), pathRange)) {
		return;
	}
	//cerr << " YES" << endl;

    // extend this hypo
	const Bitmap &newBitmap = mgr.GetBitmaps().GetBitmap(hypoBitmap, pathRange);
    //SCORE estimatedScore = mgr.GetEstimatedScores().CalcFutureScore2(bitmap, pathRange.GetStartPos(), pathRange.GetEndPos());
    SCORE estimatedScore = mgr.GetEstimatedScores().CalcEstimatedScore(newBitmap);

    size_t numPt = mgr.system.mappings.size();
	const TargetPhrases **tpsAllPt = path.targetPhrases;
	for (size_t i = 0; i < numPt; ++i) {
		const TargetPhrases *tps = tpsAllPt[i];
		if (tps) {
			Extend(hypo, *tps, path, newBitmap, estimatedScore);
		}
	}
}

void SearchNormal::Extend(const Hypothesis &hypo,
		const TargetPhrases &tps,
		const InputPath &path,
		const Bitmap &newBitmap,
		SCORE estimatedScore)
{
  BOOST_FOREACH(const TargetPhrase *tp, tps) {
	  Extend(hypo, *tp, path, newBitmap, estimatedScore);
  }
}

void SearchNormal::Extend(const Hypothesis &hypo,
		const TargetPhrase &tp,
		const InputPath &path,
		const Bitmap &newBitmap,
		SCORE estimatedScore)
{
	Hypothesis *newHypo = Hypothesis::Create(mgr.GetSystemPool(), mgr);
	newHypo->Init(mgr, hypo, path, tp, newBitmap, estimatedScore);
	newHypo->EvaluateWhenApplied();

	m_stacks.Add(newHypo, mgr.GetHypoRecycle(), mgr.arcLists);

	//m_arcLists.AddArc(stackAdded.added, newHypo, stackAdded.other);
	//stack.Prune(mgr.GetHypoRecycle(), mgr.system.stackSize, mgr.system.stackSize * 2);

}

const Hypothesis *SearchNormal::GetBestHypothesis() const
{
	const Stack &lastStack = m_stacks.Back();
	std::vector<const HypothesisBase*> sortedHypos = lastStack.GetBestHypos(1);

	const Hypothesis *best = NULL;
	if (sortedHypos.size()) {
		best = static_cast<const Hypothesis*>(sortedHypos[0]);
	}
	return best;
}

void SearchNormal::AddInitialTrellisPaths(TrellisPaths &paths) const
{
	cerr << "Not yet implemented";
	abort();
}

}

<commit_msg>nbest for SearchNormal<commit_after>/*
 * SearchNormal.cpp
 *
 *  Created on: 25 Oct 2015
 *      Author: hieu
 */

#include "Search.h"
#include <algorithm>
#include <boost/foreach.hpp>
#include "Stack.h"
#include "../Manager.h"
#include "../TrellisPath.h"
#include "../TrellisPaths.h"
#include "../../InputPathsBase.h"
#include "../../TargetPhrases.h"
#include "../../Phrase.h"
#include "../../System.h"
#include "../../Sentence.h"

using namespace std;

namespace Moses2
{

SearchNormal::SearchNormal(Manager &mgr)
:Search(mgr)
,m_stacks(mgr)
{
	// TODO Auto-generated constructor stub

}

SearchNormal::~SearchNormal() {
	// TODO Auto-generated destructor stub
}

void SearchNormal::Decode()
{
	// init stacks
	m_stacks.Init(mgr, mgr.GetInput().GetSize() + 1);

	const Bitmap &initBitmap = mgr.GetBitmaps().GetInitialBitmap();
	Hypothesis *initHypo = Hypothesis::Create(mgr.GetSystemPool(), mgr);
	initHypo->Init(mgr, mgr.GetInputPaths().GetBlank(), mgr.GetInitPhrase(), initBitmap);
	initHypo->EmptyHypothesisState(mgr.GetInput());

	m_stacks.Add(initHypo, mgr.GetHypoRecycle(), mgr.arcLists);

	for (size_t stackInd = 0; stackInd < m_stacks.GetSize(); ++stackInd) {
		Decode(stackInd);
		//cerr << m_stacks << endl;

		// delete stack to save mem
		if (stackInd < m_stacks.GetSize() - 1) {
			m_stacks.Delete(stackInd);
		}
		//cerr << m_stacks << endl;
	}
}

void SearchNormal::Decode(size_t stackInd)
{
  Stack &stack = m_stacks[stackInd];
  if (&stack == &m_stacks.Back()) {
	  // last stack. don't do anythin
	  return;
  }

  std::vector<const HypothesisBase*> hypos = stack.GetBestHyposAndPrune(mgr.system.stackSize, mgr.GetHypoRecycle());

	const InputPaths &paths = mgr.GetInputPaths();

	BOOST_FOREACH(const InputPathBase *path, paths) {
	  BOOST_FOREACH(const HypothesisBase *hypo, hypos) {
			Extend(*static_cast<const Hypothesis*>(hypo), *static_cast<const InputPath*>(path));
	  }
	}
}

void SearchNormal::Extend(const Hypothesis &hypo, const InputPath &path)
{
	const Bitmap &hypoBitmap = hypo.GetBitmap();
	const Range &hypoRange = hypo.GetInputPath().range;
	const Range &pathRange = path.range;

	if (!CanExtend(hypoBitmap, hypoRange.GetEndPos(), pathRange)) {
		return;
	}
	//cerr << " YES" << endl;

    // extend this hypo
	const Bitmap &newBitmap = mgr.GetBitmaps().GetBitmap(hypoBitmap, pathRange);
    //SCORE estimatedScore = mgr.GetEstimatedScores().CalcFutureScore2(bitmap, pathRange.GetStartPos(), pathRange.GetEndPos());
    SCORE estimatedScore = mgr.GetEstimatedScores().CalcEstimatedScore(newBitmap);

    size_t numPt = mgr.system.mappings.size();
	const TargetPhrases **tpsAllPt = path.targetPhrases;
	for (size_t i = 0; i < numPt; ++i) {
		const TargetPhrases *tps = tpsAllPt[i];
		if (tps) {
			Extend(hypo, *tps, path, newBitmap, estimatedScore);
		}
	}
}

void SearchNormal::Extend(const Hypothesis &hypo,
		const TargetPhrases &tps,
		const InputPath &path,
		const Bitmap &newBitmap,
		SCORE estimatedScore)
{
  BOOST_FOREACH(const TargetPhrase *tp, tps) {
	  Extend(hypo, *tp, path, newBitmap, estimatedScore);
  }
}

void SearchNormal::Extend(const Hypothesis &hypo,
		const TargetPhrase &tp,
		const InputPath &path,
		const Bitmap &newBitmap,
		SCORE estimatedScore)
{
	Hypothesis *newHypo = Hypothesis::Create(mgr.GetSystemPool(), mgr);
	newHypo->Init(mgr, hypo, path, tp, newBitmap, estimatedScore);
	newHypo->EvaluateWhenApplied();

	m_stacks.Add(newHypo, mgr.GetHypoRecycle(), mgr.arcLists);

	//m_arcLists.AddArc(stackAdded.added, newHypo, stackAdded.other);
	//stack.Prune(mgr.GetHypoRecycle(), mgr.system.stackSize, mgr.system.stackSize * 2);

}

const Hypothesis *SearchNormal::GetBestHypothesis() const
{
	const Stack &lastStack = m_stacks.Back();
	std::vector<const HypothesisBase*> sortedHypos = lastStack.GetBestHypos(1);

	const Hypothesis *best = NULL;
	if (sortedHypos.size()) {
		best = static_cast<const Hypothesis*>(sortedHypos[0]);
	}
	return best;
}

void SearchNormal::AddInitialTrellisPaths(TrellisPaths &paths) const
{
  const Stack &lastStack = m_stacks.Back();
    BOOST_FOREACH(const HypothesisBase *hypoBase, lastStack) {
      const Hypothesis *hypo = static_cast<const Hypothesis*>(hypoBase);
      TrellisPath *path = new TrellisPath(hypo, mgr.arcLists);
      paths.Add(path);
  }
}

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "virtual_swapchain.h"
#include <cassert>
#include <chrono>
#include <functional>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

namespace {

// Determines what heap memory should be allocated from, given
// a set of bits.
int32_t
FindMemoryType(const VkPhysicalDeviceMemoryProperties *memory_properties,
               uint32_t memoryTypeBits, VkMemoryPropertyFlags properties) {
  for (int32_t i = 0; i < memory_properties->memoryTypeCount; ++i) {
    if ((memoryTypeBits & (1 << i)) &&
        ((memory_properties->memoryTypes[i].propertyFlags & properties) ==
         properties))
      return i;
  }
  return -1;
}

void null_callback(void *, uint8_t *, size_t) {}
}

namespace swapchain {
VirtualSwapchain::VirtualSwapchain(
    VkDevice device, uint32_t queue,
    const VkPhysicalDeviceProperties *pProperties,
    const VkPhysicalDeviceMemoryProperties *memory_properties,
    const DeviceData *functions,
    const VkSwapchainCreateInfoKHR *_swapchain_info,
    const VkAllocationCallbacks *pAllocator,
    uint32_t pending_image_timeout_in_milliseconds,
    bool always_get_acquired_image)
    : swapchain_info_(*_swapchain_info),
      num_images_(_swapchain_info->minImageCount == 0
                      ? 1
                      : _swapchain_info->minImageCount),
      image_data_(num_images_), should_close_(false),
      device_(device), queue_(queue),
      functions_(functions), pending_image_timeout_in_milliseconds_(
                                 pending_image_timeout_in_milliseconds),
      always_get_acquired_image_(always_get_acquired_image) {
  callback_ = null_callback;
  width_ = _swapchain_info->imageExtent.width;
  height_ = _swapchain_info->imageExtent.height;
  VkPhysicalDeviceMemoryProperties properties = *memory_properties;
  build_swapchain_image_data_ = [this, properties, pAllocator]() {
      SwapchainImageData image_data;

      static const VkFenceCreateInfo fence_info{
          VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0};
      const VkImageCreateInfo image_create_info{
          VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
          nullptr,                             // pNext
          0,                                   // flags
          VK_IMAGE_TYPE_2D,                    // imageType
          swapchain_info_.imageFormat,         // format
          VkExtent3D{swapchain_info_.imageExtent.width,
                     swapchain_info_.imageExtent.height, 1}, // extent
          1,                                                 // mipLevels
          swapchain_info_.imageArrayLayers,                  // arrayLayers
          VK_SAMPLE_COUNT_1_BIT,                             // samples
          VK_IMAGE_TILING_OPTIMAL,                           // tiling
          swapchain_info_.imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
          swapchain_info_.imageSharingMode,      // sharingmode
          swapchain_info_.queueFamilyIndexCount, // queueFamilyIndexCount
          swapchain_info_.pQueueFamilyIndices,   // queueFamilyIndices
          VK_IMAGE_LAYOUT_UNDEFINED,             // initialLayout
      };
      // The size of the buffer that we need is surprisingly easy.
      // Pixel-width * width * height. The GPU will copy into the
      // buffer with the stride we provide.
      // All we want to do here is create a buffer that we can copy
      // the image into.
      // TODO(awolosyn): Currently we know the format is VK_FORMAT_R8G8B8A8_UNORM
      // Handle more formats later if we have other swapchain formats we care
      // about.

      // maximum non-coherent-command-size is 128 bytes
      // This means we can write subsequent layers on 128-byte
      // boundaries
      size_t buffer_memory_size =
          ((ImageByteSize() + 127) & ~127) * swapchain_info_.imageArrayLayers;

      const VkBufferCreateInfo buffer_create_info{
          VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
          nullptr,                              // pNext
          0,                                    // flags
          buffer_memory_size,                   // size
          VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // usage
          VK_SHARING_MODE_EXCLUSIVE,            // sharingMode
          0,                                    // queueFamilyIndexCount
          nullptr                               // pQueueFamilyIndices
        };

      VkCommandPoolCreateInfo command_pool_info{
          VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
          nullptr,                                         // pNext
          VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
          queue_                                           // queueFamilyIndex
      };

      functions_->vkCreateCommandPool(device_, &command_pool_info, pAllocator,
                                      &command_pool_);

      VkCommandBufferAllocateInfo command_buffer_info{
          VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
          nullptr,                                        // pNext
          command_pool_,                                  // commandPool
          VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level
          1                                               // count
      };

      // Create the command buffer
      functions_->vkAllocateCommandBuffers(device_, &command_buffer_info,
                                           &image_data.command_buffer_);

      // Create the fence
      {

          functions_->vkCreateFence(device_, &fence_info, pAllocator,
                                    &image_data.fence_);
          functions_->vkResetFences(device_, 1, &image_data.fence_);
      }

      // Create the buffer
      {
          functions_->vkCreateBuffer(device_, &buffer_create_info, pAllocator,
                                     &image_data.buffer_);
          // Create device-memory for the buffer
          {
              VkMemoryRequirements reqs;
              functions_->vkGetBufferMemoryRequirements(
                  device_, image_data.buffer_, &reqs);

              uint32_t memory_type =
                  FindMemoryType(&properties, reqs.memoryTypeBits,
                                 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
              VkMemoryAllocateInfo buffer_memory_info{
                  VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
                  nullptr,                                // pNext
                  reqs.size,                              // allocationSize
                  memory_type                             // memoryTypeIndex
              };

              functions_->vkAllocateMemory(device_, &buffer_memory_info,
                                           pAllocator,
                                           &image_data.buffer_memory_);
              functions_->vkBindBufferMemory(device_, image_data.buffer_,
                                             image_data.buffer_memory_, 0);
          }
      }

      // Create the image
      {

          functions_->vkCreateImage(device_, &image_create_info, pAllocator,
                                    &image_data.image_);
          // Create device-memory for the image
          {
              VkMemoryRequirements reqs;
              functions_->vkGetImageMemoryRequirements(
                  device_, image_data.image_, &reqs);
              uint32_t memory_type =
                  FindMemoryType(&properties, reqs.memoryTypeBits, 0);

              VkMemoryAllocateInfo image_memory_info{
                  VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
                  nullptr,                                // pNext
                  reqs.size,                              // allocationSize
                  memory_type                             // memoryTypeIndex
              };

              functions_->vkAllocateMemory(device_, &image_memory_info, pAllocator,
                                           &image_data.image_memory_);
              functions_->vkBindImageMemory(device_, image_data.image_,
                                            image_data.image_memory_, 0);
          }
      }

      VkBufferMemoryBarrier dest_barrier{
          VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
          nullptr,                                 // pNext
          VK_ACCESS_TRANSFER_WRITE_BIT,            // srcAccessMask
          VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask
          VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
          VK_QUEUE_FAMILY_IGNORED,                 // dstQueueFamilyIndex
          image_data.buffer_,                      // buffer
          0,                                       // offset
          VK_WHOLE_SIZE                            // size
      };

      VkBufferImageCopy region{
          0, // Start of the buffer
          0, // bufferRowLength Tightly packed buffer
          0, // bufferImageHeight same
          VkImageSubresourceLayers{
              VK_IMAGE_ASPECT_COLOR_BIT,          // aspectMask
              0,                                  // mipLevel
              0,                                  // baseArrayLayer
              swapchain_info_.imageArrayLayers},  // imageSubresourceLayers
          VkOffset3D{0, 0, 0},
          VkExtent3D{swapchain_info_.imageExtent.width,
                     swapchain_info_.imageExtent.height, 1}
      };

      VkCommandBufferBeginInfo cbegin{
          VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
          nullptr,                                     // pNext
          0,                                           // flags
          nullptr                                      // pInheritanceInfo
      };

      functions_->vkBeginCommandBuffer(image_data.command_buffer_, &cbegin);
      functions_->vkCmdCopyImageToBuffer(image_data.command_buffer_,
                                         image_data.image_,
                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                                         image_data.buffer_, 1, &region);
      functions_->vkCmdPipelineBarrier(
          image_data.command_buffer_, VK_PIPELINE_STAGE_TRANSFER_BIT,
          VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1, &dest_barrier, 0, 0);
      functions_->vkEndCommandBuffer(image_data.command_buffer_);

      return image_data;
  };

  // Populate the swapchain image data vector
  for (uint32_t i = 0; i < num_images_; i++) {
    image_data_[i] = build_swapchain_image_data_();
    free_images_.push_back(i);
  }

#ifdef _WIN32
  thread_ = CreateThread(NULL, 0,
                         [](void *data) -> DWORD {
                           ((VirtualSwapchain *)data)->CopyThreadFunc();
                           return 0;
                         },
                         this, 0, nullptr);
#else
  pthread_create(&thread_, nullptr,
                 +[](void *data) -> void * {
                   ((VirtualSwapchain *)data)->CopyThreadFunc();
                   return nullptr;
                 },
                 this);
#endif
}

void VirtualSwapchain::Destroy(const VkAllocationCallbacks *pAllocator) {
  should_close_.store(true);
#ifdef _WIN32
  WaitForSingleObject(thread_, INFINITE);
  CloseHandle(thread_);
#else
  pthread_join(thread_, nullptr);
#endif

  for (size_t i = 0; i < num_images_; ++i) {
    functions_->vkFreeMemory(device_, image_data_[i].image_memory_, pAllocator);
    functions_->vkDestroyImage(device_, image_data_[i].image_, pAllocator);
    functions_->vkFreeMemory(device_, image_data_[i].buffer_memory_,
                             pAllocator);
    functions_->vkDestroyBuffer(device_, image_data_[i].buffer_, pAllocator);
    functions_->vkDestroyFence(device_, image_data_[i].fence_, pAllocator);
    functions_->vkFreeCommandBuffers(device_, command_pool_, 1,
                                     &image_data_[i].command_buffer_);
  }

  functions_->vkDestroyCommandPool(device_, command_pool_, pAllocator);
}

void VirtualSwapchain::CopyThreadFunc() {
  while (true) {
    uint32_t pending_image = 0;
    // We have to wait until there is a pending image.
    {
      // Wait 10ms for our next image.
      std::unique_lock<threading::mutex> pl(pending_images_lock_);
      while (pending_images_.empty()) {
        if (threading::cv_status::timeout ==
            pending_images_condition_.wait_for(
                pl, std::chrono::milliseconds(
                        pending_image_timeout_in_milliseconds_))) {
          if (should_close_.load()) {
            // One last check to see if there are any more pending images.
            // If not we can return.
            if (!pending_images_.empty())
              break;
            return;
          }
        }
      }
      pending_image = pending_images_.front();
      pending_images_.pop_front();
    }

    VkResult ret = functions_->vkWaitForFences(
        device_, 1, &image_data_[pending_image].fence_, false, UINT64_MAX);
    functions_->vkResetFences(device_, 1, &image_data_[pending_image].fence_);

    void *mapped_value;
    functions_->vkMapMemory(device_, image_data_[pending_image].buffer_memory_,
                            0, VK_WHOLE_SIZE, 0, &mapped_value);
    VkMappedMemoryRange range{
        VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,     // sType
        nullptr,                                   // pNext
        image_data_[pending_image].buffer_memory_, // memory
        0,                                         // offset
        VK_WHOLE_SIZE,                             // size
    };
    functions_->vkInvalidateMappedMemoryRanges(device_, 1, &range);

    uint32_t length = ImageByteSize();
    { callback_(callback_user_data_, (uint8_t *)mapped_value, length); }
    functions_->vkUnmapMemory(device_,
                              image_data_[pending_image].buffer_memory_);
    {
      std::unique_lock<threading::mutex> l(free_images_lock_);
      free_images_.push_back(pending_image);
    }
    free_images_condition_.notify_all();
  }
}

bool VirtualSwapchain::GetImage(uint64_t timeout, uint32_t* image) {
  // A helper function that tries to get a free image.
  auto try_get_image_index = [&](uint32_t* index) {
    uint32_t i = 0;
    if (always_get_acquired_image_) {
      for (auto iter = free_images_.begin(); iter != free_images_.end();
           iter++, i++) {
        if (*iter == *image) {
          *index = *iter;
          free_images_.erase(iter);
          return true;
        }
      }
      return false;
    } else {
      if (free_images_.empty())
        return false;
      *index = free_images_[0];
      free_images_.pop_front();
      return true;
    }
  };

  auto wakeup = std::chrono::nanoseconds(timeout);
  while (true) {
    std::unique_lock<threading::mutex> sl(free_images_lock_);
    if (try_get_image_index(image))
      return true;
    if (timeout == UINT64_MAX) {
      free_images_condition_.wait(sl);
    } else {
      if (free_images_condition_.wait_for(sl, wakeup) ==
          threading::cv_status::timeout) {
        return false;
      }
    }
  }
}

void VirtualSwapchain::SetCallback(void callback(void *, uint8_t *, size_t),
                                   void *user_data) {
  callback_ = callback;
  callback_user_data_ = user_data;
}

uint32_t VirtualSwapchain::ImageByteSize() const {
  // TODO(awoloszyn): Once we support more than RGBA8, have this be
  // more dynamic.
  return width_ * height_ * 4;
}
} // swapchain
<commit_msg>Only destroy the command pool, do not destroy each command buffer.<commit_after>/*
 * Copyright (C) 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "virtual_swapchain.h"
#include <cassert>
#include <chrono>
#include <functional>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

namespace {

// Determines what heap memory should be allocated from, given
// a set of bits.
int32_t
FindMemoryType(const VkPhysicalDeviceMemoryProperties *memory_properties,
               uint32_t memoryTypeBits, VkMemoryPropertyFlags properties) {
  for (int32_t i = 0; i < memory_properties->memoryTypeCount; ++i) {
    if ((memoryTypeBits & (1 << i)) &&
        ((memory_properties->memoryTypes[i].propertyFlags & properties) ==
         properties))
      return i;
  }
  return -1;
}

void null_callback(void *, uint8_t *, size_t) {}
}

namespace swapchain {
VirtualSwapchain::VirtualSwapchain(
    VkDevice device, uint32_t queue,
    const VkPhysicalDeviceProperties *pProperties,
    const VkPhysicalDeviceMemoryProperties *memory_properties,
    const DeviceData *functions,
    const VkSwapchainCreateInfoKHR *_swapchain_info,
    const VkAllocationCallbacks *pAllocator,
    uint32_t pending_image_timeout_in_milliseconds,
    bool always_get_acquired_image)
    : swapchain_info_(*_swapchain_info),
      num_images_(_swapchain_info->minImageCount == 0
                      ? 1
                      : _swapchain_info->minImageCount),
      image_data_(num_images_), should_close_(false),
      device_(device), queue_(queue),
      functions_(functions), pending_image_timeout_in_milliseconds_(
                                 pending_image_timeout_in_milliseconds),
      always_get_acquired_image_(always_get_acquired_image) {
  callback_ = null_callback;
  width_ = _swapchain_info->imageExtent.width;
  height_ = _swapchain_info->imageExtent.height;
  VkPhysicalDeviceMemoryProperties properties = *memory_properties;
  build_swapchain_image_data_ = [this, properties, pAllocator]() {
      SwapchainImageData image_data;

      static const VkFenceCreateInfo fence_info{
          VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0};
      const VkImageCreateInfo image_create_info{
          VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
          nullptr,                             // pNext
          0,                                   // flags
          VK_IMAGE_TYPE_2D,                    // imageType
          swapchain_info_.imageFormat,         // format
          VkExtent3D{swapchain_info_.imageExtent.width,
                     swapchain_info_.imageExtent.height, 1}, // extent
          1,                                                 // mipLevels
          swapchain_info_.imageArrayLayers,                  // arrayLayers
          VK_SAMPLE_COUNT_1_BIT,                             // samples
          VK_IMAGE_TILING_OPTIMAL,                           // tiling
          swapchain_info_.imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
          swapchain_info_.imageSharingMode,      // sharingmode
          swapchain_info_.queueFamilyIndexCount, // queueFamilyIndexCount
          swapchain_info_.pQueueFamilyIndices,   // queueFamilyIndices
          VK_IMAGE_LAYOUT_UNDEFINED,             // initialLayout
      };
      // The size of the buffer that we need is surprisingly easy.
      // Pixel-width * width * height. The GPU will copy into the
      // buffer with the stride we provide.
      // All we want to do here is create a buffer that we can copy
      // the image into.
      // TODO(awolosyn): Currently we know the format is VK_FORMAT_R8G8B8A8_UNORM
      // Handle more formats later if we have other swapchain formats we care
      // about.

      // maximum non-coherent-command-size is 128 bytes
      // This means we can write subsequent layers on 128-byte
      // boundaries
      size_t buffer_memory_size =
          ((ImageByteSize() + 127) & ~127) * swapchain_info_.imageArrayLayers;

      const VkBufferCreateInfo buffer_create_info{
          VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
          nullptr,                              // pNext
          0,                                    // flags
          buffer_memory_size,                   // size
          VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // usage
          VK_SHARING_MODE_EXCLUSIVE,            // sharingMode
          0,                                    // queueFamilyIndexCount
          nullptr                               // pQueueFamilyIndices
        };

      VkCommandPoolCreateInfo command_pool_info{
          VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
          nullptr,                                         // pNext
          VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
          queue_                                           // queueFamilyIndex
      };

      functions_->vkCreateCommandPool(device_, &command_pool_info, pAllocator,
                                      &command_pool_);

      VkCommandBufferAllocateInfo command_buffer_info{
          VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
          nullptr,                                        // pNext
          command_pool_,                                  // commandPool
          VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // level
          1                                               // count
      };

      // Create the command buffer
      functions_->vkAllocateCommandBuffers(device_, &command_buffer_info,
                                           &image_data.command_buffer_);

      // Create the fence
      {

          functions_->vkCreateFence(device_, &fence_info, pAllocator,
                                    &image_data.fence_);
          functions_->vkResetFences(device_, 1, &image_data.fence_);
      }

      // Create the buffer
      {
          functions_->vkCreateBuffer(device_, &buffer_create_info, pAllocator,
                                     &image_data.buffer_);
          // Create device-memory for the buffer
          {
              VkMemoryRequirements reqs;
              functions_->vkGetBufferMemoryRequirements(
                  device_, image_data.buffer_, &reqs);

              uint32_t memory_type =
                  FindMemoryType(&properties, reqs.memoryTypeBits,
                                 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
              VkMemoryAllocateInfo buffer_memory_info{
                  VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
                  nullptr,                                // pNext
                  reqs.size,                              // allocationSize
                  memory_type                             // memoryTypeIndex
              };

              functions_->vkAllocateMemory(device_, &buffer_memory_info,
                                           pAllocator,
                                           &image_data.buffer_memory_);
              functions_->vkBindBufferMemory(device_, image_data.buffer_,
                                             image_data.buffer_memory_, 0);
          }
      }

      // Create the image
      {

          functions_->vkCreateImage(device_, &image_create_info, pAllocator,
                                    &image_data.image_);
          // Create device-memory for the image
          {
              VkMemoryRequirements reqs;
              functions_->vkGetImageMemoryRequirements(
                  device_, image_data.image_, &reqs);
              uint32_t memory_type =
                  FindMemoryType(&properties, reqs.memoryTypeBits, 0);

              VkMemoryAllocateInfo image_memory_info{
                  VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
                  nullptr,                                // pNext
                  reqs.size,                              // allocationSize
                  memory_type                             // memoryTypeIndex
              };

              functions_->vkAllocateMemory(device_, &image_memory_info, pAllocator,
                                           &image_data.image_memory_);
              functions_->vkBindImageMemory(device_, image_data.image_,
                                            image_data.image_memory_, 0);
          }
      }

      VkBufferMemoryBarrier dest_barrier{
          VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
          nullptr,                                 // pNext
          VK_ACCESS_TRANSFER_WRITE_BIT,            // srcAccessMask
          VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask
          VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
          VK_QUEUE_FAMILY_IGNORED,                 // dstQueueFamilyIndex
          image_data.buffer_,                      // buffer
          0,                                       // offset
          VK_WHOLE_SIZE                            // size
      };

      VkBufferImageCopy region{
          0, // Start of the buffer
          0, // bufferRowLength Tightly packed buffer
          0, // bufferImageHeight same
          VkImageSubresourceLayers{
              VK_IMAGE_ASPECT_COLOR_BIT,          // aspectMask
              0,                                  // mipLevel
              0,                                  // baseArrayLayer
              swapchain_info_.imageArrayLayers},  // imageSubresourceLayers
          VkOffset3D{0, 0, 0},
          VkExtent3D{swapchain_info_.imageExtent.width,
                     swapchain_info_.imageExtent.height, 1}
      };

      VkCommandBufferBeginInfo cbegin{
          VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
          nullptr,                                     // pNext
          0,                                           // flags
          nullptr                                      // pInheritanceInfo
      };

      functions_->vkBeginCommandBuffer(image_data.command_buffer_, &cbegin);
      functions_->vkCmdCopyImageToBuffer(image_data.command_buffer_,
                                         image_data.image_,
                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                                         image_data.buffer_, 1, &region);
      functions_->vkCmdPipelineBarrier(
          image_data.command_buffer_, VK_PIPELINE_STAGE_TRANSFER_BIT,
          VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1, &dest_barrier, 0, 0);
      functions_->vkEndCommandBuffer(image_data.command_buffer_);

      return image_data;
  };

  // Populate the swapchain image data vector
  for (uint32_t i = 0; i < num_images_; i++) {
    image_data_[i] = build_swapchain_image_data_();
    free_images_.push_back(i);
  }

#ifdef _WIN32
  thread_ = CreateThread(NULL, 0,
                         [](void *data) -> DWORD {
                           ((VirtualSwapchain *)data)->CopyThreadFunc();
                           return 0;
                         },
                         this, 0, nullptr);
#else
  pthread_create(&thread_, nullptr,
                 +[](void *data) -> void * {
                   ((VirtualSwapchain *)data)->CopyThreadFunc();
                   return nullptr;
                 },
                 this);
#endif
}

void VirtualSwapchain::Destroy(const VkAllocationCallbacks *pAllocator) {
  should_close_.store(true);
#ifdef _WIN32
  WaitForSingleObject(thread_, INFINITE);
  CloseHandle(thread_);
#else
  pthread_join(thread_, nullptr);
#endif

  for (size_t i = 0; i < num_images_; ++i) {
    functions_->vkFreeMemory(device_, image_data_[i].image_memory_, pAllocator);
    functions_->vkDestroyImage(device_, image_data_[i].image_, pAllocator);
    functions_->vkFreeMemory(device_, image_data_[i].buffer_memory_,
                             pAllocator);
    functions_->vkDestroyBuffer(device_, image_data_[i].buffer_, pAllocator);
    functions_->vkDestroyFence(device_, image_data_[i].fence_, pAllocator);
  }

  functions_->vkDestroyCommandPool(device_, command_pool_, pAllocator);
}

void VirtualSwapchain::CopyThreadFunc() {
  while (true) {
    uint32_t pending_image = 0;
    // We have to wait until there is a pending image.
    {
      // Wait 10ms for our next image.
      std::unique_lock<threading::mutex> pl(pending_images_lock_);
      while (pending_images_.empty()) {
        if (threading::cv_status::timeout ==
            pending_images_condition_.wait_for(
                pl, std::chrono::milliseconds(
                        pending_image_timeout_in_milliseconds_))) {
          if (should_close_.load()) {
            // One last check to see if there are any more pending images.
            // If not we can return.
            if (!pending_images_.empty())
              break;
            return;
          }
        }
      }
      pending_image = pending_images_.front();
      pending_images_.pop_front();
    }

    VkResult ret = functions_->vkWaitForFences(
        device_, 1, &image_data_[pending_image].fence_, false, UINT64_MAX);
    functions_->vkResetFences(device_, 1, &image_data_[pending_image].fence_);

    void *mapped_value;
    functions_->vkMapMemory(device_, image_data_[pending_image].buffer_memory_,
                            0, VK_WHOLE_SIZE, 0, &mapped_value);
    VkMappedMemoryRange range{
        VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,     // sType
        nullptr,                                   // pNext
        image_data_[pending_image].buffer_memory_, // memory
        0,                                         // offset
        VK_WHOLE_SIZE,                             // size
    };
    functions_->vkInvalidateMappedMemoryRanges(device_, 1, &range);

    uint32_t length = ImageByteSize();
    { callback_(callback_user_data_, (uint8_t *)mapped_value, length); }
    functions_->vkUnmapMemory(device_,
                              image_data_[pending_image].buffer_memory_);
    {
      std::unique_lock<threading::mutex> l(free_images_lock_);
      free_images_.push_back(pending_image);
    }
    free_images_condition_.notify_all();
  }
}

bool VirtualSwapchain::GetImage(uint64_t timeout, uint32_t* image) {
  // A helper function that tries to get a free image.
  auto try_get_image_index = [&](uint32_t* index) {
    uint32_t i = 0;
    if (always_get_acquired_image_) {
      for (auto iter = free_images_.begin(); iter != free_images_.end();
           iter++, i++) {
        if (*iter == *image) {
          *index = *iter;
          free_images_.erase(iter);
          return true;
        }
      }
      return false;
    } else {
      if (free_images_.empty())
        return false;
      *index = free_images_[0];
      free_images_.pop_front();
      return true;
    }
  };

  auto wakeup = std::chrono::nanoseconds(timeout);
  while (true) {
    std::unique_lock<threading::mutex> sl(free_images_lock_);
    if (try_get_image_index(image))
      return true;
    if (timeout == UINT64_MAX) {
      free_images_condition_.wait(sl);
    } else {
      if (free_images_condition_.wait_for(sl, wakeup) ==
          threading::cv_status::timeout) {
        return false;
      }
    }
  }
}

void VirtualSwapchain::SetCallback(void callback(void *, uint8_t *, size_t),
                                   void *user_data) {
  callback_ = callback;
  callback_user_data_ = user_data;
}

uint32_t VirtualSwapchain::ImageByteSize() const {
  // TODO(awoloszyn): Once we support more than RGBA8, have this be
  // more dynamic.
  return width_ * height_ * 4;
}
} // swapchain
<|endoftext|>