Remove trailing space, git doesn't like it
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@12797 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
9f8996727d
commit
b56bf4dc53
@ -60,29 +60,29 @@ Addon::Addon(const XMLNode &xml)
|
||||
xml.get("arena", &is_arena );
|
||||
if(is_arena) m_type="arena";
|
||||
}
|
||||
|
||||
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string designer;
|
||||
|
||||
xml.get("name", &name );
|
||||
xml.get("name", &name );
|
||||
m_name = StringUtils::decodeFromHtmlEntities(name);
|
||||
m_dir_name = StringUtils::toLowerCase(name);
|
||||
xml.get("id", &m_dir_name );
|
||||
m_id = createAddonId(m_dir_name);
|
||||
xml.get("designer", &designer );
|
||||
xml.get("status", &m_status );
|
||||
|
||||
|
||||
int64_t tmp;
|
||||
xml.get("date", &tmp );
|
||||
m_date = tmp;
|
||||
|
||||
|
||||
xml.get("installed", &m_installed );
|
||||
xml.get("installed-revision", &m_installed_revision);
|
||||
xml.get("revision", &m_revision );
|
||||
xml.get("file", &m_zip_file );
|
||||
xml.get("description", &description );
|
||||
|
||||
|
||||
m_description = StringUtils::decodeFromHtmlEntities(description);
|
||||
m_designer = StringUtils::decodeFromHtmlEntities(designer);
|
||||
|
||||
@ -111,7 +111,7 @@ Addon::Addon(const XMLNode &xml)
|
||||
}; // Addon(const XML&)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Copies the installation data (like description, revision, icon) from the
|
||||
/** Copies the installation data (like description, revision, icon) from the
|
||||
* downloaded online list to this entry.
|
||||
*/
|
||||
void Addon::copyInstallData(const Addon &addon)
|
||||
@ -135,14 +135,14 @@ void Addon::copyInstallData(const Addon &addon)
|
||||
} // copyInstallData
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Writes information about an installed addon (it is only called for
|
||||
/** Writes information about an installed addon (it is only called for
|
||||
* installed addons).
|
||||
* \param out_stream Output stream to write to.
|
||||
*/
|
||||
void Addon::writeXML(std::ofstream *out_stream)
|
||||
{
|
||||
// We write m_dir_name as 'id' to stay backwards compatible
|
||||
(*out_stream) << " <" << m_type
|
||||
(*out_stream) << " <" << m_type
|
||||
<< " name=\""
|
||||
<< StringUtils::encodeToHtmlEntities(m_name)
|
||||
<< "\" id=\"" << m_dir_name
|
||||
@ -150,11 +150,11 @@ void Addon::writeXML(std::ofstream *out_stream)
|
||||
<< StringUtils::encodeToHtmlEntities(m_designer)
|
||||
<< "\" status=\"" << m_status
|
||||
<< "\" date=\"" << m_date
|
||||
<< "\" installed=\""
|
||||
<< "\" installed=\""
|
||||
<< (m_installed ? "true" : "false" )
|
||||
<< "\" installed-revision=\"" << m_installed_revision
|
||||
<< "\" size=\"" << m_size
|
||||
<< "\" icon-revision=\"" << m_icon_revision
|
||||
<< "\" icon-revision=\"" << m_icon_revision
|
||||
<< "\" icon-name=\"" << m_icon_basename
|
||||
<< "\"/>\n";
|
||||
} // writeXML
|
||||
|
@ -74,7 +74,7 @@ AddonsManager::~AddonsManager()
|
||||
* downloaded list of available addons. This is called by network_http before
|
||||
* it goes into command-receiving mode, so we can't use any asynchronous calls
|
||||
* here (though this is being called from a separate thread , so the
|
||||
* main GUI is not blocked anyway). This function will update the state
|
||||
* main GUI is not blocked anyway). This function will update the state
|
||||
* variable
|
||||
*/
|
||||
void AddonsManager::initOnline(const XMLNode *xml)
|
||||
@ -120,13 +120,13 @@ void AddonsManager::initOnline(const XMLNode *xml)
|
||||
{
|
||||
// If the version is too old (e.g. after an update of stk)
|
||||
// remove a cached icon.
|
||||
std::string full_path =
|
||||
std::string full_path =
|
||||
file_manager->getAddonsFile("icons/"
|
||||
+addon.getIconBasename());
|
||||
if(file_manager->fileExists(full_path))
|
||||
{
|
||||
if(UserConfigParams::logAddons())
|
||||
Log::warn("[addons] Removing cached icon '%s'.\n",
|
||||
Log::warn("[addons] Removing cached icon '%s'.\n",
|
||||
addon.getIconBasename().c_str());
|
||||
file_manager->removeFile(full_path);
|
||||
}
|
||||
@ -137,7 +137,7 @@ void AddonsManager::initOnline(const XMLNode *xml)
|
||||
if(index>=0)
|
||||
{
|
||||
Addon& tmplist_addon = m_addons_list.getData()[index];
|
||||
|
||||
|
||||
// Only copy the data if a newer revision is found (ignore unapproved
|
||||
// revisions unless player is in the mode to see them)
|
||||
if (tmplist_addon.getRevision() < addon.getRevision() &&
|
||||
@ -157,7 +157,7 @@ void AddonsManager::initOnline(const XMLNode *xml)
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
fprintf(stderr,
|
||||
"[addons] Found invalid node '%s' while downloading addons.\n",
|
||||
node->getName().c_str());
|
||||
fprintf(stderr, "[addons] Ignored.\n");
|
||||
@ -183,7 +183,7 @@ void AddonsManager::initOnline(const XMLNode *xml)
|
||||
continue;
|
||||
}
|
||||
// This addon is not on the server anymore, and not installed. Remove
|
||||
// it from the list.
|
||||
// it from the list.
|
||||
if(UserConfigParams::logAddons())
|
||||
Log::warn(
|
||||
"[addons] Removing '%s' which is not on the server anymore.\n",
|
||||
@ -227,7 +227,7 @@ void AddonsManager::checkInstalledAddons()
|
||||
bool something_was_changed = false;
|
||||
|
||||
// Lock the whole addons list to make sure a consistent view is
|
||||
// written back to disk. The network thread might still be
|
||||
// written back to disk. The network thread might still be
|
||||
// downloading icons and modify content
|
||||
m_addons_list.lock();
|
||||
|
||||
@ -243,7 +243,7 @@ void AddonsManager::checkInstalledAddons()
|
||||
if(n<0) continue;
|
||||
if(!m_addons_list.getData()[n].isInstalled())
|
||||
{
|
||||
Log::info("[addons] Marking '%s' as being installed.\n",
|
||||
Log::info("[addons] Marking '%s' as being installed.\n",
|
||||
kp->getIdent().c_str());
|
||||
m_addons_list.getData()[n].setInstalled(true);
|
||||
something_was_changed = true;
|
||||
@ -262,7 +262,7 @@ void AddonsManager::checkInstalledAddons()
|
||||
if(n<0) continue;
|
||||
if(!m_addons_list.getData()[n].isInstalled())
|
||||
{
|
||||
Log::info("[addons] Marking '%s' as being installed.\n",
|
||||
Log::info("[addons] Marking '%s' as being installed.\n",
|
||||
track->getIdent().c_str());
|
||||
m_addons_list.getData()[n].setInstalled(true);
|
||||
something_was_changed = true;
|
||||
@ -274,7 +274,7 @@ void AddonsManager::checkInstalledAddons()
|
||||
} // checkInstalledAddons
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Download all necessary icons (i.e. icons that are either missing or have
|
||||
/** Download all necessary icons (i.e. icons that are either missing or have
|
||||
* been updated since they were downloaded).
|
||||
*/
|
||||
void AddonsManager::downloadIcons()
|
||||
@ -284,7 +284,7 @@ void AddonsManager::downloadIcons()
|
||||
Addon &addon = m_addons_list.getData()[i];
|
||||
const std::string &icon = addon.getIconBasename();
|
||||
const std::string &icon_full
|
||||
= file_manager->getAddonsFile("icons/"+icon);
|
||||
= file_manager->getAddonsFile("icons/"+icon);
|
||||
if(addon.iconNeedsUpdate() ||
|
||||
!file_manager->fileExists(icon_full))
|
||||
{
|
||||
@ -299,11 +299,11 @@ void AddonsManager::downloadIcons()
|
||||
continue;
|
||||
}
|
||||
std::string save = "icons/"+icon;
|
||||
Request *r = INetworkHttp::get()->downloadFileAsynchron(url, save,
|
||||
Request *r = INetworkHttp::get()->downloadFileAsynchron(url, save,
|
||||
/*priority*/1,
|
||||
/*manage_mem*/true);
|
||||
if (r != NULL)
|
||||
r->setAddonIconNotification(&addon);
|
||||
r->setAddonIconNotification(&addon);
|
||||
}
|
||||
else
|
||||
m_addons_list.getData()[i].setIconReady();
|
||||
@ -342,7 +342,7 @@ void AddonsManager::loadInstalledAddons()
|
||||
} // loadInstalledAddons
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns an addon with a given id. Raises an assertion if the id is not
|
||||
/** Returns an addon with a given id. Raises an assertion if the id is not
|
||||
* found!
|
||||
* \param id The id to search for.
|
||||
*/
|
||||
@ -370,8 +370,8 @@ int AddonsManager::getAddonIndex(const std::string &id) const
|
||||
} // getAddonIndex
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Installs or updates (i.e. = install on top of an existing installation) an
|
||||
* addon. It checks for the directories and then unzips the file (which must
|
||||
/** Installs or updates (i.e. = install on top of an existing installation) an
|
||||
* addon. It checks for the directories and then unzips the file (which must
|
||||
* already have been downloaded).
|
||||
* \param addon Addon data for the addon to install.
|
||||
* \return true if installation was successful.
|
||||
@ -381,16 +381,16 @@ bool AddonsManager::install(const Addon &addon)
|
||||
bool success=true;
|
||||
file_manager->checkAndCreateDirForAddons(addon.getDataDir());
|
||||
|
||||
//extract the zip in the addons folder called like the addons name
|
||||
//extract the zip in the addons folder called like the addons name
|
||||
std::string base_name = StringUtils::getBasename(addon.getZipFileName());
|
||||
std::string from = file_manager->getAddonsFile("tmp/"+base_name);
|
||||
std::string to = addon.getDataDir();
|
||||
|
||||
|
||||
success = extract_zip(from, to);
|
||||
if (!success)
|
||||
{
|
||||
// TODO: show a message in the interface
|
||||
std::cerr << "[addons] Failed to unzip '" << from << "' to '"
|
||||
std::cerr << "[addons] Failed to unzip '" << from << "' to '"
|
||||
<< to << "'\n";
|
||||
std::cerr << "[addons] Zip file will not be removed.\n";
|
||||
return false;
|
||||
@ -405,15 +405,15 @@ bool AddonsManager::install(const Addon &addon)
|
||||
int index = getAddonIndex(addon.getId());
|
||||
assert(index>=0 && index < (int)m_addons_list.getData().size());
|
||||
m_addons_list.getData()[index].setInstalled(true);
|
||||
|
||||
|
||||
if(addon.getType()=="kart")
|
||||
{
|
||||
// We have to remove the mesh of the kart since otherwise it remains
|
||||
// cashed (if a kart is updated), and will therefore be found again
|
||||
// when reloading the karts. This is important on one hand since we
|
||||
// cashed (if a kart is updated), and will therefore be found again
|
||||
// when reloading the karts. This is important on one hand since we
|
||||
// reload all karts (this function is easily available) and existing
|
||||
// karts will not reload their meshes.
|
||||
const KartProperties *prop =
|
||||
const KartProperties *prop =
|
||||
kart_properties_manager->getKart(addon.getId());
|
||||
// If the model already exist, first remove the old kart
|
||||
if(prop)
|
||||
@ -425,7 +425,7 @@ bool AddonsManager::install(const Addon &addon)
|
||||
Track *track = track_manager->getTrack(addon.getId());
|
||||
if(track)
|
||||
track_manager->removeTrack(addon.getId());
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
track_manager->loadTrack(addon.getDataDir());
|
||||
@ -447,7 +447,7 @@ bool AddonsManager::install(const Addon &addon)
|
||||
*/
|
||||
bool AddonsManager::uninstall(const Addon &addon)
|
||||
{
|
||||
std::cout << "[addons] Uninstalling <"
|
||||
std::cout << "[addons] Uninstalling <"
|
||||
<< core::stringc(addon.getName()).c_str() << ">\n";
|
||||
|
||||
// addon is a const reference, and to avoid removing the const, we
|
||||
@ -478,7 +478,7 @@ bool AddonsManager::uninstall(const Addon &addon)
|
||||
} // uninstall
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Saves the information about installed addons and cached icons to
|
||||
/** Saves the information about installed addons and cached icons to
|
||||
* addons_installed.xml. If this is not called, information about downloaded
|
||||
* icons is lost (and will trigger a complete redownload when STK is started
|
||||
* next time).
|
||||
|
@ -52,18 +52,18 @@
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Create a thread that handles all network functions independent of the
|
||||
/** Create a thread that handles all network functions independent of the
|
||||
* main program. NetworkHttp supports only a single thread (i.e. it's not
|
||||
* possible to download two addons at the same time), which makes handling
|
||||
* and synchronisation a lot easier (otherwise all objects using this object
|
||||
* would need an additional handle to get the right data back).
|
||||
* This separate thread is running in NetworkHttp::mainLoop, and is being
|
||||
* This separate thread is running in NetworkHttp::mainLoop, and is being
|
||||
* waken up if a command is issued (e.g. using downloadFileAsynchronous).
|
||||
* While UserConfigParams are modified, they can't (easily) be saved here,
|
||||
* since the user might trigger another save in the menu (potentially
|
||||
* ending up with an corrupted file).
|
||||
*/
|
||||
NetworkHttp::NetworkHttp() :
|
||||
NetworkHttp::NetworkHttp() :
|
||||
m_current_request(NULL),
|
||||
m_abort(false),
|
||||
m_thread_id(NULL)
|
||||
@ -83,14 +83,14 @@ NetworkHttp::NetworkHttp() :
|
||||
Request *request = new Request(Request::HC_INIT, 9999);
|
||||
m_all_requests.lock();
|
||||
m_all_requests.getData().push(request);
|
||||
m_all_requests.unlock();
|
||||
m_all_requests.unlock();
|
||||
} // NetworkHttp
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Start the actual network thread. This can not be done as part of
|
||||
* the constructor, since the assignment to the global network_http
|
||||
* variable has not been assigned at that stage, and the thread might
|
||||
* use network_http - a very subtle race condition. So the thread can
|
||||
* use network_http - a very subtle race condition. So the thread can
|
||||
* only be started after the assignment (in main) has been done.
|
||||
*/
|
||||
void NetworkHttp::startNetworkThread()
|
||||
@ -106,7 +106,7 @@ void NetworkHttp::startNetworkThread()
|
||||
//pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
|
||||
m_thread_id.setAtomic(new pthread_t());
|
||||
int error = pthread_create(m_thread_id.getData(), &attr,
|
||||
int error = pthread_create(m_thread_id.getData(), &attr,
|
||||
&NetworkHttp::mainLoop, this);
|
||||
if(error)
|
||||
{
|
||||
@ -121,7 +121,7 @@ void NetworkHttp::startNetworkThread()
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** The actual main loop, which is started as a separate thread from the
|
||||
* constructor. After testing for a new server, fetching news, the list
|
||||
* constructor. After testing for a new server, fetching news, the list
|
||||
* of packages to download, it will wait for commands to be issued.
|
||||
* \param obj: A pointer to this object, passed on by pthread_create
|
||||
*/
|
||||
@ -146,26 +146,26 @@ void *NetworkHttp::mainLoop(void *obj)
|
||||
if(UserConfigParams::logAddons())
|
||||
printf("[addons] No request, sleeping.\n");
|
||||
|
||||
pthread_cond_wait(&me->m_cond_request,
|
||||
pthread_cond_wait(&me->m_cond_request,
|
||||
me->m_all_requests.getMutex());
|
||||
empty = me->m_all_requests.getData().empty();
|
||||
}
|
||||
// Get the first (=highest priority) request and remove it from the
|
||||
// Get the first (=highest priority) request and remove it from the
|
||||
// queue. Only this code actually removes requests from the queue,
|
||||
// so it is certain that even
|
||||
// so it is certain that even
|
||||
me->m_current_request = me->m_all_requests.getData().top();
|
||||
me->m_all_requests.getData().pop();
|
||||
if(UserConfigParams::logAddons())
|
||||
{
|
||||
if(me->m_current_request->getCommand()==Request::HC_DOWNLOAD_FILE)
|
||||
printf("[addons] Executing download '%s' to '%s' priority %d.\n",
|
||||
me->m_current_request->getURL().c_str(),
|
||||
me->m_current_request->getURL().c_str(),
|
||||
me->m_current_request->getSavePath().c_str(),
|
||||
me->m_current_request->getPriority());
|
||||
else
|
||||
printf("[addons] Executing command '%d' priority %d.\n",
|
||||
me->m_current_request->getCommand(),
|
||||
me->m_current_request->getPriority());
|
||||
me->m_current_request->getCommand(),
|
||||
me->m_current_request->getPriority());
|
||||
}
|
||||
if(me->m_current_request->getCommand()==Request::HC_QUIT)
|
||||
{
|
||||
@ -178,7 +178,7 @@ void *NetworkHttp::mainLoop(void *obj)
|
||||
CURLcode status=CURLE_OK;
|
||||
switch(me->m_current_request->getCommand())
|
||||
{
|
||||
case Request::HC_INIT:
|
||||
case Request::HC_INIT:
|
||||
status = me->init();
|
||||
break;
|
||||
case Request::HC_REINIT:
|
||||
@ -187,7 +187,7 @@ void *NetworkHttp::mainLoop(void *obj)
|
||||
case Request::HC_DOWNLOAD_FILE:
|
||||
status = me->downloadFileInternal(me->m_current_request);
|
||||
break;
|
||||
case Request::HC_QUIT:
|
||||
case Request::HC_QUIT:
|
||||
assert(false); // quit is checked already
|
||||
break;
|
||||
default:
|
||||
@ -224,7 +224,7 @@ void *NetworkHttp::mainLoop(void *obj)
|
||||
// ---------------------------------------------------------------------------
|
||||
/** This function inserts a high priority request to quit into the request
|
||||
* queue of the network thead, and also aborts any ongoing download.
|
||||
* Separating this allows more time for the thread to finish cleanly,
|
||||
* Separating this allows more time for the thread to finish cleanly,
|
||||
* before it gets cancelled in the destructor.
|
||||
*/
|
||||
void NetworkHttp::stopNetworkThread()
|
||||
@ -296,7 +296,7 @@ CURLcode NetworkHttp::init()
|
||||
"news.xml", "news.xml");
|
||||
CURLcode status = download ? downloadFileInternal(&r)
|
||||
: CURLE_OK;
|
||||
if(download &&
|
||||
if(download &&
|
||||
status==CURLE_COULDNT_RESOLVE_HOST)
|
||||
{
|
||||
// Assume that the server address is wrong. And retry
|
||||
@ -326,7 +326,7 @@ CURLcode NetworkHttp::init()
|
||||
UserConfigParams::m_server_addons.revertToDefaults();
|
||||
status = downloadFileInternal(&r);
|
||||
if(status==CURLE_OK)
|
||||
UserConfigParams::m_news_last_updated =
|
||||
UserConfigParams::m_news_last_updated =
|
||||
Time::getTimeSinceEpoch();
|
||||
delete xml;
|
||||
xml = new XMLNode(xml_file);
|
||||
@ -376,7 +376,7 @@ CURLcode NetworkHttp::init()
|
||||
*/
|
||||
void NetworkHttp::insertReInit()
|
||||
{
|
||||
Request *request = new Request(Request::HC_REINIT, 9999,
|
||||
Request *request = new Request(Request::HC_REINIT, 9999,
|
||||
/*manage_memory*/true);
|
||||
|
||||
if(UserConfigParams::logAddons())
|
||||
@ -409,7 +409,7 @@ CURLcode NetworkHttp::reInit()
|
||||
printf("[addons] Xml files deleted, re-initialising addon manager.\n");
|
||||
|
||||
return init();
|
||||
|
||||
|
||||
} // reInit
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -432,7 +432,7 @@ CURLcode NetworkHttp::loadAddonsList(const XMLNode *xml,
|
||||
if(include)
|
||||
{
|
||||
include->get("file", &addon_list_url);
|
||||
|
||||
|
||||
int64_t tmp;
|
||||
include->get("mtime", &tmp);
|
||||
mtime = tmp;
|
||||
@ -455,7 +455,7 @@ CURLcode NetworkHttp::loadAddonsList(const XMLNode *xml,
|
||||
|
||||
Request r(Request::HC_DOWNLOAD_FILE, 9999, false,
|
||||
addon_list_url, "addons.xml");
|
||||
CURLcode status = download ? downloadFileInternal(&r)
|
||||
CURLcode status = download ? downloadFileInternal(&r)
|
||||
: CURLE_OK;
|
||||
if(status==CURLE_OK)
|
||||
{
|
||||
@ -478,7 +478,7 @@ CURLcode NetworkHttp::loadAddonsList(const XMLNode *xml,
|
||||
} // loadAddonsList
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Download a file. The file name isn't absolute, the server in the config
|
||||
/** Download a file. The file name isn't absolute, the server in the config
|
||||
* will be added to file. The file is downloaded with a ".part" extention,
|
||||
* and the file is renamed after it was downloaded successfully.
|
||||
* \param request The request object containing the url and the path where
|
||||
@ -486,15 +486,15 @@ CURLcode NetworkHttp::loadAddonsList(const XMLNode *xml,
|
||||
*/
|
||||
CURLcode NetworkHttp::downloadFileInternal(Request *request)
|
||||
{
|
||||
std::string full_save =
|
||||
std::string full_save =
|
||||
file_manager->getAddonsFile(request->getSavePath());
|
||||
|
||||
std::string full_url = request->getURL();
|
||||
if(full_url.substr(0, 5)!="http:" && full_url.substr(0, 4)!="ftp:")
|
||||
full_url = (std::string)UserConfigParams::m_server_addons
|
||||
full_url = (std::string)UserConfigParams::m_server_addons
|
||||
+ "/" + full_url;
|
||||
if(UserConfigParams::logAddons())
|
||||
printf("[addons] Downloading '%s' as '%s'.\n",
|
||||
printf("[addons] Downloading '%s' as '%s'.\n",
|
||||
full_url.c_str(), request->getSavePath().c_str());
|
||||
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_URL, full_url.c_str());
|
||||
@ -516,7 +516,7 @@ CURLcode NetworkHttp::downloadFileInternal(Request *request)
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_PROGRESSDATA, request);
|
||||
FILE * fout = fopen((full_save+".part").c_str(), "wb");
|
||||
|
||||
|
||||
if(!fout)
|
||||
{
|
||||
printf("[addons] Can't open '%s' for writing, ignored.\n",
|
||||
@ -526,8 +526,8 @@ CURLcode NetworkHttp::downloadFileInternal(Request *request)
|
||||
//from and out
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_WRITEDATA, fout );
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_WRITEFUNCTION, fwrite);
|
||||
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_PROGRESSFUNCTION,
|
||||
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_PROGRESSFUNCTION,
|
||||
&NetworkHttp::progressDownload);
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_NOPROGRESS, 0);
|
||||
|
||||
@ -541,14 +541,14 @@ CURLcode NetworkHttp::downloadFileInternal(Request *request)
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_CONNECTTIMEOUT, 20);
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_LOW_SPEED_LIMIT, 10);
|
||||
curl_easy_setopt(m_curl_session, CURLOPT_LOW_SPEED_TIME, 20);
|
||||
|
||||
|
||||
CURLcode status = curl_easy_perform(m_curl_session);
|
||||
fclose(fout);
|
||||
if(status==CURLE_OK)
|
||||
{
|
||||
if(UserConfigParams::logAddons())
|
||||
printf("[addons] Download successful.\n");
|
||||
// The behaviour of rename is unspecified if the target
|
||||
// The behaviour of rename is unspecified if the target
|
||||
// file should already exist - so remove it.
|
||||
file_manager->removeFile(full_save);
|
||||
int ret = rename((full_save+".part").c_str(), full_save.c_str());
|
||||
@ -567,26 +567,26 @@ CURLcode NetworkHttp::downloadFileInternal(Request *request)
|
||||
printf("[addons] Problems downloading file - return code %d.\n",
|
||||
status);
|
||||
}
|
||||
|
||||
|
||||
request->setProgress( (status==CURLE_OK) ? 1.0f : -1.0f );
|
||||
return status;
|
||||
} // downloadFileInternal
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Signals to the progress function to request any ongoing download to be
|
||||
* cancelled. This function can also be called if there is actually no
|
||||
* download atm. The function progressDownload checks m_abort and will
|
||||
/** Signals to the progress function to request any ongoing download to be
|
||||
* cancelled. This function can also be called if there is actually no
|
||||
* download atm. The function progressDownload checks m_abort and will
|
||||
* return a non-zero value which causes libcurl to abort. */
|
||||
void NetworkHttp::cancelAllDownloads()
|
||||
{
|
||||
void NetworkHttp::cancelAllDownloads()
|
||||
{
|
||||
if(UserConfigParams::logAddons())
|
||||
printf("[addons] Requesting cancellation of download.\n");
|
||||
m_abort.setAtomic(true);
|
||||
m_abort.setAtomic(true);
|
||||
} // cancelAllDownload
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** External interface to download a file asynchronously. This will wake up
|
||||
* the thread and schedule it to download the file. The calling program has
|
||||
/** External interface to download a file asynchronously. This will wake up
|
||||
* the thread and schedule it to download the file. The calling program has
|
||||
* to poll using getProgress() to find out if the download has finished.
|
||||
* \param url The file from the server to download.
|
||||
* \param save The name to save the downloaded file under. Defaults to
|
||||
@ -601,12 +601,12 @@ Request *NetworkHttp::downloadFileAsynchron(const std::string &url,
|
||||
// Limit priorities to 99 so that important system requests
|
||||
// (init and quit) will have highest priority.
|
||||
assert(priority<=99);
|
||||
Request *request = new Request(Request::HC_DOWNLOAD_FILE, priority,
|
||||
Request *request = new Request(Request::HC_DOWNLOAD_FILE, priority,
|
||||
manage_memory,
|
||||
url, (save!="") ? save : url );
|
||||
|
||||
if(UserConfigParams::logAddons())
|
||||
printf("[addons] Download asynchron '%s' as '%s'.\n",
|
||||
printf("[addons] Download asynchron '%s' as '%s'.\n",
|
||||
request->getURL().c_str(), request->getSavePath().c_str());
|
||||
insertRequest(request);
|
||||
return request;
|
||||
@ -630,20 +630,20 @@ void NetworkHttp::insertRequest(Request *request)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Callback function from curl: inform about progress.
|
||||
* \param clientp
|
||||
* \param clientp
|
||||
* \param download_total Total size of data to download.
|
||||
* \param download_now How much has been downloaded so far.
|
||||
* \param upload_total Total amount of upload.
|
||||
* \param upload_now How muc has been uploaded so far.
|
||||
*/
|
||||
int NetworkHttp::progressDownload(void *clientp,
|
||||
double download_total, double download_now,
|
||||
int NetworkHttp::progressDownload(void *clientp,
|
||||
double download_total, double download_now,
|
||||
double upload_total, double upload_now)
|
||||
{
|
||||
Request *request = (Request *)clientp;
|
||||
|
||||
|
||||
NetworkHttp* self = (NetworkHttp*)INetworkHttp::get();
|
||||
|
||||
|
||||
// Check if we are asked to abort the download. If so, signal this
|
||||
// back to libcurl by returning a non-zero status.
|
||||
if(self->m_abort.getAtomic() || request->isCancelled() )
|
||||
@ -652,7 +652,7 @@ int NetworkHttp::progressDownload(void *clientp,
|
||||
{
|
||||
if(self->m_abort.getAtomic())
|
||||
{
|
||||
// Reset abort flag so that the next download will work
|
||||
// Reset abort flag so that the next download will work
|
||||
// as expected.
|
||||
self->m_abort.setAtomic(false);
|
||||
printf("[addons] Global abort of downloads.\n");
|
||||
@ -669,11 +669,11 @@ int NetworkHttp::progressDownload(void *clientp,
|
||||
if(download_now < download_total)
|
||||
{
|
||||
f = (float)download_now / (float)download_total;
|
||||
// In case of floating point rouding errors make sure that
|
||||
// In case of floating point rouding errors make sure that
|
||||
// 1.0 is only reached when downloadFileInternal is finished
|
||||
if (f>=1.0f) f=0.99f;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// Don't set progress to 1.0f; this is done in loadFileInternal
|
||||
// after checking curls return code!
|
||||
|
@ -72,8 +72,8 @@ void NewsManager::checkRedirect(const XMLNode *xml)
|
||||
{
|
||||
if(UserConfigParams::logAddons())
|
||||
{
|
||||
std::cout << "[Addons] Current server: "
|
||||
<< (std::string)UserConfigParams::m_server_addons
|
||||
std::cout << "[Addons] Current server: "
|
||||
<< (std::string)UserConfigParams::m_server_addons
|
||||
<< std::endl
|
||||
<< "[Addons] New server: " << new_server << std::endl;
|
||||
}
|
||||
@ -85,8 +85,8 @@ void NewsManager::checkRedirect(const XMLNode *xml)
|
||||
/** Updates the 'news' string to be displayed in the main menu.
|
||||
* \param xml The XML data from the news file.
|
||||
* \param filename The filename of the news xml file. Only needed
|
||||
* in case of an error (e.g. the file might be corrupted)
|
||||
* - the file will be deleted so that on next start of stk it
|
||||
* in case of an error (e.g. the file might be corrupted)
|
||||
* - the file will be deleted so that on next start of stk it
|
||||
* will be updated again.
|
||||
*/
|
||||
void NewsManager::updateNews(const XMLNode *xml, const std::string &filename)
|
||||
@ -123,7 +123,7 @@ void NewsManager::updateNews(const XMLNode *xml, const std::string &filename)
|
||||
{
|
||||
|
||||
if(!important)
|
||||
m_all_news_messages += m_all_news_messages.size()>0
|
||||
m_all_news_messages += m_all_news_messages.size()>0
|
||||
? message_divider + news
|
||||
: news;
|
||||
else
|
||||
@ -168,9 +168,9 @@ void NewsManager::addNewsMessage(const core::stringw &s)
|
||||
m_news.unlock();
|
||||
} // addNewsMessage
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the important message with the smallest id that has not been
|
||||
/** Returns the important message with the smallest id that has not been
|
||||
* shown, or NULL if no important (not shown before) message exists atm. The
|
||||
* user config is updated to store the last important message id shown.
|
||||
* user config is updated to store the last important message id shown.
|
||||
*/
|
||||
const core::stringw NewsManager::getImportantMessage()
|
||||
{
|
||||
@ -179,10 +179,10 @@ const core::stringw NewsManager::getImportantMessage()
|
||||
for(unsigned int i=0; i<m_news.getData().size(); i++)
|
||||
{
|
||||
const NewsMessage &m = m_news.getData()[i];
|
||||
//
|
||||
if(m.isImportant() &&
|
||||
//
|
||||
if(m.isImportant() &&
|
||||
m.getMessageId()>UserConfigParams::m_last_important_message_id &&
|
||||
(index == -1 ||
|
||||
(index == -1 ||
|
||||
m.getMessageId() < m_news.getData()[index].getMessageId() ) )
|
||||
{
|
||||
index = i;
|
||||
@ -224,7 +224,7 @@ const core::stringw NewsManager::getNextNewsMessage()
|
||||
|
||||
if(m_news.getData().size()==0)
|
||||
{
|
||||
// Lock
|
||||
// Lock
|
||||
m_news.unlock();
|
||||
return "";
|
||||
}
|
||||
@ -233,7 +233,7 @@ const core::stringw NewsManager::getNextNewsMessage()
|
||||
{
|
||||
m_current_news_message++;
|
||||
if(m_current_news_message >= (int)m_news.getData().size())
|
||||
m_current_news_message = 0;
|
||||
m_current_news_message = 0;
|
||||
|
||||
m = m_news.getData()[m_current_news_message].getNews();
|
||||
}
|
||||
|
@ -24,9 +24,9 @@
|
||||
Request::Request(HttpCommands command, int priority, bool manage_memory)
|
||||
: m_progress(0)
|
||||
{
|
||||
m_command = command;
|
||||
m_command = command;
|
||||
m_priority = priority;
|
||||
m_url = "";
|
||||
m_url = "";
|
||||
m_full_path = "";
|
||||
m_manage_memory = manage_memory;
|
||||
m_icon_addon = NULL;
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <fstream>
|
||||
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
@ -58,16 +58,16 @@ bool extract_zip(const std::string &from, const std::string &to)
|
||||
{
|
||||
//Add the zip to the file system
|
||||
IFileSystem *file_system = irr_driver->getDevice()->getFileSystem();
|
||||
if(!file_system->addFileArchive(from.c_str(),
|
||||
/*ignoreCase*/false,
|
||||
if(!file_system->addFileArchive(from.c_str(),
|
||||
/*ignoreCase*/false,
|
||||
/*ignorePath*/true, io::EFAT_ZIP))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the recently added archive, which is necessary to get a
|
||||
// Get the recently added archive, which is necessary to get a
|
||||
// list of file in the zip archive.
|
||||
io::IFileArchive *zip_archive =
|
||||
io::IFileArchive *zip_archive =
|
||||
file_system->getFileArchive(file_system->getFileArchiveCount()-1);
|
||||
const io::IFileList *zip_file_list = zip_archive->getFileList();
|
||||
// Copy all files from the zip archive to the destination
|
||||
@ -80,7 +80,7 @@ bool extract_zip(const std::string &from, const std::string &to)
|
||||
if(current_file[0]=='.') continue;
|
||||
const std::string base = StringUtils::getBasename(current_file);
|
||||
|
||||
IReadFile* src_file =
|
||||
IReadFile* src_file =
|
||||
zip_archive->createAndOpenFile(current_file.c_str());
|
||||
if(!src_file)
|
||||
{
|
||||
@ -90,7 +90,7 @@ bool extract_zip(const std::string &from, const std::string &to)
|
||||
continue;
|
||||
}
|
||||
|
||||
IWriteFile* dst_file =
|
||||
IWriteFile* dst_file =
|
||||
file_system->createAndWriteFile((to+"/"+base).c_str());
|
||||
if(dst_file == NULL)
|
||||
{
|
||||
@ -112,13 +112,13 @@ bool extract_zip(const std::string &from, const std::string &to)
|
||||
dst_file->drop();
|
||||
src_file->drop();
|
||||
}
|
||||
// Remove the zip from the filesystem to save memory and avoid
|
||||
// Remove the zip from the filesystem to save memory and avoid
|
||||
// problem with a name conflict. Note that we have to convert
|
||||
// the path using getAbsolutePath, otherwise windows name
|
||||
// will not be detected correctly (e.g. if from=c:\... the
|
||||
// stored filename will be c:/..., which then does not match
|
||||
// on removing it. getAbsolutePath will convert all \ to /.
|
||||
file_system->removeFileArchive(file_system->getAbsolutePath(from.c_str()));
|
||||
|
||||
|
||||
return !error;
|
||||
} // extract_zip
|
||||
|
@ -68,7 +68,7 @@ AnimationBase::AnimationBase(Ipo *ipo)
|
||||
* \param xyz Position of the object.
|
||||
* \param hpr Rotation of the object.
|
||||
*/
|
||||
void AnimationBase::setInitialTransform(const Vec3 &xyz,
|
||||
void AnimationBase::setInitialTransform(const Vec3 &xyz,
|
||||
const Vec3 &hpr)
|
||||
{
|
||||
Ipo* curr;
|
||||
@ -100,7 +100,7 @@ void AnimationBase::reset()
|
||||
void AnimationBase::update(float dt, Vec3 *xyz, Vec3 *hpr, Vec3 *scale)
|
||||
{
|
||||
assert(!isnan(m_current_time));
|
||||
|
||||
|
||||
// Don't do anything if the animation is disabled
|
||||
if(!m_playing) return;
|
||||
m_current_time += dt;
|
||||
|
@ -45,7 +45,7 @@ Ipo::IpoData::IpoData(const XMLNode &curve, float fps, bool reverse)
|
||||
{
|
||||
if(curve.getName()!="curve")
|
||||
{
|
||||
fprintf(stderr, "Expected 'curve' for animation, got '%s' --> Ignored.\n",
|
||||
fprintf(stderr, "Expected 'curve' for animation, got '%s' --> Ignored.\n",
|
||||
curve.getName().c_str());
|
||||
return;
|
||||
}
|
||||
@ -54,7 +54,7 @@ Ipo::IpoData::IpoData(const XMLNode &curve, float fps, bool reverse)
|
||||
m_channel=IPO_MAX;
|
||||
for(unsigned int i=IPO_LOCX; i<IPO_MAX; i++)
|
||||
{
|
||||
if(m_all_channel_names[i]==channel)
|
||||
if(m_all_channel_names[i]==channel)
|
||||
{
|
||||
m_channel=(IpoChannelType)i;
|
||||
break;
|
||||
@ -62,12 +62,12 @@ Ipo::IpoData::IpoData(const XMLNode &curve, float fps, bool reverse)
|
||||
}
|
||||
if(m_channel==IPO_MAX)
|
||||
{
|
||||
fprintf(stderr, "Unknown animation channel: '%s' - aborting.\n",
|
||||
fprintf(stderr, "Unknown animation channel: '%s' - aborting.\n",
|
||||
channel.c_str());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
std::string interp;
|
||||
std::string interp;
|
||||
curve.get("interpolation", &interp);
|
||||
if (interp=="const" ) m_interpolation = IP_CONST;
|
||||
else if(interp=="linear") m_interpolation = IP_LINEAR;
|
||||
@ -110,7 +110,7 @@ void Ipo::IpoData::readIPO(const XMLNode &curve, float fps, bool reverse)
|
||||
{
|
||||
int node_index = reverse ? curve.getNumNodes()-i-1 : i;
|
||||
const XMLNode *node = curve.getNode(node_index);
|
||||
core::vector2df xy;
|
||||
core::vector2df xy;
|
||||
node->get("c", &xy);
|
||||
// Convert blender's frame number (1 ...) into time (0 ...)
|
||||
float t = (xy.X-1)/fps;
|
||||
@ -121,11 +121,11 @@ void Ipo::IpoData::readIPO(const XMLNode &curve, float fps, bool reverse)
|
||||
if(m_interpolation==IP_BEZIER)
|
||||
{
|
||||
Vec3 handle1, handle2;
|
||||
core::vector2df handle;
|
||||
core::vector2df handle;
|
||||
node->get(reverse ? "h2" : "h1", &handle);
|
||||
handle1.setW((xy.X-1)/fps);
|
||||
handle1.setX(handle.Y);
|
||||
node->get(reverse ? "h1" : "h2", &handle);
|
||||
node->get(reverse ? "h1" : "h2", &handle);
|
||||
handle2.setW((xy.X-1)/fps);
|
||||
handle2.setX(handle.Y);
|
||||
m_handle1.push_back(handle1);
|
||||
@ -136,9 +136,9 @@ void Ipo::IpoData::readIPO(const XMLNode &curve, float fps, bool reverse)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Reads in 3 dimensional curve data - i.e. the xml file contains xyz, but no
|
||||
* time. If the curve is using bezier interpolation, the curve is
|
||||
* approximated by piecewise linear functions. Reason is that bezier curves
|
||||
* can not (easily) be used for smooth (i.e. constant speed) driving:
|
||||
* time. If the curve is using bezier interpolation, the curve is
|
||||
* approximated by piecewise linear functions. Reason is that bezier curves
|
||||
* can not (easily) be used for smooth (i.e. constant speed) driving:
|
||||
* A linear time variation in [0, 1] will result in non-linear distances
|
||||
* for the bezier function, which is a 3rd degree polynomial (--> the speed
|
||||
* which is the deviation of this function is a 2nd degree polynomial, and
|
||||
@ -171,8 +171,8 @@ void Ipo::IpoData::readCurve(const XMLNode &curve, bool reverse)
|
||||
if(i>0)
|
||||
{
|
||||
// We have to take a copy of the end point, since otherwise
|
||||
// it can happen that as more points are added to m_points
|
||||
// in the approximateBezier function, the data gets
|
||||
// it can happen that as more points are added to m_points
|
||||
// in the approximateBezier function, the data gets
|
||||
// reallocated and then the reference to the original point
|
||||
// is not correct anymore.
|
||||
Vec3 end_point = m_points[m_points.size()-1];
|
||||
@ -183,9 +183,9 @@ void Ipo::IpoData::readCurve(const XMLNode &curve, bool reverse)
|
||||
m_points.push_back(point);
|
||||
} // for i<getNumNodes()
|
||||
|
||||
// The handles of a bezier curve are not needed anymore and can be
|
||||
// The handles of a bezier curve are not needed anymore and can be
|
||||
// removed now (since the bezier funciton has been replaced with a
|
||||
// piecewise linear
|
||||
// piecewise linear
|
||||
if(m_interpolation==IP_BEZIER)
|
||||
{
|
||||
m_handle1.clear();
|
||||
@ -209,7 +209,7 @@ void Ipo::IpoData::readCurve(const XMLNode &curve, bool reverse)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** This function approximates a bezier curve by piecewise linear functions.
|
||||
* It uses quite primitive approximations: if the estimated distance of
|
||||
* the bezier curve at between t=t0 and t=t1 is greater than 2, it
|
||||
* the bezier curve at between t=t0 and t=t1 is greater than 2, it
|
||||
* inserts one point at (t0+t1)/2, and recursively splits the two intervals
|
||||
* further. End condition is either a maximum recursion depth of 6 or
|
||||
* an estimated curve length of less than 2. It does not add any points
|
||||
@ -218,7 +218,7 @@ void Ipo::IpoData::readCurve(const XMLNode &curve, bool reverse)
|
||||
* \param p0, p1, h0, h1: The bezier parameters.
|
||||
* \param rec_level The recursion level to avoid creating too many points.
|
||||
*/
|
||||
void Ipo::IpoData::approximateBezier(float t0, float t1,
|
||||
void Ipo::IpoData::approximateBezier(float t0, float t1,
|
||||
const Vec3 &p0, const Vec3 &p1,
|
||||
const Vec3 &h0, const Vec3 &h1,
|
||||
unsigned int rec_level)
|
||||
@ -247,14 +247,14 @@ void Ipo::IpoData::approximateBezier(float t0, float t1,
|
||||
} // approximateBezier
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Approximates the length of a bezier curve using a simple Euler
|
||||
/** Approximates the length of a bezier curve using a simple Euler
|
||||
* approximation by dividing the interval [t0, t1] into 10 pieces. Good enough
|
||||
* for our needs in STK.
|
||||
* \param t0, t1 Approximate for t in [t0, t1].
|
||||
* \param p0, p1 The start and end point of the curve.
|
||||
* \param h0, h1 The control points for the corresponding points.
|
||||
*/
|
||||
float Ipo::IpoData::approximateLength(float t0, float t1,
|
||||
float Ipo::IpoData::approximateLength(float t0, float t1,
|
||||
const Vec3 &p0, const Vec3 &p1,
|
||||
const Vec3 &h0, const Vec3 &h1)
|
||||
{
|
||||
@ -283,7 +283,7 @@ float Ipo::IpoData::approximateLength(float t0, float t1,
|
||||
} // IpoData::approximateLength
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Adjusts the time so that it is between start and end of this Ipo. This
|
||||
/** Adjusts the time so that it is between start and end of this Ipo. This
|
||||
* takes the extend type into account, e.g. cyclic animations will just
|
||||
* use a modulo operation, while constant extends will return start or
|
||||
* end time directly.
|
||||
@ -295,7 +295,7 @@ float Ipo::IpoData::adjustTime(float time)
|
||||
{
|
||||
switch(m_extend)
|
||||
{
|
||||
case IpoData::ET_CYCLIC:
|
||||
case IpoData::ET_CYCLIC:
|
||||
time = m_start_time + fmodf(time, m_end_time-m_start_time); break;
|
||||
case ET_CONST:
|
||||
time = m_start_time; break;
|
||||
@ -309,7 +309,7 @@ float Ipo::IpoData::adjustTime(float time)
|
||||
{
|
||||
switch(m_extend)
|
||||
{
|
||||
case ET_CYCLIC:
|
||||
case ET_CYCLIC:
|
||||
time = m_start_time + fmodf(time, m_end_time-m_start_time); break;
|
||||
case ET_CONST:
|
||||
time = m_end_time; break;
|
||||
@ -329,7 +329,7 @@ float Ipo::IpoData::get(float time, unsigned int index, unsigned int n)
|
||||
case IP_CONST : return m_points[n][index];
|
||||
case IP_LINEAR : {
|
||||
float t = time-m_points[n].getW();
|
||||
return m_points[n][index]
|
||||
return m_points[n][index]
|
||||
+ t*(m_points[n+1][index]-m_points[n][index]) /
|
||||
(m_points[n+1].getW()-m_points[n].getW());
|
||||
}
|
||||
@ -340,7 +340,7 @@ float Ipo::IpoData::get(float time, unsigned int index, unsigned int n)
|
||||
}
|
||||
float t = (time-m_points[n].getW())
|
||||
/ (m_points[n+1].getW()-m_points[n].getW());
|
||||
return getCubicBezier(t,
|
||||
return getCubicBezier(t,
|
||||
m_points [n ][index],
|
||||
m_handle2[n ][index],
|
||||
m_handle1[n+1][index],
|
||||
@ -357,7 +357,7 @@ float Ipo::IpoData::get(float time, unsigned int index, unsigned int n)
|
||||
* \param t The parameter for the bezier curve, must be in [0,1].
|
||||
* \param p0, p1, p2, p3 The four control points.
|
||||
*/
|
||||
float Ipo::IpoData::getCubicBezier(float t, float p0, float p1,
|
||||
float Ipo::IpoData::getCubicBezier(float t, float p0, float p1,
|
||||
float p2, float p3) const
|
||||
{
|
||||
float c = 3.0f*(p1-p0);
|
||||
@ -368,13 +368,13 @@ float Ipo::IpoData::getCubicBezier(float t, float p0, float p1,
|
||||
|
||||
// ============================================================================
|
||||
/** The Ipo constructor. Ipos can share the actual data to interpolate, which
|
||||
* is stored in a separate IpoData object, see Ipo(const Ipo *ipo)
|
||||
* is stored in a separate IpoData object, see Ipo(const Ipo *ipo)
|
||||
* constructor. This is used for cannons: the actual check line stores the
|
||||
* 'master' Ipo, and each actual IPO that animate a kart just use a copy
|
||||
* of this read-only data.
|
||||
* \param curve The XML data for this curve.
|
||||
* \param fps Frames per second, used to convert all frame based value
|
||||
* in the xml file into seconds.
|
||||
* in the xml file into seconds.
|
||||
* \param reverse If this is set to true, the ipo data will be reverse. This
|
||||
* is used by the cannon if the track is driven in reverse.
|
||||
*/
|
||||
@ -421,7 +421,7 @@ Ipo::~Ipo()
|
||||
* \param xyz Position of the object.
|
||||
* \param hpr Rotation of the object.
|
||||
*/
|
||||
void Ipo::setInitialTransform(const Vec3 &xyz,
|
||||
void Ipo::setInitialTransform(const Vec3 &xyz,
|
||||
const Vec3 &hpr)
|
||||
{
|
||||
m_ipo_data->m_initial_xyz = xyz;
|
||||
@ -429,7 +429,7 @@ void Ipo::setInitialTransform(const Vec3 &xyz,
|
||||
} // setInitialTransform
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Resets the IPO for (re)starting an animation.
|
||||
/** Resets the IPO for (re)starting an animation.
|
||||
*/
|
||||
void Ipo::reset()
|
||||
{
|
||||
@ -437,7 +437,7 @@ void Ipo::reset()
|
||||
} // reset
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updates the time of this ipo and interpolates the new position and
|
||||
/** Updates the time of this ipo and interpolates the new position and
|
||||
* rotation (taking the cycle length etc. into account). If a NULL is
|
||||
* given, the value is not updated.
|
||||
* \param time Current time for which to determine the interpolation.
|
||||
@ -459,7 +459,7 @@ void Ipo::update(float time, Vec3 *xyz, Vec3 *hpr,Vec3 *scale)
|
||||
case Ipo::IPO_SCALEX : if(scale) scale->setX(get(time, 0)); break;
|
||||
case Ipo::IPO_SCALEY : if(scale) scale->setY(get(time, 0)); break;
|
||||
case Ipo::IPO_SCALEZ : if(scale) scale->setZ(get(time, 0)); break;
|
||||
case Ipo::IPO_LOCXYZ :
|
||||
case Ipo::IPO_LOCXYZ :
|
||||
{
|
||||
if(xyz)
|
||||
{
|
||||
@ -482,9 +482,9 @@ void Ipo::update(float time, Vec3 *xyz, Vec3 *hpr,Vec3 *scale)
|
||||
float Ipo::get(float time, unsigned int index) const
|
||||
{
|
||||
assert(!isnan(time));
|
||||
|
||||
|
||||
// Avoid crash in case that only one point is given for this IPO.
|
||||
if(m_next_n==0)
|
||||
if(m_next_n==0)
|
||||
return m_ipo_data->m_points[0][index];
|
||||
|
||||
time = m_ipo_data->adjustTime(time);
|
||||
@ -494,8 +494,8 @@ float Ipo::get(float time, unsigned int index) const
|
||||
if(time < m_ipo_data->m_points[m_next_n-1].getW())
|
||||
m_next_n = 1;
|
||||
// Search for the first point in the (sorted) array which is greater or equal
|
||||
// to the current time.
|
||||
while(m_next_n<m_ipo_data->m_points.size()-1 &&
|
||||
// to the current time.
|
||||
while(m_next_n<m_ipo_data->m_points.size()-1 &&
|
||||
time >=m_ipo_data->m_points[m_next_n].getW())
|
||||
m_next_n++;
|
||||
float rval = m_ipo_data->get(time, index, m_next_n-1);
|
||||
|
@ -40,12 +40,12 @@
|
||||
ThreeDAnimation::ThreeDAnimation(const XMLNode &node, TrackObject* object) : AnimationBase(node)
|
||||
{
|
||||
m_object = object;
|
||||
|
||||
|
||||
m_crash_reset = false;
|
||||
m_explode_kart = false;
|
||||
node.get("reset", &m_crash_reset);
|
||||
node.get("explode", &m_explode_kart);
|
||||
|
||||
|
||||
m_important_animation = (World::getWorld()->getIdent() == IDENT_CUSTSCENE);
|
||||
node.get("important", &m_important_animation);
|
||||
|
||||
@ -53,7 +53,7 @@ ThreeDAnimation::ThreeDAnimation(const XMLNode &node, TrackObject* object) : Ani
|
||||
setInitialTransform(object->getInitXYZ(),
|
||||
object->getInitRotation() );
|
||||
m_hpr = object->getInitRotation();
|
||||
|
||||
|
||||
assert(!isnan(m_hpr.getX()));
|
||||
assert(!isnan(m_hpr.getY()));
|
||||
assert(!isnan(m_hpr.getZ()));
|
||||
@ -75,13 +75,13 @@ void ThreeDAnimation::update(float dt)
|
||||
{
|
||||
Vec3 xyz = m_object->getPosition();
|
||||
Vec3 scale = m_object->getScale();
|
||||
|
||||
|
||||
AnimationBase::update(dt, &xyz, &m_hpr, &scale); //updates all IPOs
|
||||
//m_node->setPosition(xyz.toIrrVector());
|
||||
//m_node->setScale(scale.toIrrVector());
|
||||
|
||||
|
||||
// Note that the rotation order of irrlicht is different from the one
|
||||
// in blender. So in order to reproduce the blender IPO rotations
|
||||
// in blender. So in order to reproduce the blender IPO rotations
|
||||
// correctly, we have to get the rotations around each axis and combine
|
||||
// them in the right order for irrlicht
|
||||
core::matrix4 m;
|
||||
|
@ -45,7 +45,7 @@ MusicInformation *MusicInformation::create(const std::string &filename)
|
||||
if (!root) return NULL;
|
||||
if(root->getName()!="music")
|
||||
{
|
||||
Log::error("MusicInformation",
|
||||
Log::error("MusicInformation",
|
||||
"Music file '%s' does not contain music node.\n",
|
||||
filename.c_str());
|
||||
delete root;
|
||||
@ -57,7 +57,7 @@ MusicInformation *MusicInformation::create(const std::string &filename)
|
||||
!root->get("file", &s) )
|
||||
|
||||
{
|
||||
Log::error("MusicInformation",
|
||||
Log::error("MusicInformation",
|
||||
"One of 'title', 'composer' or 'file' attribute "
|
||||
"is missing in the music XML file '%s'!\n",
|
||||
filename.c_str());
|
||||
@ -70,7 +70,7 @@ MusicInformation *MusicInformation::create(const std::string &filename)
|
||||
} // create()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
MusicInformation::MusicInformation(const XMLNode *root,
|
||||
MusicInformation::MusicInformation(const XMLNode *root,
|
||||
const std::string &filename)
|
||||
{
|
||||
m_title = "";
|
||||
@ -100,9 +100,9 @@ MusicInformation::MusicInformation(const XMLNode *root,
|
||||
root->get("tracks", &m_all_tracks );
|
||||
root->get("fast", &m_enable_fast );
|
||||
root->get("fast-filename", &m_fast_filename );
|
||||
|
||||
|
||||
m_adjusted_gain = m_gain;
|
||||
|
||||
|
||||
// Get the path from the filename and add it to the ogg filename
|
||||
std::string path = StringUtils::getPath(filename);
|
||||
m_normal_filename = path + "/" + m_normal_filename;
|
||||
@ -112,7 +112,7 @@ MusicInformation::MusicInformation(const XMLNode *root,
|
||||
{
|
||||
m_fast_filename = path + "/" + m_fast_filename;
|
||||
}
|
||||
|
||||
|
||||
assert(m_normal_filename.size() > 0);
|
||||
|
||||
} // MusicInformation
|
||||
@ -152,21 +152,21 @@ void MusicInformation::startMusic()
|
||||
"format is not recognized.\n", m_normal_filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (m_normal_music != NULL) delete m_normal_music;
|
||||
|
||||
|
||||
#if HAVE_OGGVORBIS
|
||||
m_normal_music = new MusicOggStream();
|
||||
#else
|
||||
m_normal_music = new MusicDummy();
|
||||
#endif
|
||||
|
||||
|
||||
if((m_normal_music->load(m_normal_filename)) == false)
|
||||
{
|
||||
delete m_normal_music;
|
||||
m_normal_music = NULL;
|
||||
Log::warn("MusicInformation", "Unable to load music %s, "
|
||||
"not supported or not found.\n",
|
||||
"not supported or not found.\n",
|
||||
m_normal_filename.c_str());
|
||||
return;
|
||||
}
|
||||
@ -176,7 +176,7 @@ void MusicInformation::startMusic()
|
||||
// Then (if available) load the music for the last track
|
||||
// -----------------------------------------------------
|
||||
if (m_fast_music != NULL) delete m_fast_music;
|
||||
if (m_fast_filename == "")
|
||||
if (m_fast_filename == "")
|
||||
{
|
||||
m_fast_music = NULL;
|
||||
return; // no fast music
|
||||
@ -184,12 +184,12 @@ void MusicInformation::startMusic()
|
||||
|
||||
if(StringUtils::getExtension(m_fast_filename)!="ogg")
|
||||
{
|
||||
Log::warn(
|
||||
Log::warn(
|
||||
"Music file %s format not recognized, fast music is ignored\n",
|
||||
m_fast_filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#if HAVE_OGGVORBIS
|
||||
m_fast_music = new MusicOggStream();
|
||||
#else
|
||||
@ -262,7 +262,7 @@ void MusicInformation::update(float dt)
|
||||
//-----------------------------------------------------------------------------
|
||||
void MusicInformation::stopMusic()
|
||||
{
|
||||
if (m_normal_music != NULL)
|
||||
if (m_normal_music != NULL)
|
||||
{
|
||||
m_normal_music->stopMusic();
|
||||
delete m_normal_music;
|
||||
@ -291,7 +291,7 @@ void MusicInformation::resumeMusic()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void MusicInformation::volumeMusic(float gain)
|
||||
{
|
||||
{
|
||||
m_adjusted_gain = m_gain * gain;
|
||||
if (m_normal_music != NULL) m_normal_music->volumeMusic(m_adjusted_gain);
|
||||
if (m_fast_music != NULL) m_fast_music->volumeMusic(m_adjusted_gain);
|
||||
@ -307,7 +307,7 @@ void MusicInformation::setTemporaryVolume(float gain)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void MusicInformation::switchToFastMusic()
|
||||
{
|
||||
{
|
||||
if(!m_enable_fast) return;
|
||||
m_time_since_faster = 0.0f;
|
||||
if(m_fast_music)
|
||||
@ -317,7 +317,7 @@ void MusicInformation::switchToFastMusic()
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: for now this music is too annoying,
|
||||
// FIXME: for now this music is too annoying,
|
||||
m_mode = SOUND_FASTER;
|
||||
}
|
||||
} // switchToFastMusic
|
||||
|
@ -48,7 +48,7 @@ MusicManager::MusicManager()
|
||||
|
||||
//FIXME: I'm not sure that this code goes here
|
||||
#if HAVE_OGGVORBIS
|
||||
|
||||
|
||||
#if defined(__APPLE__) && !defined(NDEBUG)
|
||||
// HACK: On OSX, when OpenAL is initialized, breaking in a debugger causes
|
||||
// my iTunes music to stop too, which is highly annoying ;) so in debug
|
||||
@ -56,7 +56,7 @@ MusicManager::MusicManager()
|
||||
if (UserConfigParams::m_sfx || UserConfigParams::m_music)
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
ALCdevice* device = alcOpenDevice ( NULL ); //The default sound device
|
||||
if( device == NULL )
|
||||
{
|
||||
@ -79,14 +79,14 @@ MusicManager::MusicManager()
|
||||
m_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(__APPLE__) && !defined(NDEBUG)
|
||||
}
|
||||
#endif
|
||||
|
||||
alGetError(); //Called here to clear any non-important errors found
|
||||
#endif
|
||||
|
||||
|
||||
loadMusicInformation();
|
||||
} // MusicManager
|
||||
|
||||
@ -95,7 +95,7 @@ MusicManager::~MusicManager()
|
||||
{
|
||||
stopMusic();
|
||||
|
||||
for(std::map<std::string,MusicInformation*>::iterator
|
||||
for(std::map<std::string,MusicInformation*>::iterator
|
||||
i=m_all_music.begin(); i!=m_all_music.end(); i++)
|
||||
{
|
||||
delete i->second;
|
||||
@ -119,7 +119,7 @@ MusicManager::~MusicManager()
|
||||
//-----------------------------------------------------------------------------
|
||||
void MusicManager::loadMusicInformation()
|
||||
{
|
||||
// Load music files from data/music, and dirs defined in
|
||||
// Load music files from data/music, and dirs defined in
|
||||
// SUPERTUXKART_MUSIC_PATH
|
||||
std::vector<std::string> allMusicDirs=file_manager->getMusicDirs();
|
||||
for(std::vector<std::string>::iterator dir=allMusicDirs.begin();
|
||||
@ -135,7 +135,7 @@ void MusicManager::loadMusicFromOneDir(const std::string& dir)
|
||||
std::set<std::string> files;
|
||||
file_manager->listFiles(files, dir, /*is_full_path*/ true,
|
||||
/*make_full_path*/ true);
|
||||
for(std::set<std::string>::iterator i = files.begin();
|
||||
for(std::set<std::string>::iterator i = files.begin();
|
||||
i != files.end(); ++i)
|
||||
{
|
||||
if(StringUtils::getExtension(*i)!="music") continue;
|
||||
@ -149,10 +149,10 @@ void MusicManager::loadMusicFromOneDir(const std::string& dir)
|
||||
//-----------------------------------------------------------------------------
|
||||
void MusicManager::addMusicToTracks()
|
||||
{
|
||||
for(std::map<std::string,MusicInformation*>::iterator
|
||||
for(std::map<std::string,MusicInformation*>::iterator
|
||||
i=m_all_music.begin(); i!=m_all_music.end(); i++)
|
||||
{
|
||||
if(!i->second)
|
||||
if(!i->second)
|
||||
{
|
||||
fprintf(stderr, "Can't find music file '%s' - ignored.\n",
|
||||
i->first.c_str());
|
||||
@ -166,21 +166,21 @@ void MusicManager::addMusicToTracks()
|
||||
void MusicManager::startMusic(MusicInformation* mi, bool startRightNow)
|
||||
{
|
||||
// If this music is already playing, ignore this call.
|
||||
if (m_current_music != NULL &&
|
||||
m_current_music == mi &&
|
||||
m_current_music->isPlaying())
|
||||
if (m_current_music != NULL &&
|
||||
m_current_music == mi &&
|
||||
m_current_music->isPlaying())
|
||||
return;
|
||||
|
||||
// It is possible here that startMusic() will be called without first
|
||||
// calling stopMusic(). This would cause a memory leak by overwriting
|
||||
// m_current_music without first releasing its resources. Guard against
|
||||
// this here by making sure that stopMusic() is called before starting
|
||||
|
||||
// It is possible here that startMusic() will be called without first
|
||||
// calling stopMusic(). This would cause a memory leak by overwriting
|
||||
// m_current_music without first releasing its resources. Guard against
|
||||
// this here by making sure that stopMusic() is called before starting
|
||||
// new music.
|
||||
stopMusic();
|
||||
m_current_music = mi;
|
||||
|
||||
|
||||
if(!mi || !UserConfigParams::m_music || !m_initialized) return;
|
||||
|
||||
|
||||
mi->volumeMusic(m_masterGain);
|
||||
if (startRightNow) mi->startMusic();
|
||||
} // startMusic
|
||||
@ -201,12 +201,12 @@ void MusicManager::setMasterMusicVolume(float gain)
|
||||
|
||||
m_masterGain = gain;
|
||||
if(m_current_music) m_current_music->volumeMusic(m_masterGain);
|
||||
|
||||
|
||||
UserConfigParams::m_music_volume = m_masterGain;
|
||||
} // setMasterMusicVolume
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
/**
|
||||
*/
|
||||
MusicInformation* MusicManager::getMusicInformation(const std::string& filename)
|
||||
{
|
||||
|
@ -52,10 +52,10 @@ MusicOggStream::~MusicOggStream()
|
||||
bool MusicOggStream::load(const std::string& filename)
|
||||
{
|
||||
if (isPlaying()) stopMusic();
|
||||
|
||||
|
||||
m_error = true;
|
||||
m_fileName = filename;
|
||||
if(m_fileName=="") return false;
|
||||
if(m_fileName=="") return false;
|
||||
|
||||
m_oggFile = fopen(m_fileName.c_str(), "rb");
|
||||
|
||||
@ -64,18 +64,18 @@ bool MusicOggStream::load(const std::string& filename)
|
||||
Log::error("MusicOgg", "Loading Music: %s failed (fopen returned NULL)\n", m_fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#if defined( WIN32 ) || defined( WIN64 )
|
||||
const int result = ov_open_callbacks((void *)m_oggFile, &m_oggStream, NULL, 0, OV_CALLBACKS_DEFAULT);
|
||||
#else
|
||||
const int result = ov_open(m_oggFile, &m_oggStream, NULL, 0);
|
||||
#endif
|
||||
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
fclose(m_oggFile);
|
||||
|
||||
|
||||
|
||||
|
||||
const char* errorMessage;
|
||||
switch (result)
|
||||
{
|
||||
@ -97,12 +97,12 @@ bool MusicOggStream::load(const std::string& filename)
|
||||
default:
|
||||
errorMessage = "Unknown Error";
|
||||
}
|
||||
|
||||
|
||||
Log::error("MusicOgg", "Loading Music: %s failed : ov_open returned error code %i (%s)\n",
|
||||
m_fileName.c_str(), result, errorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
m_vorbisInfo = ov_info(&m_oggStream, -1);
|
||||
|
||||
if (m_vorbisInfo->channels == 1) nb_channels = AL_FORMAT_MONO16;
|
||||
@ -153,7 +153,7 @@ bool MusicOggStream::release()
|
||||
|
||||
pauseMusic();
|
||||
m_fileName= "";
|
||||
|
||||
|
||||
empty();
|
||||
alDeleteSources(1, &m_soundSource);
|
||||
check("alDeleteSources");
|
||||
@ -165,7 +165,7 @@ bool MusicOggStream::release()
|
||||
|
||||
m_soundSource = -1;
|
||||
m_playing = false;
|
||||
|
||||
|
||||
return true;
|
||||
} // release
|
||||
|
||||
@ -194,10 +194,10 @@ bool MusicOggStream::playMusic()
|
||||
bool MusicOggStream::isPlaying()
|
||||
{
|
||||
return m_playing;
|
||||
|
||||
|
||||
/*
|
||||
if (m_soundSource == -1) return false;
|
||||
|
||||
|
||||
ALenum state;
|
||||
alGetSourcei(m_soundSource, AL_SOURCE_STATE, &state);
|
||||
|
||||
@ -231,7 +231,7 @@ bool MusicOggStream::pauseMusic()
|
||||
bool MusicOggStream::resumeMusic()
|
||||
{
|
||||
m_playing = true;
|
||||
|
||||
|
||||
if (m_fileName == "")
|
||||
{
|
||||
// nothing is loaded
|
||||
@ -333,7 +333,7 @@ bool MusicOggStream::streamIntoBuffer(ALuint buffer)
|
||||
|
||||
while(size < m_buffer_size)
|
||||
{
|
||||
result = ov_read(&m_oggStream, pcm + size, m_buffer_size - size,
|
||||
result = ov_read(&m_oggStream, pcm + size, m_buffer_size - size,
|
||||
isBigEndian, 2, 1, &portion);
|
||||
|
||||
if(result > 0)
|
||||
|
@ -47,7 +47,7 @@ SFXBuffer::SFXBuffer(const std::string& file,
|
||||
m_loaded = false;
|
||||
m_max_dist = max_width;
|
||||
m_file = file;
|
||||
|
||||
|
||||
m_rolloff = rolloff;
|
||||
m_positional = positional;
|
||||
m_gain = gain;
|
||||
@ -65,7 +65,7 @@ SFXBuffer::SFXBuffer(const std::string& file,
|
||||
m_positional = false;
|
||||
m_loaded = false;
|
||||
m_file = file;
|
||||
|
||||
|
||||
node->get("rolloff", &m_rolloff );
|
||||
node->get("positional", &m_positional );
|
||||
node->get("volume", &m_gain );
|
||||
@ -78,17 +78,17 @@ bool SFXBuffer::load()
|
||||
{
|
||||
#if HAVE_OGGVORBIS
|
||||
if (m_loaded) return false;
|
||||
|
||||
|
||||
alGetError(); // clear errors from previously
|
||||
|
||||
|
||||
alGenBuffers(1, &m_buffer);
|
||||
if (!SFXManager::checkError("generating a buffer"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
assert( alIsBuffer(m_buffer) );
|
||||
|
||||
|
||||
if (!loadVorbisBuffer(m_file, m_buffer))
|
||||
{
|
||||
Log::error("SFXBuffer", "Could not load sound effect %s\n", m_file.c_str());
|
||||
@ -96,7 +96,7 @@ bool SFXBuffer::load()
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
m_loaded = true;
|
||||
return true;
|
||||
}
|
||||
@ -117,45 +117,45 @@ void SFXBuffer::unload()
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Load a vorbis file into an OpenAL buffer
|
||||
* based on a routine by Peter Mulholland, used with permission (quote :
|
||||
* based on a routine by Peter Mulholland, used with permission (quote :
|
||||
* "Feel free to use")
|
||||
*/
|
||||
bool SFXBuffer::loadVorbisBuffer(const std::string &name, ALuint buffer)
|
||||
{
|
||||
#if HAVE_OGGVORBIS
|
||||
const int ogg_endianness = (IS_LITTLE_ENDIAN ? 0 : 1);
|
||||
|
||||
|
||||
|
||||
|
||||
bool success = false;
|
||||
FILE *file;
|
||||
vorbis_info *info;
|
||||
OggVorbis_File oggFile;
|
||||
|
||||
|
||||
if (alIsBuffer(buffer) == AL_FALSE)
|
||||
{
|
||||
Log::error("SFXBuffer", "Error, bad OpenAL buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
file = fopen(name.c_str(), "rb");
|
||||
|
||||
|
||||
if(!file)
|
||||
{
|
||||
Log::error("SFXBuffer", "[SFXBuffer] LoadVorbisBuffer() - couldn't open file!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (ov_open_callbacks(file, &oggFile, NULL, 0, OV_CALLBACKS_NOCLOSE) != 0)
|
||||
{
|
||||
fclose(file);
|
||||
Log::error("SFXBuffer", "[SFXBuffer] LoadVorbisBuffer() - ov_open_callbacks() failed, file isn't vorbis?\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
info = ov_info(&oggFile, -1);
|
||||
|
||||
|
||||
long len = (long)ov_pcm_total(&oggFile, -1) * info->channels * 2; // always 16 bit data
|
||||
|
||||
|
||||
char *data = (char *) malloc(len);
|
||||
if(!data)
|
||||
{
|
||||
@ -163,25 +163,25 @@ bool SFXBuffer::loadVorbisBuffer(const std::string &name, ALuint buffer)
|
||||
Log::error("SFXBuffer", "[SFXBuffer] loadVorbisBuffer() - Error : LoadVorbisBuffer() - couldn't allocate decode buffer\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int bs = -1;
|
||||
long todo = len;
|
||||
char *bufpt = data;
|
||||
|
||||
|
||||
while (todo)
|
||||
{
|
||||
int read = ov_read(&oggFile, bufpt, todo, ogg_endianness, 2, 1, &bs);
|
||||
todo -= read;
|
||||
bufpt += read;
|
||||
}
|
||||
|
||||
alBufferData(buffer, (info->channels == 1) ? AL_FORMAT_MONO16
|
||||
|
||||
alBufferData(buffer, (info->channels == 1) ? AL_FORMAT_MONO16
|
||||
: AL_FORMAT_STEREO16,
|
||||
data, len, info->rate);
|
||||
success = true;
|
||||
|
||||
|
||||
free(data);
|
||||
|
||||
|
||||
ov_clear(&oggFile);
|
||||
fclose(file);
|
||||
return success;
|
||||
|
@ -59,11 +59,11 @@ SFXManager::SFXManager()
|
||||
m_master_gain = UserConfigParams::m_sfx_volume;
|
||||
// Init position, since it can be used before positionListener is called.
|
||||
m_position = Vec3(0,0,0);
|
||||
|
||||
|
||||
loadSfx();
|
||||
if (!sfxAllowed()) return;
|
||||
setMasterSFXVolume( UserConfigParams::m_sfx_volume );
|
||||
|
||||
|
||||
} // SoundManager
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -87,7 +87,7 @@ SFXManager::~SFXManager()
|
||||
}
|
||||
}
|
||||
m_quick_sounds.clear();
|
||||
|
||||
|
||||
// ---- clear m_all_sfx_types
|
||||
{
|
||||
std::map<std::string, SFXBuffer*>::iterator i = m_all_sfx_types.begin();
|
||||
@ -100,7 +100,7 @@ SFXManager::~SFXManager()
|
||||
m_all_sfx_types.clear();
|
||||
}
|
||||
m_all_sfx_types.clear();
|
||||
|
||||
|
||||
sfx_manager = NULL;
|
||||
} // ~SFXManager
|
||||
|
||||
@ -117,9 +117,9 @@ void SFXManager::soundToggled(const bool on)
|
||||
SFXBuffer* buffer = (*i).second;
|
||||
buffer->load();
|
||||
}
|
||||
|
||||
|
||||
resumeAll();
|
||||
|
||||
|
||||
const int sfx_amount = m_all_sfx.size();
|
||||
for (int n=0; n<sfx_amount; n++)
|
||||
{
|
||||
@ -136,7 +136,7 @@ void SFXManager::soundToggled(const bool on)
|
||||
|
||||
bool SFXManager::sfxAllowed()
|
||||
{
|
||||
if(!UserConfigParams::m_sfx || !m_initialized)
|
||||
if(!UserConfigParams::m_sfx || !m_initialized)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
@ -153,12 +153,12 @@ void SFXManager::loadSfx()
|
||||
{
|
||||
std::cerr << "Could not read sounf effects XML file " << sfx_config_name.c_str() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
const int amount = root->getNumNodes();
|
||||
for (int i=0; i<amount; i++)
|
||||
{
|
||||
const XMLNode* node = root->getNode(i);
|
||||
|
||||
|
||||
if (node->getName() == "sfx")
|
||||
{
|
||||
loadSingleSfx(node);
|
||||
@ -169,7 +169,7 @@ void SFXManager::loadSfx()
|
||||
throw std::runtime_error("Unknown node in sfx XML file");
|
||||
}
|
||||
}// nend for
|
||||
|
||||
|
||||
delete root;
|
||||
} // loadSfx
|
||||
|
||||
@ -192,21 +192,21 @@ SFXBuffer* SFXManager::addSingleSfx(const std::string &sfx_name,
|
||||
{
|
||||
|
||||
SFXBuffer* buffer = new SFXBuffer(sfx_file, positional, rolloff, max_width, gain);
|
||||
|
||||
|
||||
m_all_sfx_types[sfx_name] = buffer;
|
||||
|
||||
if (!m_initialized)
|
||||
|
||||
if (!m_initialized)
|
||||
{
|
||||
// Keep the buffer even if SFX is disabled, in case
|
||||
// SFX is enabled back later
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (UserConfigParams::logMisc())
|
||||
if (UserConfigParams::logMisc())
|
||||
Log::debug("SFXManager", "Loading SFX %s\n", sfx_file.c_str());
|
||||
|
||||
|
||||
if (buffer->load()) return buffer;
|
||||
|
||||
|
||||
return NULL;
|
||||
} // addSingleSFX
|
||||
|
||||
@ -221,23 +221,23 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
|
||||
|
||||
if (node->get("filename", &filename) == 0)
|
||||
{
|
||||
Log::error("SFXManager",
|
||||
Log::error("SFXManager",
|
||||
"/!\\ The 'filename' attribute is mandatory in the SFX XML file!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
std::string sfx_name = StringUtils::removeExtension(filename);
|
||||
/*
|
||||
if (node->get("name", &sfx_name) == 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
fprintf(stderr,
|
||||
"/!\\ The 'name' attribute is mandatory in the SFX XML file!\n");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
if(m_all_sfx_types.find(sfx_name)!=m_all_sfx_types.end())
|
||||
{
|
||||
Log::error("SFXManager",
|
||||
Log::error("SFXManager",
|
||||
"There is already a sfx named '%s' installed - new one is ignored.\n",
|
||||
sfx_name.c_str());
|
||||
return NULL;
|
||||
@ -247,7 +247,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
|
||||
// to load terrain specific sfx.
|
||||
const std::string full_path = (path == "") ? file_manager->getSFXFile(filename)
|
||||
: path;
|
||||
|
||||
|
||||
SFXBuffer tmpbuffer(full_path, node);
|
||||
|
||||
return addSingleSfx(sfx_name, full_path,
|
||||
@ -255,7 +255,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
|
||||
tmpbuffer.getRolloff(),
|
||||
tmpbuffer.getMaxDist(),
|
||||
tmpbuffer.getGain());
|
||||
|
||||
|
||||
} // loadSingleSfx
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -265,7 +265,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
|
||||
* call deleteSFX().
|
||||
* \param id Identifier of the sound effect to create.
|
||||
*/
|
||||
SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
|
||||
SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
|
||||
const bool add_to_SFX_list,
|
||||
const bool owns_buffer)
|
||||
{
|
||||
@ -280,18 +280,18 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
|
||||
// buffer->getFileName().c_str(), (unsigned int)buffer,
|
||||
// positional,
|
||||
// race_manager->getNumLocalPlayers(), buffer->isPositional());
|
||||
|
||||
|
||||
#if HAVE_OGGVORBIS
|
||||
assert( alIsBuffer(buffer->getBufferID()) );
|
||||
SFXBase* sfx = new SFXOpenAL(buffer, positional, buffer->getGain(), owns_buffer);
|
||||
#else
|
||||
SFXBase* sfx = new DummySFX(buffer, positional, buffer->getGain(), owns_buffer);
|
||||
#endif
|
||||
|
||||
|
||||
sfx->volume(m_master_gain);
|
||||
|
||||
|
||||
if (add_to_SFX_list) m_all_sfx.push_back(sfx);
|
||||
|
||||
|
||||
return sfx;
|
||||
} // createSoundSource
|
||||
|
||||
@ -306,7 +306,7 @@ void SFXManager::dump()
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SFXBase* SFXManager::createSoundSource(const std::string &name,
|
||||
SFXBase* SFXManager::createSoundSource(const std::string &name,
|
||||
const bool addToSFXList)
|
||||
{
|
||||
std::map<std::string, SFXBuffer*>::iterator i = m_all_sfx_types.find(name);
|
||||
@ -315,7 +315,7 @@ SFXBase* SFXManager::createSoundSource(const std::string &name,
|
||||
Log::error("SFXManager", "SFXManager::createSoundSource could not find the requested sound effect : '%s'\n", name.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return createSoundSource( i->second, addToSFXList );
|
||||
} // createSoundSource
|
||||
|
||||
@ -344,7 +344,7 @@ void SFXManager::deleteSFXMapping(const std::string &name)
|
||||
return;
|
||||
}
|
||||
(*i).second->unload();
|
||||
|
||||
|
||||
m_all_sfx_types.erase(i);
|
||||
|
||||
} // deleteSFXMapping
|
||||
@ -366,7 +366,7 @@ void SFXManager::deleteSFX(SFXBase *sfx)
|
||||
Log::warn("SFXManager", "SFXManager::deleteSFX : Warning: sfx not found in list.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
delete sfx;
|
||||
|
||||
m_all_sfx.erase(i);
|
||||
@ -395,18 +395,18 @@ void SFXManager::resumeAll()
|
||||
{
|
||||
// ignore unpausing if sound is disabled
|
||||
if (!sfxAllowed()) return;
|
||||
|
||||
|
||||
for (std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
|
||||
i!=m_all_sfx.end(); i++)
|
||||
{
|
||||
SFXStatus status = (*i)->getStatus();
|
||||
// Initial happens when
|
||||
// Initial happens when
|
||||
if (status==SFX_PAUSED) (*i)->resume();
|
||||
} // for i in m_all_sfx
|
||||
} // resumeAll
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns whether or not an openal error has occurred. If so, an error
|
||||
/** Returns whether or not an openal error has occurred. If so, an error
|
||||
* message is printed containing the given context.
|
||||
* \param context Context to specify in the error message.
|
||||
*/
|
||||
@ -445,7 +445,7 @@ void SFXManager::setMasterSFXVolume(float gain)
|
||||
(*i)->volume(m_master_gain);
|
||||
} // for i in m_all_sfx
|
||||
}
|
||||
|
||||
|
||||
// quick SFX
|
||||
{
|
||||
std::map<std::string, SFXBase*>::iterator i = m_quick_sounds.begin();
|
||||
@ -454,7 +454,7 @@ void SFXManager::setMasterSFXVolume(float gain)
|
||||
(*i).second->volume(m_master_gain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // setMasterSFXVolume
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -482,19 +482,19 @@ void SFXManager::positionListener(const Vec3 &position, const Vec3 &front)
|
||||
{
|
||||
#if HAVE_OGGVORBIS
|
||||
if (!UserConfigParams::m_sfx || !m_initialized) return;
|
||||
|
||||
|
||||
m_position = position;
|
||||
|
||||
|
||||
//forward vector
|
||||
m_listenerVec[0] = front.getX();
|
||||
m_listenerVec[0] = front.getX();
|
||||
m_listenerVec[1] = front.getY();
|
||||
m_listenerVec[2] = front.getZ();
|
||||
|
||||
m_listenerVec[2] = front.getZ();
|
||||
|
||||
//up vector
|
||||
m_listenerVec[3] = 0;
|
||||
m_listenerVec[3] = 0;
|
||||
m_listenerVec[4] = 0;
|
||||
m_listenerVec[5] = 1;
|
||||
|
||||
|
||||
alListener3f(AL_POSITION, position.getX(), position.getY(), position.getZ());
|
||||
alListenerfv(AL_ORIENTATION, m_listenerVec);
|
||||
#endif
|
||||
@ -511,7 +511,7 @@ SFXBase* SFXManager::quickSound(const std::string &sound_type)
|
||||
{
|
||||
if (!sfxAllowed()) return NULL;
|
||||
std::map<std::string, SFXBase*>::iterator sound = m_quick_sounds.find(sound_type);
|
||||
|
||||
|
||||
if (sound == m_quick_sounds.end())
|
||||
{
|
||||
// sound not yet in our local list of quick sounds
|
||||
|
@ -45,7 +45,7 @@ SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain, bool ownsBu
|
||||
m_loop = false;
|
||||
m_gain = -1.0f;
|
||||
m_owns_buffer = ownsBuffer;
|
||||
|
||||
|
||||
// Don't initialise anything else if the sfx manager was not correctly
|
||||
// initialised. First of all the initialisation will not work, and it
|
||||
// will not be used anyway.
|
||||
@ -63,7 +63,7 @@ SFXOpenAL::~SFXOpenAL()
|
||||
{
|
||||
alDeleteSources(1, &m_soundSource);
|
||||
}
|
||||
|
||||
|
||||
if (m_owns_buffer && m_soundBuffer != NULL)
|
||||
{
|
||||
m_soundBuffer->unload();
|
||||
@ -77,25 +77,25 @@ bool SFXOpenAL::init()
|
||||
{
|
||||
alGenSources(1, &m_soundSource );
|
||||
if (!SFXManager::checkError("generating a source")) return false;
|
||||
|
||||
|
||||
assert( alIsBuffer(m_soundBuffer->getBufferID()) );
|
||||
assert( alIsSource(m_soundSource) );
|
||||
|
||||
|
||||
//std::cout << "Setting a source with buffer " << m_soundBuffer << ", rolloff " << rolloff
|
||||
// << ", gain=" << m_defaultGain << ", positional=" << (positional ? "true" : "false") << std::endl;
|
||||
|
||||
|
||||
alSourcei (m_soundSource, AL_BUFFER, m_soundBuffer->getBufferID());
|
||||
|
||||
|
||||
if (!SFXManager::checkError("attaching the buffer to the source")) return false;
|
||||
|
||||
|
||||
alSource3f(m_soundSource, AL_POSITION, 0.0, 0.0, 0.0);
|
||||
alSource3f(m_soundSource, AL_VELOCITY, 0.0, 0.0, 0.0);
|
||||
alSource3f(m_soundSource, AL_DIRECTION, 0.0, 0.0, 0.0);
|
||||
|
||||
|
||||
alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, m_soundBuffer->getRolloff());
|
||||
|
||||
|
||||
alSourcef (m_soundSource, AL_MAX_DISTANCE, m_soundBuffer->getMaxDist());
|
||||
|
||||
|
||||
if (m_gain < 0.0f)
|
||||
{
|
||||
alSourcef (m_soundSource, AL_GAIN, m_defaultGain);
|
||||
@ -104,14 +104,14 @@ bool SFXOpenAL::init()
|
||||
{
|
||||
alSourcef (m_soundSource, AL_GAIN, m_gain);
|
||||
}
|
||||
|
||||
|
||||
if (m_positional) alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||
else alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
|
||||
|
||||
alSourcei(m_soundSource, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE);
|
||||
|
||||
|
||||
m_ok = SFXManager::checkError("setting up the source");
|
||||
|
||||
|
||||
return m_ok;
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ void SFXOpenAL::speed(float factor)
|
||||
void SFXOpenAL::volume(float gain)
|
||||
{
|
||||
m_gain = m_defaultGain * gain;
|
||||
|
||||
|
||||
if(!m_ok) return;
|
||||
|
||||
alSourcef(m_soundSource, AL_GAIN, m_defaultGain * gain);
|
||||
@ -156,7 +156,7 @@ void SFXOpenAL::volume(float gain)
|
||||
void SFXOpenAL::setLoop(bool status)
|
||||
{
|
||||
m_loop = status;
|
||||
|
||||
|
||||
if(!m_ok) return;
|
||||
|
||||
alSourcei(m_soundSource, AL_LOOPING, status ? AL_TRUE : AL_FALSE);
|
||||
@ -196,11 +196,11 @@ void SFXOpenAL::resume()
|
||||
{
|
||||
// lazily create OpenAL source when needed
|
||||
init();
|
||||
|
||||
|
||||
// creation of OpenAL source failed, giving up
|
||||
if (!m_ok) return;
|
||||
}
|
||||
|
||||
|
||||
alSourcePlay(m_soundSource);
|
||||
SFXManager::checkError("resuming");
|
||||
} // resume
|
||||
@ -215,7 +215,7 @@ void SFXOpenAL::play()
|
||||
{
|
||||
// lazily create OpenAL source when needed
|
||||
init();
|
||||
|
||||
|
||||
// creation of OpenAL source failed, giving up
|
||||
if (!m_ok) return;
|
||||
}
|
||||
@ -251,7 +251,7 @@ void SFXOpenAL::position(const Vec3 &position)
|
||||
|
||||
alSource3f(m_soundSource, AL_POSITION,
|
||||
(float)position.getX(), (float)position.getY(), (float)position.getZ());
|
||||
|
||||
|
||||
if (sfx_manager->getListenerPos().distance(position) > m_soundBuffer->getMaxDist())
|
||||
{
|
||||
alSourcef(m_soundSource, AL_GAIN, 0);
|
||||
@ -260,7 +260,7 @@ void SFXOpenAL::position(const Vec3 &position)
|
||||
{
|
||||
alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain));
|
||||
}
|
||||
|
||||
|
||||
SFXManager::checkError("positioning");
|
||||
} // position
|
||||
|
||||
|
@ -55,23 +55,23 @@ void Challenge::load(const XMLNode* challengesNode)
|
||||
|
||||
if (easy != NULL)
|
||||
{
|
||||
bool finished = false;
|
||||
bool finished = false;
|
||||
easy->get("solved", &finished);
|
||||
|
||||
|
||||
if (finished) m_state[0] = CH_SOLVED;
|
||||
}
|
||||
if (medium != NULL)
|
||||
{
|
||||
bool finished = false;
|
||||
bool finished = false;
|
||||
medium->get("solved", &finished);
|
||||
|
||||
|
||||
if (finished) m_state[1] = CH_SOLVED;
|
||||
}
|
||||
if (hard != NULL)
|
||||
{
|
||||
bool finished = false;
|
||||
bool finished = false;
|
||||
hard->get("solved", &finished);
|
||||
|
||||
|
||||
if (finished) m_state[2] = CH_SOLVED;
|
||||
}
|
||||
} // load
|
||||
|
@ -53,15 +53,15 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
m_energy[d] = -1;
|
||||
m_ai_superpower[d] = RaceManager::SUPERPOWER_NONE;
|
||||
}
|
||||
|
||||
|
||||
// we are using auto_ptr to make sure the XML node is released when leaving
|
||||
// the scope
|
||||
std::auto_ptr<XMLNode> root(new XMLNode( filename ));
|
||||
|
||||
|
||||
if(root.get() == NULL || root->getName()!="challenge")
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "Couldn't load challenge '" << filename
|
||||
msg << "Couldn't load challenge '" << filename
|
||||
<< "': no challenge node.";
|
||||
throw std::runtime_error(msg.str());
|
||||
}
|
||||
@ -69,25 +69,25 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
setId(StringUtils::removeExtension(StringUtils::getBasename(filename)));
|
||||
|
||||
root->get("version", &m_version);
|
||||
// No need to get the rest of the data if this challenge
|
||||
// No need to get the rest of the data if this challenge
|
||||
// is not supported anyway (id is needed for warning message)
|
||||
if(!unlock_manager->isSupportedVersion(*this))
|
||||
{
|
||||
fprintf(stderr, "[ChallengeData] WARNING: challenge <%s> is older "
|
||||
"or newer than this version of STK, will be ignored.\n",
|
||||
"or newer than this version of STK, will be ignored.\n",
|
||||
filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const XMLNode* mode_node = root->getNode("mode");
|
||||
if (mode_node == NULL)
|
||||
{
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
" has no <mode> node!");
|
||||
}
|
||||
|
||||
|
||||
std::string mode;
|
||||
mode_node->get("major", &mode);
|
||||
|
||||
@ -109,21 +109,21 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
m_minor = RaceManager::MINOR_MODE_FOLLOW_LEADER;
|
||||
else
|
||||
error("minor");
|
||||
|
||||
|
||||
const XMLNode* track_node = root->getNode("track");
|
||||
const XMLNode* gp_node = root->getNode("grandprix");
|
||||
|
||||
|
||||
if (m_mode == CM_SINGLE_RACE && track_node == NULL)
|
||||
{
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
" has no <track> node!");
|
||||
}
|
||||
if (m_mode == CM_GRAND_PRIX && gp_node == NULL)
|
||||
{
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
" has no <grandprix> node!");
|
||||
}
|
||||
|
||||
|
||||
if (track_node != NULL)
|
||||
{
|
||||
if (!track_node->get("id", &m_track_id ))
|
||||
@ -134,8 +134,8 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
{
|
||||
error("track");
|
||||
}
|
||||
|
||||
if (!track_node->get("laps", &m_num_laps) &&
|
||||
|
||||
if (!track_node->get("laps", &m_num_laps) &&
|
||||
m_minor != RaceManager::MINOR_MODE_FOLLOW_LEADER)
|
||||
{
|
||||
error("laps");
|
||||
@ -148,11 +148,11 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
error("grandprix");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const XMLNode* requirements_node = root->getNode("requirements");
|
||||
if (requirements_node == NULL)
|
||||
{
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
throw std::runtime_error("Challenge file " + filename +
|
||||
" has no <requirements> node!");
|
||||
}
|
||||
requirements_node->get("trophies", &m_num_trophies);
|
||||
@ -168,20 +168,20 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
{
|
||||
error("<easy> or <medium> or <hard>");
|
||||
}
|
||||
|
||||
|
||||
for (int d=0; d<=RaceManager::DIFFICULTY_HARD; d++)
|
||||
{
|
||||
const XMLNode* karts_node = difficulties[d]->getNode("karts");
|
||||
if (karts_node == NULL) error("<karts .../>");
|
||||
|
||||
|
||||
int num_karts = -1;
|
||||
if (!karts_node->get("number", &num_karts)) error("karts");
|
||||
m_num_karts[d] = num_karts;
|
||||
|
||||
|
||||
std::string ai_kart_ident;
|
||||
if (karts_node->get("aiIdent", &ai_kart_ident))
|
||||
m_ai_kart_ident[d] = ai_kart_ident;
|
||||
|
||||
|
||||
std::string superPower;
|
||||
if (karts_node->get("superPower", &superPower))
|
||||
{
|
||||
@ -191,13 +191,13 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
fprintf(stderr,
|
||||
"[ChallengeData] WARNING: Unknown A superpower '%s'\n",
|
||||
superPower.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
const XMLNode* requirements_node =
|
||||
|
||||
const XMLNode* requirements_node =
|
||||
difficulties[d]->getNode("requirements");
|
||||
if (requirements_node == NULL) error("<requirements .../>");
|
||||
|
||||
@ -212,10 +212,10 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
{
|
||||
m_position[d] = position;
|
||||
}
|
||||
|
||||
|
||||
int time = -1;
|
||||
if (requirements_node->get("time", &time)) m_time[d] = (float)time;
|
||||
|
||||
|
||||
if (m_time[d] < 0 && m_position[d] < 0) error("position/time");
|
||||
|
||||
// This is optional
|
||||
@ -242,20 +242,20 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "[ChallengeData] unknown unlock entry.\n");
|
||||
fprintf(stderr,
|
||||
fprintf(stderr,
|
||||
"Must be one of kart, track, gp, mode, difficulty.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
core::stringw description;
|
||||
if (track_node != NULL)
|
||||
{
|
||||
//I18N: number of laps to race in a challenge
|
||||
description += _("Laps : %i", m_num_laps);
|
||||
description += core::stringw(L"\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_challenge_description = description;
|
||||
} // ChallengeData
|
||||
|
||||
@ -263,17 +263,17 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
void ChallengeData::error(const char *id) const
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "Undefined or incorrect value for '" << id
|
||||
msg << "Undefined or incorrect value for '" << id
|
||||
<< "' in challenge file '" << m_filename << "'.";
|
||||
|
||||
|
||||
printf("ChallengeData : %s\n", msg.str().c_str());
|
||||
|
||||
|
||||
throw std::runtime_error(msg.str());
|
||||
} // error
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Checks if this challenge is valid, i.e. contains a valid track or a valid
|
||||
* GP. If incorrect data are found, STK is aborted with an error message.
|
||||
* GP. If incorrect data are found, STK is aborted with an error message.
|
||||
* (otherwise STK aborts when trying to do this challenge, which is worse).
|
||||
*/
|
||||
void ChallengeData::check() const
|
||||
@ -292,7 +292,7 @@ void ChallengeData::check() const
|
||||
else if(m_mode==CM_GRAND_PRIX)
|
||||
{
|
||||
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(m_gp_id);
|
||||
|
||||
|
||||
if (gp == NULL)
|
||||
{
|
||||
error("gp");
|
||||
@ -318,14 +318,14 @@ void ChallengeData::setUnlocks(const std::string &id, RewardType reward)
|
||||
{
|
||||
case UNLOCK_TRACK: assert (false);
|
||||
break;
|
||||
|
||||
|
||||
case UNLOCK_GP: addUnlockGPReward(id);
|
||||
break;
|
||||
|
||||
|
||||
case UNLOCK_MODE: {
|
||||
const RaceManager::MinorRaceModeType mode =
|
||||
RaceManager::getModeIDFromInternalName(id);
|
||||
addUnlockModeReward(id,
|
||||
addUnlockModeReward(id,
|
||||
RaceManager::getNameOf(mode));
|
||||
break;
|
||||
}
|
||||
@ -337,7 +337,7 @@ void ChallengeData::setUnlocks(const std::string &id, RewardType reward)
|
||||
break;
|
||||
}
|
||||
case UNLOCK_KART: {
|
||||
const KartProperties* prop =
|
||||
const KartProperties* prop =
|
||||
kart_properties_manager->getKart(id);
|
||||
if (prop == NULL)
|
||||
{
|
||||
@ -390,7 +390,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
|
||||
race_manager->setNumKarts(m_num_karts[d]);
|
||||
race_manager->setNumLocalPlayers(1);
|
||||
}
|
||||
|
||||
|
||||
if (m_ai_kart_ident[d] != "")
|
||||
{
|
||||
race_manager->setAIKartOverride(m_ai_kart_ident[d]);
|
||||
@ -406,7 +406,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
|
||||
*/
|
||||
bool ChallengeData::isChallengeFulfilled() const
|
||||
{
|
||||
// GP's use the grandPrixFinished() function,
|
||||
// GP's use the grandPrixFinished() function,
|
||||
// so they can't be fulfilled here.
|
||||
if(m_mode==CM_GRAND_PRIX) return false;
|
||||
|
||||
@ -414,9 +414,9 @@ bool ChallengeData::isChallengeFulfilled() const
|
||||
// ------------
|
||||
World *world = World::getWorld();
|
||||
std::string track_name = world->getTrack()->getIdent();
|
||||
|
||||
|
||||
int d = race_manager->getDifficulty();
|
||||
|
||||
|
||||
AbstractKart* kart = world->getPlayerKart(0);
|
||||
|
||||
if (kart->isEliminated() ) return false;
|
||||
@ -424,35 +424,35 @@ bool ChallengeData::isChallengeFulfilled() const
|
||||
if ((int)world->getNumKarts() < m_num_karts[d] ) return false;
|
||||
if (m_energy[d] > 0 && kart->getEnergy() < m_energy[d] ) return false;
|
||||
if (m_position[d] > 0 && kart->getPosition() > m_position[d]) return false;
|
||||
|
||||
|
||||
// Follow the leader
|
||||
// -----------------
|
||||
if(m_minor==RaceManager::MINOR_MODE_FOLLOW_LEADER)
|
||||
{
|
||||
// All possible conditions were already checked, so:
|
||||
// All possible conditions were already checked, so:
|
||||
// must have been successful
|
||||
return true;
|
||||
}
|
||||
// Quickrace / Timetrial
|
||||
// ---------------------
|
||||
// FIXME - encapsulate this better, each race mode needs to be able
|
||||
// FIXME - encapsulate this better, each race mode needs to be able
|
||||
// to specify its own challenges and deal with them
|
||||
LinearWorld* lworld = dynamic_cast<LinearWorld*>(world);
|
||||
if(lworld != NULL)
|
||||
{
|
||||
// wrong number of laps
|
||||
if(lworld->getLapForKart( kart->getWorldKartId() ) != m_num_laps)
|
||||
if(lworld->getLapForKart( kart->getWorldKartId() ) != m_num_laps)
|
||||
return false;
|
||||
}
|
||||
// too slow
|
||||
if (m_time[d] > 0.0f && kart->getFinishTime() > m_time[d]) return false;
|
||||
|
||||
|
||||
if (m_ai_superpower[d] != RaceManager::SUPERPOWER_NONE &&
|
||||
race_manager->getAISuperPower() != m_ai_superpower[d])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
} // isChallengeFulfilled
|
||||
|
||||
@ -462,7 +462,7 @@ bool ChallengeData::isChallengeFulfilled() const
|
||||
bool ChallengeData::isGPFulfilled() const
|
||||
{
|
||||
int d = race_manager->getDifficulty();
|
||||
|
||||
|
||||
// Note that we have to call race_manager->getNumKarts, since there
|
||||
// is no world objects to query at this stage.
|
||||
if (race_manager->getMajorMode() != RaceManager::MAJOR_MODE_GRAND_PRIX ||
|
||||
@ -473,14 +473,14 @@ bool ChallengeData::isGPFulfilled() const
|
||||
|
||||
// check if the player came first.
|
||||
const int rank = race_manager->getLocalPlayerGPRank(0);
|
||||
|
||||
|
||||
if (rank != 0) return false;
|
||||
|
||||
return true;
|
||||
} // isGPFulfilled
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
const irr::core::stringw
|
||||
const irr::core::stringw
|
||||
ChallengeData::UnlockableFeature::getUnlockedMessage() const
|
||||
{
|
||||
switch (m_type)
|
||||
@ -488,11 +488,11 @@ const irr::core::stringw
|
||||
case UNLOCK_TRACK:
|
||||
{ // {} avoids compiler warning
|
||||
const Track* track = track_manager->getTrack(m_name);
|
||||
|
||||
|
||||
// shouldn't happen but let's avoid crashes as much as possible...
|
||||
if (track == NULL) return irr::core::stringw( L"????" );
|
||||
|
||||
return _("New track '%s' now available",
|
||||
|
||||
return _("New track '%s' now available",
|
||||
core::stringw(track->getName()));
|
||||
break;
|
||||
}
|
||||
@ -503,10 +503,10 @@ const irr::core::stringw
|
||||
case UNLOCK_GP:
|
||||
{
|
||||
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(m_name);
|
||||
|
||||
|
||||
// shouldn't happen but let's avoid crashes as much as possible...
|
||||
if (gp == NULL) return irr::core::stringw( L"????" );
|
||||
|
||||
|
||||
const irr::core::stringw& gp_user_name = gp->getName();
|
||||
return _("New Grand Prix '%s' now available", gp_user_name);
|
||||
}
|
||||
@ -516,13 +516,13 @@ const irr::core::stringw
|
||||
}
|
||||
case UNLOCK_KART:
|
||||
{
|
||||
const KartProperties* kp =
|
||||
const KartProperties* kp =
|
||||
kart_properties_manager->getKart(m_name);
|
||||
|
||||
|
||||
// shouldn't happen but let's avoid crashes as much as possible...
|
||||
if (kp == NULL) return irr::core::stringw( L"????" );
|
||||
|
||||
return _("New kart '%s' now available",
|
||||
|
||||
return _("New kart '%s' now available",
|
||||
core::stringw(kp->getName()));
|
||||
}
|
||||
default:
|
||||
@ -533,19 +533,19 @@ const irr::core::stringw
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets that the given track will be unlocked if this challenge
|
||||
* is unlocked.
|
||||
* is unlocked.
|
||||
* \param track_name Name of the track to unlock.
|
||||
*/
|
||||
void ChallengeData::addUnlockTrackReward(const std::string &track_name)
|
||||
{
|
||||
|
||||
|
||||
if (track_manager->getTrack(track_name) == NULL)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
StringUtils::insertValues("Challenge refers to unknown track <%s>",
|
||||
track_name.c_str()));
|
||||
}
|
||||
|
||||
|
||||
UnlockableFeature feature;
|
||||
feature.m_name = track_name;
|
||||
feature.m_type = UNLOCK_TRACK;
|
||||
@ -556,7 +556,7 @@ void ChallengeData::addUnlockTrackReward(const std::string &track_name)
|
||||
|
||||
void ChallengeData::addUnlockModeReward(const std::string &internal_mode_name,
|
||||
const irr::core::stringw &user_mode_name)
|
||||
{
|
||||
{
|
||||
UnlockableFeature feature;
|
||||
feature.m_name = internal_mode_name;
|
||||
feature.m_type = UNLOCK_MODE;
|
||||
@ -571,21 +571,21 @@ void ChallengeData::addUnlockGPReward(const std::string &gp_name)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
StringUtils::insertValues(
|
||||
"Challenge refers to unknown Grand Prix <%s>",
|
||||
"Challenge refers to unknown Grand Prix <%s>",
|
||||
gp_name.c_str()));
|
||||
}
|
||||
|
||||
|
||||
UnlockableFeature feature;
|
||||
|
||||
|
||||
feature.m_name = gp_name.c_str();
|
||||
|
||||
|
||||
feature.m_type = UNLOCK_GP;
|
||||
m_feature.push_back(feature);
|
||||
} // addUnlockGPReward
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ChallengeData::addUnlockDifficultyReward(const std::string &internal_name,
|
||||
void ChallengeData::addUnlockDifficultyReward(const std::string &internal_name,
|
||||
const irr::core::stringw &user_name)
|
||||
{
|
||||
UnlockableFeature feature;
|
||||
@ -596,7 +596,7 @@ void ChallengeData::addUnlockDifficultyReward(const std::string &internal_name,
|
||||
} // addUnlockDifficultyReward
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ChallengeData::addUnlockKartReward(const std::string &internal_name,
|
||||
void ChallengeData::addUnlockKartReward(const std::string &internal_name,
|
||||
const irr::core::stringw &user_name)
|
||||
{
|
||||
try
|
||||
@ -610,7 +610,7 @@ void ChallengeData::addUnlockKartReward(const std::string &internal_name,
|
||||
StringUtils::insertValues("Challenge refers to unknown kart <%s>",
|
||||
internal_name.c_str()));
|
||||
}
|
||||
|
||||
|
||||
UnlockableFeature feature;
|
||||
feature.m_name = internal_name;
|
||||
feature.m_type = UNLOCK_KART;
|
||||
|
@ -46,37 +46,37 @@ void GameSlot::computeActive()
|
||||
m_easy_challenges = 0;
|
||||
m_medium_challenges = 0;
|
||||
m_hard_challenges = 0;
|
||||
|
||||
|
||||
m_locked_features.clear(); // start afresh
|
||||
|
||||
|
||||
std::map<std::string, Challenge*>::const_iterator i;
|
||||
for(i = m_challenges_state.begin();
|
||||
for(i = m_challenges_state.begin();
|
||||
i != m_challenges_state.end(); i++)
|
||||
{
|
||||
// Changed challenge
|
||||
// -----------------
|
||||
if((i->second)->isSolvedAtAnyDifficulty())
|
||||
if((i->second)->isSolvedAtAnyDifficulty())
|
||||
{
|
||||
// The constructor calls computeActive, which actually locks
|
||||
// The constructor calls computeActive, which actually locks
|
||||
// all features, so unlock the solved ones (and don't try to
|
||||
// save the state, since we are currently reading it)
|
||||
|
||||
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_EASY))
|
||||
{
|
||||
unlockFeature(i->second, RaceManager::DIFFICULTY_EASY,
|
||||
unlockFeature(i->second, RaceManager::DIFFICULTY_EASY,
|
||||
/*save*/ false);
|
||||
}
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM))
|
||||
{
|
||||
unlockFeature(i->second, RaceManager::DIFFICULTY_MEDIUM,
|
||||
unlockFeature(i->second, RaceManager::DIFFICULTY_MEDIUM,
|
||||
/*save*/ false);
|
||||
}
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_HARD))
|
||||
{
|
||||
unlockFeature(i->second, RaceManager::DIFFICULTY_HARD,
|
||||
unlockFeature(i->second, RaceManager::DIFFICULTY_HARD,
|
||||
/*save*/ false);
|
||||
}
|
||||
|
||||
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_HARD))
|
||||
{
|
||||
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD];
|
||||
@ -99,7 +99,7 @@ void GameSlot::computeActive()
|
||||
// --------------------------
|
||||
lockFeature(i->second);
|
||||
}
|
||||
|
||||
|
||||
if (i->second->isSolved(RaceManager::DIFFICULTY_HARD))
|
||||
{
|
||||
// challenge beaten at hardest, nothing more to do here
|
||||
@ -121,7 +121,7 @@ void GameSlot::computeActive()
|
||||
i->second->setActive(RaceManager::DIFFICULTY_EASY);
|
||||
}
|
||||
} // for i
|
||||
|
||||
|
||||
// now we have the number of points. Actually lock the tracks
|
||||
for (i = m_challenges_state.begin(); i != m_challenges_state.end(); i++)
|
||||
{
|
||||
@ -138,19 +138,19 @@ void GameSlot::computeActive()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
clearUnlocked();
|
||||
|
||||
|
||||
|
||||
|
||||
} // computeActive
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GameSlot::lockFeature(Challenge *challenge)
|
||||
{
|
||||
const std::vector<ChallengeData::UnlockableFeature>& features =
|
||||
const std::vector<ChallengeData::UnlockableFeature>& features =
|
||||
challenge->getData()->getFeatures();
|
||||
|
||||
|
||||
const unsigned int amount = (unsigned int)features.size();
|
||||
for (unsigned int n=0; n<amount; n++)
|
||||
{
|
||||
@ -164,7 +164,7 @@ void GameSlot::lockFeature(Challenge *challenge)
|
||||
* \param d Difficulty at which the challenge was solved.
|
||||
* \param do_save If true update the challenge file on disk.
|
||||
*/
|
||||
void GameSlot::unlockFeature(Challenge* c, RaceManager::Difficulty d,
|
||||
void GameSlot::unlockFeature(Challenge* c, RaceManager::Difficulty d,
|
||||
bool do_save)
|
||||
{
|
||||
const unsigned int amount=(unsigned int)c->getData()->getFeatures().size();
|
||||
@ -180,11 +180,11 @@ void GameSlot::unlockFeature(Challenge* c, RaceManager::Difficulty d,
|
||||
}
|
||||
m_locked_features.erase(p);
|
||||
}
|
||||
|
||||
|
||||
// Add to list of recently unlocked features
|
||||
m_unlocked_features.push_back(c->getData());
|
||||
c->setSolved(d); // reset isActive flag
|
||||
|
||||
|
||||
// Save the new unlock information
|
||||
if (do_save) unlock_manager->save();
|
||||
} // unlockFeature
|
||||
@ -195,7 +195,7 @@ void GameSlot::unlockFeature(Challenge* c, RaceManager::Difficulty d,
|
||||
*/
|
||||
void GameSlot::setCurrentChallenge(const std::string &challenge_id)
|
||||
{
|
||||
m_current_challenge = challenge_id=="" ? NULL
|
||||
m_current_challenge = challenge_id=="" ? NULL
|
||||
: getChallenge(challenge_id);
|
||||
} // setCurrentChallenge
|
||||
|
||||
@ -206,13 +206,13 @@ void GameSlot::setCurrentChallenge(const std::string &challenge_id)
|
||||
void GameSlot::raceFinished()
|
||||
{
|
||||
if(m_current_challenge &&
|
||||
m_current_challenge->isActive(race_manager->getDifficulty()) &&
|
||||
m_current_challenge->isActive(race_manager->getDifficulty()) &&
|
||||
m_current_challenge->getData()->isChallengeFulfilled() )
|
||||
{
|
||||
// cast const away so that the challenge can be set to fulfilled.
|
||||
// The 'clean' implementation would involve searching the challenge
|
||||
// in m_challenges_state, which is a bit of an overkill
|
||||
unlockFeature(const_cast<Challenge*>(m_current_challenge),
|
||||
unlockFeature(const_cast<Challenge*>(m_current_challenge),
|
||||
race_manager->getDifficulty());
|
||||
} // if isActive && challenge solved
|
||||
} // raceFinished
|
||||
@ -224,13 +224,13 @@ void GameSlot::raceFinished()
|
||||
void GameSlot::grandPrixFinished()
|
||||
{
|
||||
if(m_current_challenge &&
|
||||
m_current_challenge->isActive(race_manager->getDifficulty()) &&
|
||||
m_current_challenge->isActive(race_manager->getDifficulty()) &&
|
||||
m_current_challenge->getData()->isGPFulfilled() )
|
||||
{
|
||||
unlockFeature(const_cast<Challenge*>(m_current_challenge),
|
||||
unlockFeature(const_cast<Challenge*>(m_current_challenge),
|
||||
race_manager->getDifficulty());
|
||||
} // if isActive && challenge solved
|
||||
|
||||
|
||||
race_manager->setCoinTarget(0);
|
||||
} // grandPrixFinished
|
||||
|
||||
@ -238,12 +238,12 @@ void GameSlot::grandPrixFinished()
|
||||
|
||||
void GameSlot::save(std::ofstream& out, const std::string& name)
|
||||
{
|
||||
out << " <gameslot playerID=\"" << m_player_unique_id.c_str()
|
||||
<< "\" kart=\"" << m_kart_ident.c_str()
|
||||
out << " <gameslot playerID=\"" << m_player_unique_id.c_str()
|
||||
<< "\" kart=\"" << m_kart_ident.c_str()
|
||||
<< "\" firstTime=\"" << (m_first_time ? "true" : "false")
|
||||
<< "\"> <!-- " << name.c_str() << " -->\n";
|
||||
std::map<std::string, Challenge*>::const_iterator i;
|
||||
for(i = m_challenges_state.begin();
|
||||
for(i = m_challenges_state.begin();
|
||||
i != m_challenges_state.end(); i++)
|
||||
{
|
||||
if (i->second != NULL)
|
||||
|
@ -48,9 +48,9 @@ UnlockManager::UnlockManager()
|
||||
unlock_manager = this;
|
||||
|
||||
m_current_game_slot = "";
|
||||
|
||||
|
||||
m_locked_sound = sfx_manager->createSoundSource("locked");
|
||||
|
||||
|
||||
|
||||
// Read challenges from .../data/challenges
|
||||
// ----------------------------------------
|
||||
@ -59,7 +59,7 @@ UnlockManager::UnlockManager()
|
||||
for(std::set<std::string>::iterator i = result.begin();
|
||||
i != result.end() ; i++)
|
||||
{
|
||||
if (StringUtils::hasSuffix(*i, ".challenge"))
|
||||
if (StringUtils::hasSuffix(*i, ".challenge"))
|
||||
addChallenge(file_manager->getDataFile("challenges/"+*i));
|
||||
} // for i
|
||||
|
||||
@ -85,20 +85,20 @@ UnlockManager::UnlockManager()
|
||||
UnlockManager::~UnlockManager()
|
||||
{
|
||||
save();
|
||||
|
||||
for(AllChallengesType::iterator i =m_all_challenges.begin();
|
||||
|
||||
for(AllChallengesType::iterator i =m_all_challenges.begin();
|
||||
i!=m_all_challenges.end(); i++)
|
||||
{
|
||||
delete i->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::map<std::string, GameSlot*>::iterator it;
|
||||
for (it = m_game_slots.begin(); it != m_game_slots.end(); it++)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
|
||||
// sfx_manager is destroyed before UnlockManager is, so SFX will be already deleted
|
||||
// sfx_manager->deleteSFX(m_locked_sound);
|
||||
} // ~UnlockManager
|
||||
@ -112,14 +112,14 @@ void UnlockManager::readAllChallengesInDirs(const std::vector<std::string>* all_
|
||||
{
|
||||
std::set<std::string> all_files;
|
||||
file_manager->listFiles(all_files, *dir, /*is_full_path*/ true);
|
||||
|
||||
for(std::set<std::string>::iterator file = all_files.begin();
|
||||
|
||||
for(std::set<std::string>::iterator file = all_files.begin();
|
||||
file != all_files.end(); file++)
|
||||
{
|
||||
if (!StringUtils::hasSuffix(*file,".challenge")) continue;
|
||||
|
||||
|
||||
std::string filename = *dir + "/" + *file;
|
||||
|
||||
|
||||
FILE* f = fopen(filename.c_str(), "r");
|
||||
if (f)
|
||||
{
|
||||
@ -139,13 +139,13 @@ void UnlockManager::readAllChallengesInDirs(const std::vector<std::string>* all_
|
||||
}
|
||||
addOrFreeChallenge(new_challenge);
|
||||
} // if file
|
||||
|
||||
|
||||
} // for file in files
|
||||
} // for dir in all_track_dirs
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** If a challenge is supported by this binary (i.e. has an appropriate
|
||||
/** If a challenge is supported by this binary (i.e. has an appropriate
|
||||
* challenge version number), add this challenge to the set of all challenges,
|
||||
* otherwise free the memory for this challenge.
|
||||
* \param c The challenge that is either stored or freed.
|
||||
@ -184,7 +184,7 @@ void UnlockManager::addChallenge(const std::string& filename)
|
||||
return;
|
||||
}
|
||||
addOrFreeChallenge(new_challenge);
|
||||
|
||||
|
||||
} // addChallenge
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -212,11 +212,11 @@ void UnlockManager::load()
|
||||
filename.c_str());
|
||||
createSlotsIfNeeded();
|
||||
save();
|
||||
|
||||
|
||||
if (root) delete root;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::vector<XMLNode*> xml_game_slots;
|
||||
root->getNodes("gameslot", xml_game_slots);
|
||||
for (unsigned int n=0; n<xml_game_slots.size(); n++)
|
||||
@ -228,34 +228,34 @@ void UnlockManager::load()
|
||||
"a player ID attached. Discarding it.");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
GameSlot* slot = new GameSlot(player_id);
|
||||
|
||||
|
||||
std::string kart_id;
|
||||
xml_game_slots[n]->get("kart", &kart_id);
|
||||
slot->setKartIdent(kart_id);
|
||||
|
||||
|
||||
m_game_slots[player_id] = slot;
|
||||
|
||||
|
||||
bool first_time = true;
|
||||
xml_game_slots[n]->get("firstTime", &first_time);
|
||||
slot->setFirstTime(first_time);
|
||||
|
||||
for(AllChallengesType::iterator i = m_all_challenges.begin();
|
||||
|
||||
for(AllChallengesType::iterator i = m_all_challenges.begin();
|
||||
i!=m_all_challenges.end(); i++)
|
||||
{
|
||||
ChallengeData* curr = i->second;
|
||||
Challenge* state = new Challenge(curr);
|
||||
|
||||
|
||||
slot->m_challenges_state[curr->getId()] = state;
|
||||
state->load(xml_game_slots[n]);
|
||||
}
|
||||
slot->computeActive();
|
||||
}
|
||||
|
||||
|
||||
bool something_changed = createSlotsIfNeeded();
|
||||
if (something_changed) save();
|
||||
|
||||
|
||||
delete root;
|
||||
} // load
|
||||
|
||||
@ -264,12 +264,12 @@ void UnlockManager::load()
|
||||
void UnlockManager::save()
|
||||
{
|
||||
std::string filename = file_manager->getChallengeFile("challenges.xml");
|
||||
|
||||
|
||||
std::ofstream challenge_file(filename.c_str(), std::ios::out);
|
||||
|
||||
if (!challenge_file.is_open())
|
||||
{
|
||||
Log::warn("unlock_manager",
|
||||
Log::warn("unlock_manager",
|
||||
"Failed to open '%s' for writing, challenges won't be saved\n",
|
||||
filename.c_str());
|
||||
return;
|
||||
@ -277,7 +277,7 @@ void UnlockManager::save()
|
||||
|
||||
challenge_file << "<?xml version=\"1.0\"?>\n";
|
||||
challenge_file << "<challenges>\n";
|
||||
|
||||
|
||||
std::map<std::string, GameSlot*>::iterator it;
|
||||
for (it = m_game_slots.begin(); it != m_game_slots.end(); it++)
|
||||
{
|
||||
@ -290,10 +290,10 @@ void UnlockManager::save()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
it->second->save(challenge_file, name);
|
||||
}
|
||||
|
||||
|
||||
challenge_file << "</challenges>\n\n";
|
||||
challenge_file.close();
|
||||
} // save
|
||||
@ -305,13 +305,13 @@ void UnlockManager::save()
|
||||
bool UnlockManager::createSlotsIfNeeded()
|
||||
{
|
||||
bool something_changed = false;
|
||||
|
||||
|
||||
// make sure all players have at least one game slot associated
|
||||
PtrVector<PlayerProfile>& players = UserConfigParams::m_all_players;
|
||||
for (int n=0; n<players.size(); n++)
|
||||
{
|
||||
bool exists = false;
|
||||
|
||||
|
||||
std::map<std::string, GameSlot*>::iterator it;
|
||||
for (it = m_game_slots.begin(); it != m_game_slots.end(); it++)
|
||||
{
|
||||
@ -322,24 +322,24 @@ bool UnlockManager::createSlotsIfNeeded()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
GameSlot* slot = new GameSlot(players[n].getUniqueID());
|
||||
for(AllChallengesType::iterator i = m_all_challenges.begin();
|
||||
for(AllChallengesType::iterator i = m_all_challenges.begin();
|
||||
i!=m_all_challenges.end(); i++)
|
||||
{
|
||||
ChallengeData* cd = i->second;
|
||||
slot->m_challenges_state[cd->getId()] = new Challenge(cd);
|
||||
}
|
||||
slot->computeActive();
|
||||
|
||||
|
||||
m_game_slots[players[n].getUniqueID()] = slot;
|
||||
|
||||
|
||||
something_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return something_changed;
|
||||
} // UnlockManager::createSlotsIfNeeded
|
||||
|
||||
@ -431,7 +431,7 @@ void UnlockManager::findWhatWasUnlocked(int points_before, int points_now,
|
||||
it != m_all_challenges.end(); it++)
|
||||
{
|
||||
ChallengeData* c = it->second;
|
||||
if (c->getNumTrophies() > points_before &&
|
||||
if (c->getNumTrophies() > points_before &&
|
||||
c->getNumTrophies() <= points_now )
|
||||
{
|
||||
if (c->getTrackId() != "")
|
||||
|
@ -41,27 +41,27 @@ irr::core::stringw DeviceConfig::getBindingAsString (const PlayerAction action)
|
||||
irr::core::stringw DeviceConfig::getMappingIdString (const PlayerAction action) const
|
||||
{
|
||||
irr::core::stringw returnString = "";
|
||||
|
||||
|
||||
if ((action < PA_COUNT) && (action >= 0))
|
||||
{
|
||||
const Input::InputType type = m_bindings[action].getType();
|
||||
const int id = m_bindings[action].getId();
|
||||
const Input::AxisDirection dir = m_bindings[action].getDirection();
|
||||
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case Input::IT_KEYBOARD:
|
||||
returnString += "keyb_";
|
||||
returnString += id;
|
||||
break;
|
||||
|
||||
|
||||
case Input::IT_STICKMOTION:
|
||||
returnString += "stkmo_";
|
||||
returnString += id;
|
||||
returnString += "$";
|
||||
returnString += dir;
|
||||
break;
|
||||
|
||||
|
||||
case Input::IT_STICKBUTTON:
|
||||
returnString += "stkbt_";
|
||||
returnString += id;
|
||||
@ -73,12 +73,12 @@ irr::core::stringw DeviceConfig::getMappingIdString (const PlayerAction action)
|
||||
returnString += "$";
|
||||
returnString += dir;
|
||||
break;
|
||||
|
||||
|
||||
case Input::IT_MOUSEBUTTON:
|
||||
returnString += "mousebtn_";
|
||||
returnString += id;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
returnString += type;
|
||||
@ -88,7 +88,7 @@ irr::core::stringw DeviceConfig::getMappingIdString (const PlayerAction action)
|
||||
returnString += dir;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ irr::core::stringw DeviceConfig::toString ()
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void DeviceConfig::setBinding ( const PlayerAction action,
|
||||
void DeviceConfig::setBinding ( const PlayerAction action,
|
||||
const Input::InputType type,
|
||||
const int id,
|
||||
Input::AxisDirection direction,
|
||||
@ -151,7 +151,7 @@ bool DeviceConfig::doGetAction(Input::InputType type,
|
||||
PlayerAction* action /* out */ )
|
||||
{
|
||||
if (!m_enabled) return false;
|
||||
|
||||
|
||||
bool success = false;
|
||||
int n;
|
||||
|
||||
@ -162,9 +162,9 @@ bool DeviceConfig::doGetAction(Input::InputType type,
|
||||
|
||||
if (type == Input::IT_STICKMOTION)
|
||||
{
|
||||
if ( ((m_bindings[n].getDirection() == Input::AD_POSITIVE)
|
||||
if ( ((m_bindings[n].getDirection() == Input::AD_POSITIVE)
|
||||
&& (value > 0)) ||
|
||||
((m_bindings[n].getDirection() == Input::AD_NEGATIVE)
|
||||
((m_bindings[n].getDirection() == Input::AD_NEGATIVE)
|
||||
&& (value < 0)) )
|
||||
{
|
||||
success = true;
|
||||
@ -176,7 +176,7 @@ bool DeviceConfig::doGetAction(Input::InputType type,
|
||||
success = true;
|
||||
*action = (PlayerAction)n;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end for n
|
||||
|
||||
return success;
|
||||
@ -222,7 +222,7 @@ bool DeviceConfig::deserializeAction(irr::io::IrrXMLReader* xml)
|
||||
}
|
||||
if(binding_id==-1)
|
||||
{
|
||||
printf("WARNING: DeviceConfig::deserializeAction : action '%s' is unknown\n",
|
||||
printf("WARNING: DeviceConfig::deserializeAction : action '%s' is unknown\n",
|
||||
name_string);
|
||||
return false;
|
||||
}
|
||||
@ -257,7 +257,7 @@ void KeyboardConfig::setDefaultBinds()
|
||||
setBinding(PA_FIRE, Input::IT_KEYBOARD, KEY_SPACE);
|
||||
setBinding(PA_LOOK_BACK, Input::IT_KEYBOARD, KEY_KEY_B);
|
||||
setBinding(PA_PAUSE_RACE, Input::IT_KEYBOARD, KEY_ESCAPE);
|
||||
|
||||
|
||||
setBinding(PA_MENU_UP, Input::IT_KEYBOARD, KEY_UP);
|
||||
setBinding(PA_MENU_DOWN, Input::IT_KEYBOARD, KEY_DOWN);
|
||||
setBinding(PA_MENU_LEFT, Input::IT_KEYBOARD, KEY_LEFT);
|
||||
@ -312,7 +312,7 @@ void GamepadConfig::setDefaultBinds ()
|
||||
|
||||
GamepadConfig::GamepadConfig ( const std::string &name,
|
||||
const int axis_count,
|
||||
const int button_count )
|
||||
const int button_count )
|
||||
: DeviceConfig( DEVICE_CONFIG_TYPE_GAMEPAD )
|
||||
{
|
||||
m_name = name;
|
||||
@ -331,11 +331,11 @@ GamepadConfig::GamepadConfig(irr::io::IrrXMLReader* xml) : DeviceConfig( DEVICE_
|
||||
{
|
||||
printf("ERROR: Unnamed joystick in config file\n");
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
m_name = name_string;
|
||||
}
|
||||
|
||||
|
||||
const char* enabled_string = xml->getAttributeValue("enabled");
|
||||
if (enabled_string != NULL)
|
||||
{
|
||||
@ -345,7 +345,7 @@ GamepadConfig::GamepadConfig(irr::io::IrrXMLReader* xml) : DeviceConfig( DEVICE_
|
||||
{
|
||||
m_enabled = true;
|
||||
}
|
||||
|
||||
|
||||
m_plugged = 0;
|
||||
setDefaultBinds();
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ PlayerProfile::PlayerProfile(const core::stringw& name) :
|
||||
m_magic_number = 0xABCD1234;
|
||||
#endif
|
||||
int64_t unique_id = generateUniqueId(core::stringc(name.c_str()).c_str());
|
||||
|
||||
|
||||
std::ostringstream tostring;
|
||||
tostring << std::hex << unique_id;
|
||||
m_unique_id = tostring.str();
|
||||
|
@ -44,7 +44,7 @@ SavedGrandPrix::SavedGPKart::SavedGPKart(GroupUserConfigParam * group,
|
||||
} // SavedGPKart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SavedGrandPrix::SavedGPKart::SavedGPKart(GroupUserConfigParam * group,
|
||||
SavedGrandPrix::SavedGPKart::SavedGPKart(GroupUserConfigParam * group,
|
||||
const XMLNode* node)
|
||||
: m_group("Kart", group, "Saved state of a kart"),
|
||||
m_ident("-","ident", &m_group),
|
||||
@ -156,7 +156,7 @@ void SavedGrandPrix::loadKarts(std::vector<RaceManager::KartStatus> & kart_list)
|
||||
else
|
||||
{
|
||||
//Get correct player
|
||||
for(unsigned int x = kart_list.size()-m_player_karts;
|
||||
for(unsigned int x = kart_list.size()-m_player_karts;
|
||||
x < kart_list.size(); x++)
|
||||
{
|
||||
if(kart_list[x].m_local_player_id == m_karts[i].m_local_player_id)
|
||||
|
@ -104,7 +104,7 @@ void STKConfig::load(const std::string &filename)
|
||||
Log::fatal("StkConfig", "No follow leader interval(s) defined in stk_config");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
if(m_switch_items.size()!=Item::ITEM_LAST-Item::ITEM_FIRST+1)
|
||||
{
|
||||
Log::fatal("StkConfig", "Wrong number of item switches defined in stk_config");
|
||||
@ -159,7 +159,7 @@ void STKConfig::init_defaults()
|
||||
m_bomb_time = m_bomb_time_increase =
|
||||
m_anvil_time = m_music_credit_time =
|
||||
m_delay_finish_time = m_skid_fadeout_time =
|
||||
m_near_ground = m_item_switch_time =
|
||||
m_near_ground = m_item_switch_time =
|
||||
m_smooth_angle_limit =
|
||||
m_penalty_time = m_explosion_impulse_objects = UNDEFINED;
|
||||
m_bubble_gum_counter = -100;
|
||||
@ -181,7 +181,7 @@ void STKConfig::init_defaults()
|
||||
m_ai_acceleration = 1.0f;
|
||||
m_disable_steer_while_unskid = false;
|
||||
m_camera_follow_skid = false;
|
||||
|
||||
|
||||
m_score_increase.clear();
|
||||
m_leader_intervals.clear();
|
||||
m_switch_items.clear();
|
||||
@ -226,7 +226,7 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
(int)m_score_increase.size()!=from-1)
|
||||
{
|
||||
Log::error("StkConfig", "Incorrect GP point specification:");
|
||||
Log::fatal("StkConfig", "from: %d to: %d points: %d",
|
||||
Log::fatal("StkConfig", "from: %d to: %d points: %d",
|
||||
from, to, points);
|
||||
exit(-1);
|
||||
}
|
||||
@ -246,7 +246,7 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
physics_node->get("smooth-normals", &m_smooth_normals );
|
||||
physics_node->get("smooth-angle-limit", &m_smooth_angle_limit);
|
||||
}
|
||||
|
||||
|
||||
if (const XMLNode *startup_node= root->getNode("startup"))
|
||||
{
|
||||
startup_node->get("penalty", &m_penalty_time );
|
||||
@ -268,7 +268,7 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
std::string title_music;
|
||||
music_node->get("title", &title_music);
|
||||
assert(title_music.size() > 0);
|
||||
|
||||
|
||||
m_title_music = MusicInformation::create(file_manager->getDataDir()
|
||||
+ "/music/" + title_music );
|
||||
if(!m_title_music)
|
||||
@ -293,7 +293,7 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
if(const XMLNode *credits_node= root->getNode("credits"))
|
||||
credits_node->get("music", &m_music_credit_time);
|
||||
|
||||
|
||||
|
||||
if(const XMLNode *anvil_node= root->getNode("anvil"))
|
||||
{
|
||||
anvil_node->get("weight", &m_anvil_weight );
|
||||
@ -352,7 +352,7 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
{
|
||||
ai_node->get("acceleration", &m_ai_acceleration);
|
||||
}
|
||||
|
||||
|
||||
if(const XMLNode *networking_node= root->getNode("networking"))
|
||||
networking_node->get("enable", &m_enable_networking);
|
||||
|
||||
@ -386,7 +386,7 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
void STKConfig::getAllScores(std::vector<int> *all_scores, int num_karts)
|
||||
{
|
||||
if (num_karts == 0) return;
|
||||
|
||||
|
||||
assert(num_karts <= m_max_karts);
|
||||
all_scores->resize(num_karts);
|
||||
(*all_scores)[num_karts-1] = 1; // last position gets one point
|
||||
|
@ -136,7 +136,7 @@ void GroupUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
|
||||
const XMLNode* child = node->getNode( m_param_name );
|
||||
if (child == NULL)
|
||||
{
|
||||
//std::cerr << "/!\\ User Config : Couldn't find parameter group "
|
||||
//std::cerr << "/!\\ User Config : Couldn't find parameter group "
|
||||
// << paramName << std::endl;
|
||||
return;
|
||||
}
|
||||
@ -180,7 +180,7 @@ void GroupUserConfigParam::addChild(UserConfigParam* child)
|
||||
|
||||
|
||||
// ============================================================================
|
||||
IntUserConfigParam::IntUserConfigParam(int default_value,
|
||||
IntUserConfigParam::IntUserConfigParam(int default_value,
|
||||
const char* param_name,
|
||||
const char* comment)
|
||||
{
|
||||
@ -192,9 +192,9 @@ IntUserConfigParam::IntUserConfigParam(int default_value,
|
||||
} // IntUserConfigParam
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
IntUserConfigParam::IntUserConfigParam(int default_value,
|
||||
IntUserConfigParam::IntUserConfigParam(int default_value,
|
||||
const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
@ -207,9 +207,9 @@ IntUserConfigParam::IntUserConfigParam(int default_value,
|
||||
// ----------------------------------------------------------------------------
|
||||
void IntUserConfigParam::write(XMLWriter& stream) const
|
||||
{
|
||||
if(m_comment.size() > 0) stream << L" <!-- " << m_comment.c_str()
|
||||
if(m_comment.size() > 0) stream << L" <!-- " << m_comment.c_str()
|
||||
<< L" -->\n";
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\"" << m_value
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\"" << m_value
|
||||
<< L"\" />\n\n";
|
||||
} // write
|
||||
|
||||
@ -242,8 +242,8 @@ void IntUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node)
|
||||
} // findYourDataInAnAttributeOf
|
||||
|
||||
// ============================================================================
|
||||
TimeUserConfigParam::TimeUserConfigParam(Time::TimeType default_value,
|
||||
const char* param_name,
|
||||
TimeUserConfigParam::TimeUserConfigParam(Time::TimeType default_value,
|
||||
const char* param_name,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
@ -254,9 +254,9 @@ TimeUserConfigParam::TimeUserConfigParam(Time::TimeType default_value,
|
||||
} // TimeUserConfigParam
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
TimeUserConfigParam::TimeUserConfigParam(Time::TimeType default_value,
|
||||
TimeUserConfigParam::TimeUserConfigParam(Time::TimeType default_value,
|
||||
const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
@ -273,7 +273,7 @@ void TimeUserConfigParam::write(XMLWriter& stream) const
|
||||
<< L" -->\n";
|
||||
std::ostringstream o;
|
||||
o<<m_value;
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\""
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\""
|
||||
<< core::stringw(o.str().c_str()) << L"\" />\n\n";
|
||||
} // write
|
||||
|
||||
@ -299,7 +299,7 @@ void TimeUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
|
||||
//std::cout << "Couldn't find int parameter " << paramName <<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int64_t tmp;
|
||||
child->get( "value", &tmp );
|
||||
m_value = tmp;
|
||||
@ -315,7 +315,7 @@ void TimeUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node)
|
||||
|
||||
// ============================================================================
|
||||
StringUserConfigParam::StringUserConfigParam(const char* default_value,
|
||||
const char* param_name,
|
||||
const char* param_name,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
@ -326,9 +326,9 @@ StringUserConfigParam::StringUserConfigParam(const char* default_value,
|
||||
} // StringUserConfigParam
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
StringUserConfigParam::StringUserConfigParam(const char* default_value,
|
||||
StringUserConfigParam::StringUserConfigParam(const char* default_value,
|
||||
const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
@ -341,9 +341,9 @@ StringUserConfigParam::StringUserConfigParam(const char* default_value,
|
||||
// ----------------------------------------------------------------------------
|
||||
void StringUserConfigParam::write(XMLWriter& stream) const
|
||||
{
|
||||
if(m_comment.size() > 0) stream << L" <!-- " << m_comment.c_str()
|
||||
if(m_comment.size() > 0) stream << L" <!-- " << m_comment.c_str()
|
||||
<< L" -->\n";
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\""
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\""
|
||||
<< m_value.c_str() << L"\" />\n\n";
|
||||
} // write
|
||||
|
||||
@ -363,14 +363,14 @@ void StringUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node)
|
||||
} // findYourDataInAnAttributeOf
|
||||
|
||||
// ============================================================================
|
||||
WStringUserConfigParam::WStringUserConfigParam(const core::stringw& default_value,
|
||||
const char* param_name,
|
||||
WStringUserConfigParam::WStringUserConfigParam(const core::stringw& default_value,
|
||||
const char* param_name,
|
||||
const char* comment)
|
||||
{
|
||||
|
||||
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
|
||||
|
||||
m_param_name = param_name;
|
||||
all_params.push_back(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
@ -379,12 +379,12 @@ WStringUserConfigParam::WStringUserConfigParam(const core::stringw& default_valu
|
||||
// ----------------------------------------------------------------------------
|
||||
WStringUserConfigParam::WStringUserConfigParam(const core::stringw& default_value,
|
||||
const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
|
||||
|
||||
m_param_name = param_name;
|
||||
group->addChild(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
@ -395,7 +395,7 @@ void WStringUserConfigParam::write(XMLWriter& stream) const
|
||||
{
|
||||
if(m_comment.size() > 0) stream << L" <!-- " << m_comment.c_str()
|
||||
<< L" -->\n";
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\"" << m_value
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\"" << m_value
|
||||
<< L"\" />\n\n";
|
||||
} // write
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -403,7 +403,7 @@ void WStringUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
|
||||
{
|
||||
const XMLNode* child = node->getNode( m_param_name );
|
||||
if(child == NULL) return;
|
||||
|
||||
|
||||
child->get( "value", &m_value );
|
||||
} // findYourDataInAChildOf
|
||||
|
||||
@ -414,13 +414,13 @@ void WStringUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node)
|
||||
} // findYourDataInAnAttributeOf
|
||||
|
||||
// ============================================================================
|
||||
BoolUserConfigParam::BoolUserConfigParam(bool default_value,
|
||||
const char* param_name,
|
||||
BoolUserConfigParam::BoolUserConfigParam(bool default_value,
|
||||
const char* param_name,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
|
||||
|
||||
m_param_name = param_name;
|
||||
all_params.push_back(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
@ -429,12 +429,12 @@ BoolUserConfigParam::BoolUserConfigParam(bool default_value,
|
||||
// ----------------------------------------------------------------------------
|
||||
BoolUserConfigParam::BoolUserConfigParam(bool default_value,
|
||||
const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
|
||||
|
||||
m_param_name = param_name;
|
||||
group->addChild(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
@ -446,7 +446,7 @@ void BoolUserConfigParam::write(XMLWriter& stream) const
|
||||
{
|
||||
if(m_comment.size() > 0) stream << L" <!-- " << m_comment.c_str()
|
||||
<< L" -->\n";
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\""
|
||||
stream << L" <" << m_param_name.c_str() << L" value=\""
|
||||
<< (m_value ? L"true" : L"false" ) << L"\" />\n\n";
|
||||
} // write
|
||||
|
||||
@ -469,7 +469,7 @@ void BoolUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unknown value for " << m_param_name
|
||||
std::cerr << "Unknown value for " << m_param_name
|
||||
<< "; expected true or false\n";
|
||||
}
|
||||
} // findYourDataInAChildOf
|
||||
@ -490,7 +490,7 @@ void BoolUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unknown value for " << m_param_name
|
||||
std::cerr << "Unknown value for " << m_param_name
|
||||
<< "; expected true or false\n";
|
||||
}
|
||||
} // findYourDataInAnAttributeOf
|
||||
@ -502,27 +502,27 @@ irr::core::stringw BoolUserConfigParam::toString() const
|
||||
} // toString
|
||||
|
||||
// ============================================================================
|
||||
FloatUserConfigParam::FloatUserConfigParam(float default_value,
|
||||
const char* param_name,
|
||||
FloatUserConfigParam::FloatUserConfigParam(float default_value,
|
||||
const char* param_name,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
|
||||
|
||||
m_param_name = param_name;
|
||||
all_params.push_back(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
} // FloatUserConfigParam
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
FloatUserConfigParam::FloatUserConfigParam(float default_value,
|
||||
FloatUserConfigParam::FloatUserConfigParam(float default_value,
|
||||
const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment)
|
||||
{
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
|
||||
|
||||
m_param_name = param_name;
|
||||
group->addChild(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
@ -598,7 +598,7 @@ void UserConfig::addDefaultPlayer()
|
||||
else if(getenv("LOGNAME")!=NULL) // Linux, Macs
|
||||
username = getenv("LOGNAME");
|
||||
|
||||
|
||||
|
||||
class GuestPlayerProfile : public PlayerProfile
|
||||
{
|
||||
public:
|
||||
@ -607,12 +607,12 @@ void UserConfig::addDefaultPlayer()
|
||||
m_is_guest_account = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// add default guest player
|
||||
UserConfigParams::m_all_players.push_back( new GuestPlayerProfile() );
|
||||
|
||||
// Set the name as the default name for all players.
|
||||
UserConfigParams::m_all_players.push_back(
|
||||
UserConfigParams::m_all_players.push_back(
|
||||
new PlayerProfile(username.c_str()) );
|
||||
|
||||
} // addDefaultPlayer
|
||||
@ -620,7 +620,7 @@ void UserConfig::addDefaultPlayer()
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/** Comparison used to sort players. Most frequent players should be
|
||||
* listed first, so a<b actually means that
|
||||
* listed first, so a<b actually means that
|
||||
* a.m_use_frequency > b.m_use_frequency
|
||||
* This way we get a reversed sorted list.
|
||||
*/
|
||||
@ -662,7 +662,7 @@ bool UserConfig::loadConfig()
|
||||
// so we just delete the old config. in the future, for smaller updates, we can
|
||||
// add back the code previously there that upgraded the config file to the new
|
||||
// format instead of overwriting it.
|
||||
|
||||
|
||||
GUIEngine::showMessage( _("Your config file was too old, so it was deleted and a new one will be created."), 10.0f);
|
||||
printf("Your config file was too old, so it was deleted and a new one will be created.");
|
||||
delete root;
|
||||
@ -677,13 +677,13 @@ bool UserConfig::loadConfig()
|
||||
{
|
||||
all_params[i].findYourDataInAChildOf(root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ---- Read players
|
||||
// we create those AFTER other values are being read simply because we have many Player
|
||||
// nodes that all bear the same name, so the generic loading code won't work here
|
||||
UserConfigParams::m_all_players.clearAndDeleteAll();
|
||||
|
||||
|
||||
std::vector<XMLNode*> players;
|
||||
root->getNodes("Player", players);
|
||||
const int amount = players.size();
|
||||
@ -694,10 +694,10 @@ bool UserConfig::loadConfig()
|
||||
UserConfigParams::m_all_players.push_back(
|
||||
new PlayerProfile(players[i]) );
|
||||
}
|
||||
|
||||
|
||||
// sort players by frequency of use
|
||||
UserConfigParams::m_all_players.insertionSort();
|
||||
|
||||
|
||||
|
||||
// ---- Read Saved GP's
|
||||
UserConfigParams::m_saved_grand_prix_list.clearAndDeleteAll();
|
||||
@ -706,7 +706,7 @@ bool UserConfig::loadConfig()
|
||||
const int gp_amount = saved_gps.size();
|
||||
for (int i=0; i<gp_amount; i++)
|
||||
{
|
||||
UserConfigParams::m_saved_grand_prix_list.push_back(
|
||||
UserConfigParams::m_saved_grand_prix_list.push_back(
|
||||
new SavedGrandPrix( saved_gps[i]) );
|
||||
}
|
||||
delete root;
|
||||
@ -741,7 +741,7 @@ void UserConfig::saveConfig()
|
||||
//std::cout << "saving parameter " << i << " to file\n";
|
||||
all_params[i].write(configfile);
|
||||
}
|
||||
|
||||
|
||||
configfile << L"</stkconfig>\n";
|
||||
configfile.close();
|
||||
}
|
||||
@ -758,7 +758,7 @@ bool UserConfigParams::logMemory()
|
||||
{ return (m_verbosity&LOG_MEMORY) == LOG_MEMORY;}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool UserConfigParams::logGUI ()
|
||||
bool UserConfigParams::logGUI ()
|
||||
{ return (m_verbosity&LOG_GUI) == LOG_GUI; }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -766,7 +766,7 @@ bool UserConfigParams::logAddons()
|
||||
{ return (m_verbosity&LOG_ADDONS) == LOG_ADDONS;}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool UserConfigParams::logFlyable()
|
||||
bool UserConfigParams::logFlyable()
|
||||
{ return (m_verbosity&LOG_FLYABLE) == LOG_FLYABLE; }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -6,7 +6,7 @@ namespace irr
|
||||
namespace scene
|
||||
{
|
||||
|
||||
CBatchingMesh::CBatchingMesh()
|
||||
CBatchingMesh::CBatchingMesh()
|
||||
: Box(core::vector3df(0,0,0)), IsDirty(false), IsFinal(false)
|
||||
{
|
||||
|
||||
@ -37,7 +37,7 @@ void CBatchingMesh::update()
|
||||
u32 i;
|
||||
for (i=0; i<DestBuffers.size(); ++i)
|
||||
{
|
||||
if (DestBuffers[i].IndexCount != DestBuffers[i].Buffer->getIndexCount() ||
|
||||
if (DestBuffers[i].IndexCount != DestBuffers[i].Buffer->getIndexCount() ||
|
||||
DestBuffers[i].VertexCount != DestBuffers[i].Buffer->getVertexCount())
|
||||
{
|
||||
DestBuffers[i].IsDirty = true;
|
||||
@ -155,7 +155,7 @@ s32 CBatchingMesh::addMeshBuffer(IMeshBuffer* buffer, const core::matrix4 &trans
|
||||
video::E_VERTEX_TYPE vt = buffer->getVertexType();
|
||||
for (i=0; i<MaterialReferences.size(); ++i)
|
||||
{
|
||||
if (MaterialReferences[i].VertexType == vt &&
|
||||
if (MaterialReferences[i].VertexType == vt &&
|
||||
MaterialReferences[i].Material == m)
|
||||
{
|
||||
// will there be too many vertices in the buffer?
|
||||
@ -218,7 +218,7 @@ s32 CBatchingMesh::addMeshBuffer(IMeshBuffer* buffer, const core::matrix4 &trans
|
||||
r.IndexCount = buffer->getIndexCount();
|
||||
r.VertexCount = buffer->getVertexCount();
|
||||
r.FirstIndex = DestBuffers[ MaterialReferences[i].BufferIndex ].IndexCount - r.IndexCount;
|
||||
r.FirstVertex = DestBuffers[ MaterialReferences[i].BufferIndex ].VertexCount - r.VertexCount;
|
||||
r.FirstVertex = DestBuffers[ MaterialReferences[i].BufferIndex ].VertexCount - r.VertexCount;
|
||||
r.Initialized = false;
|
||||
BufferReferences.push_back(r);
|
||||
addSourceBuffer(buffer);
|
||||
@ -255,7 +255,7 @@ u32 CBatchingMesh::getMeshBufferCount() const
|
||||
//! Returns pointer to a mesh buffer.
|
||||
/** \param nr: Zero based index of the mesh buffer. The maximum value is
|
||||
getMeshBufferCount() - 1;
|
||||
\return Returns the pointer to the mesh buffer or
|
||||
\return Returns the pointer to the mesh buffer or
|
||||
NULL if there is no such mesh buffer. */
|
||||
IMeshBuffer* CBatchingMesh::getMeshBuffer(u32 nr) const
|
||||
{
|
||||
@ -266,9 +266,9 @@ IMeshBuffer* CBatchingMesh::getMeshBuffer(u32 nr) const
|
||||
}
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
IMeshBuffer* CBatchingMesh::getMeshBuffer( const video::SMaterial &material) const
|
||||
{
|
||||
return 0;
|
||||
IMeshBuffer* CBatchingMesh::getMeshBuffer( const video::SMaterial &material) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Returns an axis aligned bounding box of the mesh.
|
||||
@ -422,9 +422,9 @@ void CBatchingMesh::updateDestFromSourceBuffer(u32 i)
|
||||
|
||||
for (x=fi; x < fi+ic; ++x)
|
||||
dest->Indices[x] = ind[x-fi]+fv;
|
||||
|
||||
|
||||
video::S3DVertex* vertices= (video::S3DVertex*) ver;
|
||||
|
||||
|
||||
for (x=fv; x < fv+vc; ++x)
|
||||
{
|
||||
dest->Vertices[x] = vertices[x-fv];
|
||||
@ -439,9 +439,9 @@ void CBatchingMesh::updateDestFromSourceBuffer(u32 i)
|
||||
|
||||
for (x=fi; x < fi+ic; ++x)
|
||||
dest->Indices[x] = ind[x-fi]+fv;
|
||||
|
||||
|
||||
video::S3DVertex2TCoords* vertices= (video::S3DVertex2TCoords*) ver;
|
||||
|
||||
|
||||
for (x=fv; x < fv+vc; ++x)
|
||||
{
|
||||
dest->Vertices[x] = vertices[x-fv];
|
||||
@ -456,9 +456,9 @@ void CBatchingMesh::updateDestFromSourceBuffer(u32 i)
|
||||
|
||||
for (x=fi; x < fi+ic; ++x)
|
||||
dest->Indices[x] = ind[x-fi]+fv;
|
||||
|
||||
|
||||
video::S3DVertexTangents* vertices= (video::S3DVertexTangents*) ver;
|
||||
|
||||
|
||||
for (x=fv; x < fv+vc; ++x)
|
||||
{
|
||||
dest->Vertices[x] = vertices[x-fv];
|
||||
|
@ -54,11 +54,11 @@ Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
|
||||
m_rain = NULL;
|
||||
m_original_kart = kart;
|
||||
m_camera = irr_driver->addCameraSceneNode();
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
m_camera->setName(core::stringc("Camera for ") + kart->getKartProperties()->getName());
|
||||
#endif
|
||||
|
||||
|
||||
setupCamera();
|
||||
m_distance = kart->getKartProperties()->getCameraDistance();
|
||||
setKart(kart);
|
||||
@ -66,9 +66,9 @@ Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
|
||||
|
||||
// TODO: Put these values into a config file
|
||||
// Global or per split screen zone?
|
||||
// Either global or per user (for instance, some users may not like
|
||||
// the extra camera rotation so they could set m_rotation_range to
|
||||
// zero to disable it for themselves).
|
||||
// Either global or per user (for instance, some users may not like
|
||||
// the extra camera rotation so they could set m_rotation_range to
|
||||
// zero to disable it for themselves).
|
||||
m_position_speed = 8.0f;
|
||||
m_target_speed = 10.0f;
|
||||
m_rotation_range = 0.4f;
|
||||
@ -84,7 +84,7 @@ Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
|
||||
} // Camera
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Removes the camera scene node from the scene.
|
||||
/** Removes the camera scene node from the scene.
|
||||
*/
|
||||
Camera::~Camera()
|
||||
{
|
||||
@ -131,7 +131,7 @@ void Camera::readEndCamera(const XMLNode &root)
|
||||
for(unsigned int i=0; i<root.getNumNodes(); i++)
|
||||
{
|
||||
unsigned int index = i;
|
||||
// In reverse mode, reverse the order in which the
|
||||
// In reverse mode, reverse the order in which the
|
||||
// end cameras are read.
|
||||
if(QuadGraph::get()->isReverse())
|
||||
index = root.getNumNodes() - 1 - i;
|
||||
@ -151,16 +151,16 @@ void Camera::setupCamera()
|
||||
m_aspect = (float)(UserConfigParams::m_width)/UserConfigParams::m_height;
|
||||
switch(race_manager->getNumLocalPlayers())
|
||||
{
|
||||
case 1: m_viewport = core::recti(0, 0,
|
||||
UserConfigParams::m_width,
|
||||
case 1: m_viewport = core::recti(0, 0,
|
||||
UserConfigParams::m_width,
|
||||
UserConfigParams::m_height);
|
||||
m_scaling = core::vector2df(1.0f, 1.0f);
|
||||
m_fov = DEGREE_TO_RAD*75.0f;
|
||||
break;
|
||||
case 2: m_viewport = core::recti(0,
|
||||
m_index==0 ? 0
|
||||
case 2: m_viewport = core::recti(0,
|
||||
m_index==0 ? 0
|
||||
: UserConfigParams::m_height>>1,
|
||||
UserConfigParams::m_width,
|
||||
UserConfigParams::m_width,
|
||||
m_index==0 ? UserConfigParams::m_height>>1
|
||||
: UserConfigParams::m_height);
|
||||
m_scaling = core::vector2df(1.0f, 0.5f);
|
||||
@ -171,19 +171,19 @@ void Camera::setupCamera()
|
||||
/*
|
||||
if(m_index<2)
|
||||
{
|
||||
m_viewport = core::recti(m_index==0 ? 0
|
||||
m_viewport = core::recti(m_index==0 ? 0
|
||||
: UserConfigParams::m_width>>1,
|
||||
0,
|
||||
m_index==0 ? UserConfigParams::m_width>>1
|
||||
: UserConfigParams::m_width,
|
||||
0,
|
||||
m_index==0 ? UserConfigParams::m_width>>1
|
||||
: UserConfigParams::m_width,
|
||||
UserConfigParams::m_height>>1);
|
||||
m_scaling = core::vector2df(0.5f, 0.5f);
|
||||
m_fov = DEGREE_TO_RAD*50.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_viewport = core::recti(0, UserConfigParams::m_height>>1,
|
||||
UserConfigParams::m_width,
|
||||
m_viewport = core::recti(0, UserConfigParams::m_height>>1,
|
||||
UserConfigParams::m_width,
|
||||
UserConfigParams::m_height);
|
||||
m_scaling = core::vector2df(1.0f, 0.5f);
|
||||
m_fov = DEGREE_TO_RAD*65.0f;
|
||||
@ -205,8 +205,8 @@ void Camera::setupCamera()
|
||||
if(UserConfigParams::logMisc())
|
||||
fprintf(stderr, "Incorrect number of players: '%d' - assuming 1.\n",
|
||||
race_manager->getNumLocalPlayers());
|
||||
m_viewport = core::recti(0, 0,
|
||||
UserConfigParams::m_width,
|
||||
m_viewport = core::recti(0, 0,
|
||||
UserConfigParams::m_width,
|
||||
UserConfigParams::m_height);
|
||||
m_scaling = core::vector2df(1.0f, 1.0f);
|
||||
m_fov = DEGREE_TO_RAD*75.0f;
|
||||
@ -216,7 +216,7 @@ void Camera::setupCamera()
|
||||
m_camera->setAspectRatio(m_aspect);
|
||||
m_camera->setFarValue(World::getWorld()->getTrack()->getCameraFar());
|
||||
|
||||
if (UserConfigParams::m_weather_effects &&
|
||||
if (UserConfigParams::m_weather_effects &&
|
||||
World::getWorld()->getTrack()->getWeatherType() == WEATHER_RAIN)
|
||||
{
|
||||
m_rain = new Rain(this, NULL);
|
||||
@ -230,8 +230,8 @@ void Camera::setupCamera()
|
||||
*/
|
||||
void Camera::setMode(Mode mode)
|
||||
{
|
||||
// If we switch from reverse view, move the camera immediately to the
|
||||
// correct position.
|
||||
// If we switch from reverse view, move the camera immediately to the
|
||||
// correct position.
|
||||
if(m_mode==CM_REVERSE && mode==CM_NORMAL)
|
||||
{
|
||||
Vec3 wanted_position, wanted_target;
|
||||
@ -321,7 +321,7 @@ void Camera::smoothMoveCamera(float dt, const Vec3 &wanted_position,
|
||||
assert(!isnan(m_camera->getPosition().X));
|
||||
assert(!isnan(m_camera->getPosition().Y));
|
||||
assert(!isnan(m_camera->getPosition().Z));
|
||||
|
||||
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
{
|
||||
sfx_manager->positionListener(current_position, current_target - current_position);
|
||||
@ -341,15 +341,15 @@ void Camera::computeNormalCameraPosition(Vec3 *wanted_position,
|
||||
{
|
||||
*wanted_target = m_kart->getXYZ();
|
||||
wanted_target->setY(wanted_target->getY()+ 0.75f);
|
||||
|
||||
// This first line moves the camera around behind the kart, pointing it
|
||||
|
||||
// This first line moves the camera around behind the kart, pointing it
|
||||
// towards where the kart is turning (and turning even more while skidding).
|
||||
// The skidding effect is dampened.
|
||||
float steering = m_kart->getSteerPercent()
|
||||
float steering = m_kart->getSteerPercent()
|
||||
* (1.0f + (m_kart->getSkidding()->getSkidFactor() - 1.0f)
|
||||
/2.3f );
|
||||
// quadratically to dampen small variations (but keep sign)
|
||||
float dampened_steer = fabsf(steering) * steering;
|
||||
float dampened_steer = fabsf(steering) * steering;
|
||||
|
||||
float tan_up = tan(m_kart->getKartProperties()->getCameraForwardUpAngle());
|
||||
Vec3 relative_position(-m_distance*m_rotation_range*dampened_steer*0.5f,
|
||||
@ -366,7 +366,7 @@ void Camera::computeNormalCameraPosition(Vec3 *wanted_position,
|
||||
* \param sideway Sideway movement of the camera.
|
||||
* \param distance Distance from kart.
|
||||
*/
|
||||
void Camera::getCameraSettings(float *above_kart, float *cam_angle,
|
||||
void Camera::getCameraSettings(float *above_kart, float *cam_angle,
|
||||
float *sideway, float *distance,
|
||||
bool *smoothing)
|
||||
{
|
||||
@ -388,11 +388,11 @@ void Camera::getCameraSettings(float *above_kart, float *cam_angle,
|
||||
case CM_FALLING:
|
||||
{
|
||||
*above_kart = 0.75f;
|
||||
float steering = m_kart->getSteerPercent()
|
||||
float steering = m_kart->getSteerPercent()
|
||||
* (1.0f + (m_kart->getSkidding()->getSkidFactor()
|
||||
- 1.0f)/2.3f );
|
||||
// quadratically to dampen small variations (but keep sign)
|
||||
float dampened_steer = fabsf(steering) * steering;
|
||||
float dampened_steer = fabsf(steering) * steering;
|
||||
*cam_angle = kp->getCameraForwardUpAngle();
|
||||
*sideway = -m_rotation_range*dampened_steer*0.5f;
|
||||
*distance = -m_distance;
|
||||
@ -412,7 +412,7 @@ void Camera::getCameraSettings(float *above_kart, float *cam_angle,
|
||||
{
|
||||
*above_kart = 0.75f;
|
||||
*cam_angle = 20.0f*DEGREE_TO_RAD;
|
||||
*sideway = m_rotation_range
|
||||
*sideway = m_rotation_range
|
||||
* m_kart->getSteerPercent()
|
||||
* m_kart->getSkidding()->getSkidFactor();
|
||||
*distance = -0.5f*m_distance;
|
||||
@ -450,7 +450,7 @@ void Camera::update(float dt)
|
||||
m_rain->update(dt);
|
||||
}
|
||||
} // UserConfigParams::m_graphical_effects
|
||||
|
||||
|
||||
|
||||
// The following settings give a debug camera which shows the track from
|
||||
// high above the kart straight down.
|
||||
@ -461,7 +461,7 @@ void Camera::update(float dt)
|
||||
xyz.Y = xyz.Y+55;
|
||||
xyz.Z -= 5.0f;
|
||||
m_camera->setPosition(xyz);
|
||||
// To view inside tunnels (FIXME 27>15 why??? makes no sense
|
||||
// To view inside tunnels (FIXME 27>15 why??? makes no sense
|
||||
// - the kart should not be visible, but it works)
|
||||
m_camera->setNearValue(27.0);
|
||||
return;
|
||||
@ -508,7 +508,7 @@ void Camera::update(float dt)
|
||||
* \param sideway Sideway movement of the camera.
|
||||
* \param distance Distance from kart.
|
||||
*/
|
||||
void Camera::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
void Camera::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
float side_way, float distance, float smoothing)
|
||||
{
|
||||
Vec3 wanted_position;
|
||||
@ -521,7 +521,7 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
fabsf(distance)*tan_up+above_kart,
|
||||
distance);
|
||||
btTransform t=m_kart->getTrans();
|
||||
if(stk_config->m_camera_follow_skid &&
|
||||
if(stk_config->m_camera_follow_skid &&
|
||||
m_kart->getSkidding()->getVisualSkidRotation()!=0)
|
||||
{
|
||||
// If the camera should follow the graphical skid, add the
|
||||
@ -540,10 +540,10 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
if (m_mode!=CM_FALLING)
|
||||
m_camera->setPosition(wanted_position.toIrrVector());
|
||||
m_camera->setTarget(wanted_target.toIrrVector());
|
||||
|
||||
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
{
|
||||
sfx_manager->positionListener(m_camera->getPosition(),
|
||||
sfx_manager->positionListener(m_camera->getPosition(),
|
||||
wanted_target - m_camera->getPosition());
|
||||
}
|
||||
}
|
||||
@ -552,7 +552,7 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** This function handles the end camera. It adjusts the camera position
|
||||
* according to the current camera type, and checks if a switch to the
|
||||
* according to the current camera type, and checks if a switch to the
|
||||
* next camera should be made.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
@ -560,7 +560,7 @@ void Camera::handleEndCamera(float dt)
|
||||
{
|
||||
// First test if the kart is close enough to the next end camera, and
|
||||
// if so activate it.
|
||||
if( m_end_cameras.size()>0 &&
|
||||
if( m_end_cameras.size()>0 &&
|
||||
m_end_cameras[m_next_end_camera].isReached(m_kart->getXYZ()))
|
||||
{
|
||||
m_current_end_camera = m_next_end_camera;
|
||||
@ -573,11 +573,11 @@ void Camera::handleEndCamera(float dt)
|
||||
}
|
||||
m_camera->setFOV(m_fov);
|
||||
m_next_end_camera++;
|
||||
if(m_next_end_camera>=(unsigned)m_end_cameras.size())
|
||||
if(m_next_end_camera>=(unsigned)m_end_cameras.size())
|
||||
m_next_end_camera = 0;
|
||||
}
|
||||
|
||||
EndCameraInformation::EndCameraType info
|
||||
EndCameraInformation::EndCameraType info
|
||||
= m_end_cameras.size()==0 ? EndCameraInformation::EC_AHEAD_OF_KART
|
||||
: m_end_cameras[m_current_end_camera].m_type;
|
||||
|
||||
@ -607,8 +607,8 @@ void Camera::handleEndCamera(float dt)
|
||||
const KartProperties *kp=m_kart->getKartProperties();
|
||||
float cam_angle = kp->getCameraBackwardUpAngle();
|
||||
|
||||
positionCamera(dt, /*above_kart*/0.75f,
|
||||
cam_angle, /*side_way*/0,
|
||||
positionCamera(dt, /*above_kart*/0.75f,
|
||||
cam_angle, /*side_way*/0,
|
||||
2.0f*m_distance, /*smoothing*/false);
|
||||
break;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound)
|
||||
: HitSFX(coord, explosion_sound)
|
||||
{
|
||||
// short emision time, explosion, not constant flame
|
||||
m_remaining_time = burst_time;
|
||||
m_remaining_time = burst_time;
|
||||
m_node = irr_driver->addParticleNode();
|
||||
m_node->grab();
|
||||
#ifdef DEBUG
|
||||
@ -48,9 +48,9 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound)
|
||||
m->setMaterialProperties(&(m_node->getMaterial(0)), NULL);
|
||||
m_node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
|
||||
|
||||
scene::IParticleEmitter* em =
|
||||
scene::IParticleEmitter* em =
|
||||
m_node->createSphereEmitter(core::vector3df(0.0f,0.0f,0.0f), 0.5f,
|
||||
/* velocity in m/ms */core::vector3df(0.0f,0.005f,0.0f),
|
||||
/* velocity in m/ms */core::vector3df(0.0f,0.005f,0.0f),
|
||||
600, 900, // min max particles per sec
|
||||
video::SColor(0, 0, 0, 0), // min colour
|
||||
video::SColor(0, 0, 0, 0), // max colour
|
||||
@ -60,13 +60,13 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound)
|
||||
*1000.0f), // max max life ms
|
||||
90, // max angle
|
||||
// min and max start size
|
||||
core::dimension2df(0.3f, 0.3f),
|
||||
core::dimension2df(0.3f, 0.3f),
|
||||
core::dimension2df(0.75f, 0.75f)
|
||||
);
|
||||
m_node->setEmitter(em); // this grabs the emitter
|
||||
em->drop(); // so we can drop it here without deleting it
|
||||
|
||||
scene::IParticleAffector* scale_affector =
|
||||
scene::IParticleAffector* scale_affector =
|
||||
m_node->createScaleParticleAffector(core::dimension2df(3.0f, 3.0f));
|
||||
m_node->addAffector(scale_affector); // same goes for the affector
|
||||
scale_affector->drop();
|
||||
@ -98,26 +98,26 @@ bool Explosion::updateAndDelete(float dt)
|
||||
HitSFX::updateAndDelete(dt);
|
||||
|
||||
m_remaining_time -= dt;
|
||||
|
||||
|
||||
if (m_remaining_time < 0.0f && m_remaining_time >= -explosion_time)
|
||||
{
|
||||
|
||||
|
||||
const int intensity = (int)(255-(m_remaining_time/-explosion_time)*255);
|
||||
m_node->getMaterial(0).AmbientColor.setGreen(intensity);
|
||||
m_node->getMaterial(0).DiffuseColor.setGreen(intensity);
|
||||
m_node->getMaterial(0).EmissiveColor.setGreen(intensity);
|
||||
|
||||
|
||||
m_node->getMaterial(0).AmbientColor.setBlue(intensity);
|
||||
m_node->getMaterial(0).DiffuseColor.setBlue(intensity);
|
||||
m_node->getMaterial(0).EmissiveColor.setBlue(intensity);
|
||||
|
||||
|
||||
m_node->getMaterial(0).AmbientColor.setRed(intensity);
|
||||
m_node->getMaterial(0).DiffuseColor.setRed(intensity);
|
||||
m_node->getMaterial(0).EmissiveColor.setRed(intensity);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Do nothing more if the animation is still playing
|
||||
if (m_remaining_time>0) return false;
|
||||
|
||||
@ -133,7 +133,7 @@ bool Explosion::updateAndDelete(float dt)
|
||||
else
|
||||
{
|
||||
// Sound and animation finished, node can be removed now.
|
||||
// Returning true will cause this node to be deleted by
|
||||
// Returning true will cause this node to be deleted by
|
||||
// the projectile manager.
|
||||
return true; // finished
|
||||
}
|
||||
|
@ -33,10 +33,10 @@ void HardwareSkinning::prepareNode(scene::IAnimatedMeshSceneNode *node)
|
||||
video::IVideoDriver* driver = irr_driver->getVideoDriver();
|
||||
video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
|
||||
assert(gpu); // TODO
|
||||
|
||||
|
||||
// Create the callback
|
||||
HWSkinningCallback* callback = new HWSkinningCallback(node);
|
||||
|
||||
|
||||
// Compile the shaders and associate the callback
|
||||
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
|
||||
(file_manager->getShaderDir()+"skinning.vert").c_str(),
|
||||
@ -46,19 +46,19 @@ void HardwareSkinning::prepareNode(scene::IAnimatedMeshSceneNode *node)
|
||||
|
||||
// Drop
|
||||
callback->drop();
|
||||
|
||||
|
||||
// Assign the hardware skinning material type
|
||||
node->setMaterialType((video::E_MATERIAL_TYPE)material_type);
|
||||
|
||||
|
||||
// Use VBOs and avoid streaming the vertex data
|
||||
//mesh->setHardwareMappingHint(scene::EHM_STATIC);
|
||||
mesh->setHardwareMappingHint(scene::EHM_DYNAMIC); // TODO: is it really better?
|
||||
|
||||
|
||||
// Hardware skinning is not implemented in Irrlicht (as of version 1.7.2) so "enabling" it
|
||||
// results in the data not being sent and the CPU not computing software skinning.
|
||||
scene::ISkinnedMesh* skin_mesh = (scene::ISkinnedMesh*)mesh;
|
||||
skin_mesh->setHardwareSkinning(true);
|
||||
|
||||
|
||||
// TODO: use custom vertex attributes?
|
||||
// !FUNTO! initialize all vertex colors to 0 (used as indexes)
|
||||
for(u32 i = 0;i < skin_mesh->getMeshBuffers().size();++i)
|
||||
@ -68,7 +68,7 @@ void HardwareSkinning::prepareNode(scene::IAnimatedMeshSceneNode *node)
|
||||
skin_mesh->getMeshBuffers()[i]->getVertex(g)->Color = video::SColor(0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// !FUNTO! set all vertex colors to indexes
|
||||
const core::array<scene::ISkinnedMesh::SJoint*>& joints = skin_mesh->getAllJoints();
|
||||
for(u32 i = 0;i < joints.size();++i)
|
||||
@ -80,7 +80,7 @@ void HardwareSkinning::prepareNode(scene::IAnimatedMeshSceneNode *node)
|
||||
|
||||
int vertexId = skin_mesh->getAllJoints()[i]->Weights[j].vertex_id;
|
||||
video::SColor* vColor = &skin_mesh->getMeshBuffers()[buffId]->getVertex(vertexId)->Color;
|
||||
|
||||
|
||||
if(vColor->getRed() == 0)
|
||||
vColor->setRed(i + 1);
|
||||
else if(vColor->getGreen() == 0)
|
||||
@ -117,12 +117,12 @@ void HWSkinningCallback::OnSetConstants(video::IMaterialRendererServices *servic
|
||||
};
|
||||
static const int nb_colors = 8;
|
||||
//int index = m_used_material
|
||||
|
||||
|
||||
int index = 4;
|
||||
//int index = *reinterpret_cast<const int*>(&m_used_material->MaterialTypeParam);
|
||||
//printf("OnSetConstants: index: %d\n", index);
|
||||
//index = 4 * (index % nb_colors);
|
||||
|
||||
|
||||
services->setPixelShaderConstant("debug_color", &colors[index], 4);
|
||||
*/
|
||||
//! Sets a constant for the pixel shader based on a name.
|
||||
@ -134,7 +134,7 @@ void HWSkinningCallback::OnSetConstants(video::IMaterialRendererServices *servic
|
||||
\param count Amount of floats in array.
|
||||
\return True if successful. */
|
||||
/*virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count) = 0;*/
|
||||
|
||||
|
||||
// TODO: cleanup
|
||||
// - joints
|
||||
scene::ISkinnedMesh* mesh = (scene::ISkinnedMesh*)m_node->getMesh();
|
||||
@ -146,16 +146,16 @@ void HWSkinningCallback::OnSetConstants(video::IMaterialRendererServices *servic
|
||||
{
|
||||
core::matrix4 joint_vertex_pull(core::matrix4::EM4CONST_NOTHING);
|
||||
joint_vertex_pull.setbyproduct(joints[i]->GlobalAnimatedMatrix, joints[i]->GlobalInversedMatrix);
|
||||
|
||||
|
||||
f32* pointer = joints_data + copyIncrement;
|
||||
for(int i = 0;i < 16;++i)
|
||||
*pointer++ = joint_vertex_pull[i];
|
||||
|
||||
|
||||
copyIncrement += 16;
|
||||
}
|
||||
|
||||
|
||||
services->setVertexShaderConstant("JointTransform", joints_data, mesh->getAllJoints().size() * 16);
|
||||
|
||||
|
||||
// - mWorldViewProj
|
||||
// set clip matrix at register 4
|
||||
/* core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
|
||||
@ -164,6 +164,6 @@ void HWSkinningCallback::OnSetConstants(video::IMaterialRendererServices *servic
|
||||
services->setVertexShaderConstant(&worldViewProj.M[0], 4, 4);
|
||||
*/ // for high level shading languages, this would be another solution:
|
||||
//services->setVertexShaderConstant("mWorldViewProj", worldViewProj.M, 16);
|
||||
|
||||
// -
|
||||
|
||||
// -
|
||||
}
|
||||
|
@ -25,12 +25,12 @@
|
||||
/** Creates a sound effect when something was hit. */
|
||||
HitSFX::HitSFX(const Vec3& coord, const char* explosion_sound)
|
||||
: HitEffect()
|
||||
{
|
||||
{
|
||||
m_sfx = sfx_manager->createSoundSource( explosion_sound );
|
||||
m_sfx->position(coord);
|
||||
|
||||
// in multiplayer mode, sounds are NOT positional (because we have
|
||||
// multiple listeners) so the sounds of all AIs are constantly heard.
|
||||
|
||||
// in multiplayer mode, sounds are NOT positional (because we have
|
||||
// multiple listeners) so the sounds of all AIs are constantly heard.
|
||||
// Therefore reduce volume of sounds.
|
||||
float vol = race_manager->getNumLocalPlayers() > 1 ? 0.5f : 1.0f;
|
||||
m_sfx->volume(vol);
|
||||
@ -44,7 +44,7 @@ HitSFX::~HitSFX()
|
||||
{
|
||||
if (m_sfx->getStatus() == SFXManager::SFX_PLAYING)
|
||||
m_sfx->stop();
|
||||
|
||||
|
||||
sfx_manager->deleteSFX(m_sfx);
|
||||
} // ~HitEffect
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -37,12 +37,12 @@ LODNode::LODNode(std::string group_name, scene::ISceneNode* parent,
|
||||
{
|
||||
assert(mgr != NULL);
|
||||
assert(parent != NULL);
|
||||
|
||||
|
||||
m_group_name = group_name;
|
||||
|
||||
|
||||
m_previous_visibility = FIRST_PASS;
|
||||
|
||||
// At this stage refcount is two: one because of the object being
|
||||
|
||||
// At this stage refcount is two: one because of the object being
|
||||
// created, and once because it is a child of the parent. Drop once,
|
||||
// so that only the reference from the parent is active, causing this
|
||||
// node to be deleted when it is removed from the parent.
|
||||
@ -73,9 +73,9 @@ int LODNode::getLevel()
|
||||
scene::ICameraSceneNode* curr_cam = irr_driver->getSceneManager()->getActiveCamera();
|
||||
|
||||
// Assumes all children are at the same location
|
||||
const int dist =
|
||||
const int dist =
|
||||
(int)((getPosition() + m_nodes[0]->getPosition()).getDistanceFromSQ( curr_cam->getPosition() ));
|
||||
|
||||
|
||||
for (unsigned int n=0; n<m_detail.size(); n++)
|
||||
{
|
||||
if (dist < m_detail[n])
|
||||
@ -100,7 +100,7 @@ void LODNode::OnAnimate(u32 timeMs)
|
||||
{
|
||||
// update absolute position
|
||||
updateAbsolutePosition();
|
||||
|
||||
|
||||
int level = getLevel();
|
||||
// Assume all the scene node have the same bouding box
|
||||
if(level>=0)
|
||||
@ -121,7 +121,7 @@ void LODNode::OnAnimate(u32 timeMs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,15 +138,15 @@ void LODNode::OnRegisterSceneNode()
|
||||
m_nodes[level]->OnRegisterSceneNode();
|
||||
shown = true;
|
||||
}
|
||||
|
||||
|
||||
// support an optional, mostly hard-coded fade-in/out effect for objects with a single level
|
||||
if (m_nodes.size() == 1 && (m_nodes[0]->getType() == scene::ESNT_MESH ||
|
||||
m_nodes[0]->getType() == scene::ESNT_ANIMATED_MESH))
|
||||
{
|
||||
if (m_previous_visibility == WAS_HIDDEN && shown)
|
||||
{
|
||||
{
|
||||
scene::IMesh* mesh;
|
||||
|
||||
|
||||
if (m_nodes[0]->getType() == scene::ESNT_MESH)
|
||||
{
|
||||
scene::IMeshSceneNode* node = (scene::IMeshSceneNode*)(m_nodes[0]);
|
||||
@ -160,13 +160,13 @@ void LODNode::OnRegisterSceneNode()
|
||||
assert(node != NULL);
|
||||
mesh = node->getMesh();
|
||||
}
|
||||
|
||||
|
||||
for (unsigned int n=0; n<mesh->getMeshBufferCount(); n++)
|
||||
{
|
||||
scene::IMeshBuffer* mb = mesh->getMeshBuffer(n);
|
||||
video::ITexture* t = mb->getMaterial().getTexture(0);
|
||||
if (t == NULL) continue;
|
||||
|
||||
|
||||
Material* m = material_manager->getMaterialFor(t, mb);
|
||||
if (m != NULL)
|
||||
{
|
||||
@ -175,9 +175,9 @@ void LODNode::OnRegisterSceneNode()
|
||||
}
|
||||
}
|
||||
else if (m_previous_visibility == WAS_SHOWN && !shown)
|
||||
{
|
||||
{
|
||||
scene::IMesh* mesh;
|
||||
|
||||
|
||||
if (m_nodes[0]->getType() == scene::ESNT_MESH)
|
||||
{
|
||||
scene::IMeshSceneNode* node = (scene::IMeshSceneNode*)(m_nodes[0]);
|
||||
@ -191,7 +191,7 @@ void LODNode::OnRegisterSceneNode()
|
||||
assert(node != NULL);
|
||||
mesh = node->getMesh();
|
||||
}
|
||||
|
||||
|
||||
for (unsigned int n=0; n<mesh->getMeshBufferCount(); n++)
|
||||
{
|
||||
scene::IMeshBuffer* mb = mesh->getMeshBuffer(n);
|
||||
@ -205,9 +205,9 @@ void LODNode::OnRegisterSceneNode()
|
||||
}
|
||||
}
|
||||
else if (m_previous_visibility == FIRST_PASS && !shown)
|
||||
{
|
||||
{
|
||||
scene::IMesh* mesh;
|
||||
|
||||
|
||||
if (m_nodes[0]->getType() == scene::ESNT_MESH)
|
||||
{
|
||||
scene::IMeshSceneNode* node = (scene::IMeshSceneNode*)(m_nodes[0]);
|
||||
@ -221,7 +221,7 @@ void LODNode::OnRegisterSceneNode()
|
||||
assert(node != NULL);
|
||||
mesh = node->getMesh();
|
||||
}
|
||||
|
||||
|
||||
for (unsigned int n=0; n<mesh->getMeshBufferCount(); n++)
|
||||
{
|
||||
scene::IMeshBuffer* mb = mesh->getMeshBuffer(n);
|
||||
@ -233,14 +233,14 @@ void LODNode::OnRegisterSceneNode()
|
||||
m->isInitiallyHidden(mb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_previous_visibility = (shown ? WAS_SHOWN : WAS_HIDDEN);
|
||||
|
||||
|
||||
m_previous_visibility = (shown ? WAS_SHOWN : WAS_HIDDEN);
|
||||
|
||||
// If this node has children other than the LOD nodes, draw them
|
||||
core::list<ISceneNode*>::Iterator it;
|
||||
|
||||
|
||||
for (it = Children.begin(); it != Children.end(); it++)
|
||||
{
|
||||
if (m_nodes_set.find(*it) == m_nodes_set.end())
|
||||
@ -265,9 +265,9 @@ void LODNode::add(int level, scene::ISceneNode* node, bool reparent)
|
||||
assert(m_detail.back()<level*level);
|
||||
m_detail[m_detail.size() - 1] += (int)(((rand()%1000)-500)/500.0f*(m_detail[m_detail.size() - 1]*0.2f));
|
||||
}
|
||||
|
||||
|
||||
assert(node != NULL);
|
||||
|
||||
|
||||
node->grab();
|
||||
node->remove();
|
||||
node->setPosition(core::vector3df(0,0,0));
|
||||
@ -275,11 +275,11 @@ void LODNode::add(int level, scene::ISceneNode* node, bool reparent)
|
||||
m_nodes.push_back(node);
|
||||
m_nodes_set.insert(node);
|
||||
node->setParent(this);
|
||||
|
||||
|
||||
if(UserConfigParams::m_hw_skinning_enabled && node->getType() == scene::ESNT_ANIMATED_MESH)
|
||||
HardwareSkinning::prepareNode((scene::IAnimatedMeshSceneNode*)node);
|
||||
|
||||
|
||||
node->drop();
|
||||
|
||||
|
||||
node->updateAbsolutePosition();
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -65,7 +65,7 @@ std::set<scene::IMeshBuffer*> g_processed;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Material* MaterialManager::getMaterialFor(video::ITexture* t,
|
||||
Material* MaterialManager::getMaterialFor(video::ITexture* t,
|
||||
scene::IMeshBuffer *mb)
|
||||
{
|
||||
assert(t != NULL);
|
||||
@ -78,7 +78,7 @@ Material* MaterialManager::getMaterialFor(video::ITexture* t,
|
||||
return m_materials[i];
|
||||
}
|
||||
} // for i
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ Material* MaterialManager::getMaterialFor(video::ITexture* t,
|
||||
* \param t Pointer to the texture.
|
||||
* \param mb Pointer to the mesh buffer.
|
||||
*/
|
||||
void MaterialManager::setAllMaterialFlags(video::ITexture* t,
|
||||
void MaterialManager::setAllMaterialFlags(video::ITexture* t,
|
||||
scene::IMeshBuffer *mb)
|
||||
{
|
||||
Material* mat = getMaterialFor(t, mb);
|
||||
@ -97,7 +97,7 @@ void MaterialManager::setAllMaterialFlags(video::ITexture* t,
|
||||
mat->setMaterialProperties(&(mb->getMaterial()), mb);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// This material does not appear in materials.xml. Set some common flags...
|
||||
if (UserConfigParams::m_anisotropic > 0)
|
||||
{
|
||||
@ -110,16 +110,16 @@ void MaterialManager::setAllMaterialFlags(video::ITexture* t,
|
||||
else if (UserConfigParams::m_trilinear)
|
||||
{
|
||||
mb->getMaterial().setFlag(video::EMF_TRILINEAR_FILTER, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mb->getMaterial().ColorMaterial = video::ECM_DIFFUSE_AND_AMBIENT;
|
||||
|
||||
|
||||
if (World::getWorld() != NULL && World::getWorld()->getTrack() != NULL)
|
||||
{
|
||||
mb->getMaterial().FogEnable = World::getWorld()->getTrack()->isFogEnabled();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Modify lightmap materials so that vertex colors are taken into account.
|
||||
// But disable lighting because we assume all lighting is already part
|
||||
// of the lightmap
|
||||
@ -131,16 +131,16 @@ void MaterialManager::setAllMaterialFlags(video::ITexture* t,
|
||||
mb->getMaterial().EmissiveColor = video::SColor(255, 255, 255, 255);
|
||||
mb->getMaterial().SpecularColor = video::SColor(255, 255, 255, 255);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//if (UserConfigParams::m_fullscreen_antialiasing)
|
||||
// mb->getMaterial().AntiAliasing = video::EAAM_LINE_SMOOTH;
|
||||
|
||||
|
||||
} // setAllMaterialFlags
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MaterialManager::adjustForFog(video::ITexture* t,
|
||||
void MaterialManager::adjustForFog(video::ITexture* t,
|
||||
scene::IMeshBuffer *mb,
|
||||
scene::ISceneNode* parent,
|
||||
bool use_fog) const
|
||||
@ -274,14 +274,14 @@ void MaterialManager::popTempMaterial()
|
||||
* material permanent, make_permanent must be set to true. This is used for
|
||||
* the powerup_manager, since not all icons for the powerups are listed in the
|
||||
* materials.dat file, causing the missing ones to be temporary only (and
|
||||
* then get deleted after one race, causing the powerup_manager to have
|
||||
* then get deleted after one race, causing the powerup_manager to have
|
||||
* invalid pointers.
|
||||
* \param fname Name of the material.
|
||||
* \param is_full_path True if the name includes the path (defaults to false)
|
||||
* \param make_permanent True if this material should be kept in memory
|
||||
* \param make_permanent True if this material should be kept in memory
|
||||
* (defaults to false)
|
||||
*/
|
||||
Material *MaterialManager::getMaterial(const std::string& fname,
|
||||
Material *MaterialManager::getMaterial(const std::string& fname,
|
||||
bool is_full_path,
|
||||
bool make_permanent,
|
||||
bool complain_if_not_found)
|
||||
@ -289,7 +289,7 @@ Material *MaterialManager::getMaterial(const std::string& fname,
|
||||
if(fname=="")
|
||||
{
|
||||
// This happens while reading the stk_config file, which contains
|
||||
// kart_properties information (but no icon file): since at this
|
||||
// kart_properties information (but no icon file): since at this
|
||||
// stage loadMaterial() hasn't been called, an exception can be
|
||||
// triggered here (as it happened with visual c++), when
|
||||
// m_materials[0] is accessed.
|
||||
@ -308,7 +308,7 @@ Material *MaterialManager::getMaterial(const std::string& fname,
|
||||
// Add the new material
|
||||
Material* m=new Material(fname, m_materials.size(), is_full_path, complain_if_not_found);
|
||||
m_materials.push_back(m);
|
||||
if(make_permanent)
|
||||
if(make_permanent)
|
||||
{
|
||||
assert(m_shared_material_index==(int)m_materials.size()-1);
|
||||
m_shared_material_index = (int)m_materials.size();
|
||||
@ -329,7 +329,7 @@ void MaterialManager::makeMaterialsPermanent()
|
||||
bool MaterialManager::hasMaterial(const std::string& fname)
|
||||
{
|
||||
std::string basename=StringUtils::getBasename(fname);
|
||||
|
||||
|
||||
// Search backward so that temporary (track) textures are found first
|
||||
for(int i = (int)m_materials.size()-1; i>=0; i-- )
|
||||
{
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <IMeshBuffer.h>
|
||||
|
||||
void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
|
||||
|
||||
|
||||
Vec3 extend;
|
||||
*min = Vec3( 999999.9f);
|
||||
*max = Vec3(-999999.9f);
|
||||
@ -56,7 +56,7 @@ void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Tools::minMax3D: Ignoring type '%d'!\n",
|
||||
fprintf(stderr, "Tools::minMax3D: Ignoring type '%d'!\n",
|
||||
mb->getVertexType());
|
||||
}
|
||||
} // for i<getMeshBufferCount
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
/** Constructor for an animated texture.
|
||||
* \param matrix The texture matrix to modify.
|
||||
* \param node An XML node containing dx and dy attributes to set the
|
||||
* \param node An XML node containing dx and dy attributes to set the
|
||||
* speed of the animation.
|
||||
*/
|
||||
MovingTexture::MovingTexture(core::matrix4 *matrix, const XMLNode &node)
|
||||
@ -42,7 +42,7 @@ MovingTexture::MovingTexture(core::matrix4 *matrix, const XMLNode &node)
|
||||
node.get("dx", &m_dx);
|
||||
node.get("dy", &m_dy);
|
||||
node.get("dt", &m_dt);
|
||||
|
||||
|
||||
node.get("animByStep", &m_isAnimatedByStep);
|
||||
} // MovingTexture
|
||||
|
||||
|
@ -37,10 +37,10 @@ class FadeAwayAffector : public scene::IParticleAffector
|
||||
{
|
||||
/** (Squared) distance from camera at which a particle started being faded out */
|
||||
float m_start_fading;
|
||||
|
||||
|
||||
/** (Squared) distance from camera at which a particle is completely faded out */
|
||||
float m_end_fading;
|
||||
|
||||
|
||||
public:
|
||||
FadeAwayAffector(float start, float end)
|
||||
{
|
||||
@ -48,17 +48,17 @@ public:
|
||||
m_end_fading = end;
|
||||
assert(m_end_fading >= m_start_fading);
|
||||
} // FadeAwayAffector
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
virtual void affect(u32 now, scene::SParticle* particlearray, u32 count)
|
||||
{
|
||||
scene::ICameraSceneNode* curr_cam =
|
||||
scene::ICameraSceneNode* curr_cam =
|
||||
irr_driver->getSceneManager()->getActiveCamera();
|
||||
const core::vector3df& cam_pos = curr_cam->getPosition();
|
||||
|
||||
|
||||
// printf("Affect called with now=%u, camera=%s\n", now, curr_cam->getName());
|
||||
|
||||
|
||||
for (unsigned int n=0; n<count; n++)
|
||||
{
|
||||
scene::SParticle& curr = particlearray[n];
|
||||
@ -67,7 +67,7 @@ public:
|
||||
const float y = diff.Y;
|
||||
const float z = diff.Z;
|
||||
const float distance_squared = x*x + y*y + z*z;
|
||||
|
||||
|
||||
if (distance_squared < m_start_fading)
|
||||
{
|
||||
curr.color.setAlpha(255);
|
||||
@ -78,20 +78,20 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
curr.color.setAlpha((int)((distance_squared - m_start_fading)
|
||||
curr.color.setAlpha((int)((distance_squared - m_start_fading)
|
||||
/ (m_end_fading - m_start_fading)));
|
||||
}
|
||||
} // for n<count
|
||||
} // affect
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
virtual scene::E_PARTICLE_AFFECTOR_TYPE getType() const
|
||||
{
|
||||
// FIXME: this method seems to make sense only for built-in affectors
|
||||
return scene::EPAT_FADE_OUT;
|
||||
}
|
||||
|
||||
|
||||
}; // FadeAwayAffector
|
||||
|
||||
|
||||
@ -102,14 +102,14 @@ class HeightMapCollisionAffector : public scene::IParticleAffector
|
||||
std::vector< std::vector<float> > m_height_map;
|
||||
Track* m_track;
|
||||
bool m_first_time;
|
||||
|
||||
|
||||
public:
|
||||
HeightMapCollisionAffector(Track* t) : m_height_map(t->buildHeightMap())
|
||||
{
|
||||
m_track = t;
|
||||
m_first_time = true;
|
||||
}
|
||||
|
||||
|
||||
virtual void affect(u32 now, scene::SParticle* particlearray, u32 count)
|
||||
{
|
||||
const Vec3* aabb_min;
|
||||
@ -119,7 +119,7 @@ public:
|
||||
float track_z = aabb_min->getZ();
|
||||
const float track_x_len = aabb_max->getX() - aabb_min->getX();
|
||||
const float track_z_len = aabb_max->getZ() - aabb_min->getZ();
|
||||
|
||||
|
||||
for (unsigned int n=0; n<count; n++)
|
||||
{
|
||||
scene::SParticle& curr = particlearray[n];
|
||||
@ -135,7 +135,7 @@ public:
|
||||
core::vector3df lp = curr.pos;
|
||||
core::vector3df lp2 = curr.pos;
|
||||
lp2.Y = m_height_map[i][j] + 0.02f;
|
||||
|
||||
|
||||
irr_driver->getVideoDriver()->draw3DLine(lp, lp2, video::SColor(255,255,0,0));
|
||||
core::vector3df lp3 = lp2;
|
||||
lp3.X += 0.1f;
|
||||
@ -146,10 +146,10 @@ public:
|
||||
lp2.Z -= 0.1f;
|
||||
irr_driver->getVideoDriver()->draw3DBox(core::aabbox3d< f32 >(lp2, lp3), video::SColor(255,255,0,0));
|
||||
*/
|
||||
|
||||
|
||||
if (m_first_time)
|
||||
{
|
||||
curr.pos.Y = m_height_map[i][j]
|
||||
curr.pos.Y = m_height_map[i][j]
|
||||
+ (curr.pos.Y - m_height_map[i][j])
|
||||
*((rand()%500)/500.0f);
|
||||
}
|
||||
@ -162,10 +162,10 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_first_time) m_first_time = false;
|
||||
}
|
||||
|
||||
|
||||
virtual scene::E_PARTICLE_AFFECTOR_TYPE getType() const
|
||||
{
|
||||
// FIXME: this method seems to make sense only for built-in affectors
|
||||
@ -176,9 +176,9 @@ public:
|
||||
|
||||
// ============================================================================
|
||||
|
||||
ParticleEmitter::ParticleEmitter(const ParticleKind* type,
|
||||
ParticleEmitter::ParticleEmitter(const ParticleKind* type,
|
||||
const Vec3 &position,
|
||||
scene::ISceneNode* parent)
|
||||
scene::ISceneNode* parent)
|
||||
: m_position(position)
|
||||
{
|
||||
assert(type != NULL);
|
||||
@ -188,10 +188,10 @@ ParticleEmitter::ParticleEmitter(const ParticleKind* type,
|
||||
m_particle_type = NULL;
|
||||
m_parent = parent;
|
||||
m_emission_decay_rate = 0;
|
||||
|
||||
|
||||
setParticleType(type);
|
||||
assert(m_node != NULL);
|
||||
|
||||
|
||||
} // KartParticleSystem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -203,7 +203,7 @@ ParticleEmitter::~ParticleEmitter()
|
||||
if (m_node != NULL)
|
||||
irr_driver->removeNode(m_node);
|
||||
m_emitter->drop();
|
||||
|
||||
|
||||
m_magic_number = 0xDEADBEEF;
|
||||
} // ~ParticleEmitter
|
||||
|
||||
@ -212,26 +212,26 @@ ParticleEmitter::~ParticleEmitter()
|
||||
void ParticleEmitter::update(float dt)
|
||||
{
|
||||
assert(m_magic_number == 0x58781325);
|
||||
|
||||
|
||||
// No particles to emit, nothing to do
|
||||
if (m_emitter->getMinParticlesPerSecond() == 0) return;
|
||||
|
||||
|
||||
// the emission direction does not automatically follow the orientation of
|
||||
// the node so fix that manually...
|
||||
core::matrix4 transform = m_node->getAbsoluteTransformation();
|
||||
core::vector3df velocity(m_particle_type->getVelocityX(),
|
||||
m_particle_type->getVelocityY(),
|
||||
m_particle_type->getVelocityZ());
|
||||
|
||||
|
||||
transform.rotateVect(velocity);
|
||||
m_emitter->setDirection(velocity);
|
||||
|
||||
|
||||
if (m_emission_decay_rate > 0)
|
||||
{
|
||||
m_max_rate = m_min_rate = std::max(0.0f, (m_min_rate - m_emission_decay_rate*dt));
|
||||
setCreationRateAbsolute(m_min_rate);
|
||||
}
|
||||
|
||||
|
||||
// There seems to be no way to randomise the velocity for particles,
|
||||
// so we have to do this manually, by changing the default velocity.
|
||||
// Irrlicht expects velocity (called 'direction') in m/ms!!
|
||||
@ -247,7 +247,7 @@ void ParticleEmitter::update(float dt)
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the creation rate as a relative fraction between minimum (f=0) and
|
||||
/** Sets the creation rate as a relative fraction between minimum (f=0) and
|
||||
* maximum (f=1) of the creation rates defined in the particle kind.
|
||||
* \param fraction Fraction to use.
|
||||
*/
|
||||
@ -268,10 +268,10 @@ void ParticleEmitter::setCreationRateAbsolute(float f)
|
||||
{
|
||||
m_emitter->setMinParticlesPerSecond(int(f));
|
||||
m_emitter->setMaxParticlesPerSecond(int(f));
|
||||
|
||||
|
||||
m_min_rate = f;
|
||||
m_max_rate = f;
|
||||
|
||||
|
||||
// FIXME: to work around irrlicht bug, when an emitter is paused by setting the rate
|
||||
// to 0 results in a massive emission when enabling it back. In irrlicht 1.8
|
||||
// the node has a method called "clearParticles" that should be cleaner than this
|
||||
@ -312,7 +312,7 @@ void ParticleEmitter::clearParticles()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
{
|
||||
{
|
||||
assert(m_magic_number == 0x58781325);
|
||||
bool is_new_type = (m_particle_type != type);
|
||||
if (is_new_type)
|
||||
@ -327,26 +327,26 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
{
|
||||
m_node = irr_driver->addParticleNode();
|
||||
}
|
||||
|
||||
|
||||
if (m_parent != NULL)
|
||||
{
|
||||
m_node->setParent(m_parent);
|
||||
}
|
||||
|
||||
|
||||
m_particle_type = type;
|
||||
}
|
||||
|
||||
|
||||
m_emission_decay_rate = type->getEmissionDecayRate();
|
||||
|
||||
|
||||
Material* material = type->getMaterial();
|
||||
const float minSize = type->getMinSize();
|
||||
const float maxSize = type->getMaxSize();
|
||||
const int lifeTimeMin = type->getMinLifetime();
|
||||
const int lifeTimeMax = type->getMaxLifetime();
|
||||
|
||||
|
||||
assert(maxSize >= minSize);
|
||||
assert(lifeTimeMax >= lifeTimeMin);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
if (material != NULL)
|
||||
{
|
||||
@ -354,33 +354,33 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
assert(tex != NULL);
|
||||
const io::SNamedPath& name = tex->getName();
|
||||
const io::path& tpath = name.getPath();
|
||||
|
||||
|
||||
std::string debug_name = std::string("particles(") + tpath.c_str() + ")";
|
||||
m_node->setName(debug_name.c_str());
|
||||
}
|
||||
#endif
|
||||
m_min_rate = (float)type->getMinRate();
|
||||
m_max_rate = (float)type->getMaxRate();
|
||||
|
||||
|
||||
if (is_new_type)
|
||||
{
|
||||
video::SMaterial& mat0 = m_node->getMaterial(0);
|
||||
|
||||
|
||||
m_node->setPosition(m_position.toIrrVector());
|
||||
|
||||
|
||||
if (material != NULL)
|
||||
{
|
||||
assert(material->getTexture() != NULL);
|
||||
material->setMaterialProperties(&mat0, NULL);
|
||||
m_node->setMaterialTexture(0, material->getTexture());
|
||||
|
||||
|
||||
mat0.ZWriteEnable = !material->isTransparent(); // disable z-buffer writes if material is transparent
|
||||
}
|
||||
else
|
||||
{
|
||||
m_node->setMaterialTexture(0, irr_driver->getTexture((file_manager->getDataDir() + "gui/main_help.png").c_str()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
switch (type->getShape())
|
||||
{
|
||||
@ -396,12 +396,12 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case EMITTER_BOX:
|
||||
{
|
||||
const float box_size_x = type->getBoxSizeX()/2.0f;
|
||||
const float box_size_y = type->getBoxSizeY()/2.0f;
|
||||
|
||||
|
||||
m_emitter = m_node->createBoxEmitter(core::aabbox3df(-box_size_x, -box_size_y, -0.6f,
|
||||
box_size_x, box_size_y, -0.6f - type->getBoxSizeZ()),
|
||||
core::vector3df(m_particle_type->getVelocityX(),
|
||||
@ -412,7 +412,7 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
lifeTimeMin, lifeTimeMax,
|
||||
m_particle_type->getAngleSpread() /* angle */
|
||||
);
|
||||
|
||||
|
||||
#if VISUALIZE_BOX_EMITTER
|
||||
if (m_parent != NULL)
|
||||
{
|
||||
@ -447,19 +447,19 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
m_emitter->setMinParticlesPerSecond(int(m_min_rate));
|
||||
m_emitter->setMaxParticlesPerSecond(int(m_max_rate));
|
||||
}
|
||||
|
||||
|
||||
m_emitter->setMinStartSize(core::dimension2df(minSize, minSize));
|
||||
m_emitter->setMaxStartSize(core::dimension2df(maxSize, maxSize));
|
||||
|
||||
|
||||
if (is_new_type)
|
||||
{
|
||||
m_node->setEmitter(m_emitter); // this grabs the emitter
|
||||
|
||||
|
||||
scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 255, 255),
|
||||
type->getFadeoutTime());
|
||||
m_node->addAffector(af);
|
||||
af->drop();
|
||||
|
||||
|
||||
if (type->getGravityStrength() != 0)
|
||||
{
|
||||
scene::IParticleGravityAffector *gaf = m_node->createGravityAffector(core::vector3df(00.0f, type->getGravityStrength(), 0.0f),
|
||||
@ -467,7 +467,7 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||
m_node->addAffector(gaf);
|
||||
gaf->drop();
|
||||
}
|
||||
|
||||
|
||||
const float fas = type->getFadeAwayStart();
|
||||
const float fae = type->getFadeAwayEnd();
|
||||
if (fas > 0.0f && fae > 0.0f)
|
||||
@ -493,14 +493,14 @@ void ParticleEmitter::addHeightMapAffector(Track* t)
|
||||
void ParticleEmitter::resizeBox(float size)
|
||||
{
|
||||
scene::IParticleBoxEmitter* emitter = (scene::IParticleBoxEmitter*)m_emitter;
|
||||
|
||||
|
||||
const float box_size_x = m_particle_type->getBoxSizeX()/2.0f;
|
||||
const float box_size_y = m_particle_type->getBoxSizeY()/2.0f;
|
||||
|
||||
|
||||
|
||||
|
||||
emitter->setBox( core::aabbox3df(-box_size_x, -box_size_y, -0.6f,
|
||||
box_size_x, box_size_y, -0.6f - size) );
|
||||
|
||||
|
||||
#if VISUALIZE_BOX_EMITTER
|
||||
if (m_parent != NULL)
|
||||
{
|
||||
|
@ -51,30 +51,30 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
|
||||
m_fade_away_end = -1.0f;
|
||||
m_force_lost_to_gravity_time = 1000;
|
||||
m_emission_decay_rate = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
// ----- Read XML file
|
||||
|
||||
|
||||
//std::cout << "==== READING " << file << " ====\n";
|
||||
|
||||
|
||||
XMLNode* xml = file_manager->createXMLTree(file);
|
||||
|
||||
|
||||
if (xml == NULL)
|
||||
{
|
||||
throw std::runtime_error("[ParticleKind] Cannot find file " + file);
|
||||
}
|
||||
|
||||
|
||||
if (xml->getName() != "particles")
|
||||
{
|
||||
delete xml;
|
||||
throw std::runtime_error("[ParticleKind] No <particles> main node in " + file);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
std::string emitterShape = "point";
|
||||
xml->get("emitter", &emitterShape);
|
||||
|
||||
|
||||
if (emitterShape == "point")
|
||||
{
|
||||
m_shape = EMITTER_POINT;
|
||||
@ -82,7 +82,7 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
|
||||
else if (emitterShape == "box")
|
||||
{
|
||||
m_shape = EMITTER_BOX;
|
||||
|
||||
|
||||
xml->get("box_x", &m_box_x);
|
||||
xml->get("box_y", &m_box_y);
|
||||
xml->get("box_z", &m_box_z);
|
||||
@ -92,37 +92,37 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
|
||||
fprintf(stderr, "[ParticleKind] <particles> main node has unknown value for attribute 'emitter'\n");
|
||||
m_shape = EMITTER_POINT;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
const XMLNode* spreading = xml->getNode("spreading");
|
||||
spreading->get("angle", &m_angle_spread);
|
||||
|
||||
|
||||
//std::cout << "m_spread_factor = " << m_spread_factor << "\n";
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
const XMLNode* velocity = xml->getNode("velocity");
|
||||
velocity->get("x", &m_velocity_x);
|
||||
velocity->get("y", &m_velocity_y);
|
||||
velocity->get("z", &m_velocity_z);
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// old deperecated way
|
||||
const XMLNode* material = xml->getNode("material");
|
||||
if (material != NULL)
|
||||
{
|
||||
material->get("file", &m_material_file);
|
||||
|
||||
|
||||
if (m_material_file.size() == 0)
|
||||
{
|
||||
delete xml;
|
||||
throw std::runtime_error("[ParticleKind] <material> tag has invalid 'file' attribute");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
const XMLNode* rate = xml->getNode("rate");
|
||||
if (rate != NULL)
|
||||
{
|
||||
@ -130,85 +130,85 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
|
||||
rate->get("max", &m_max_rate);
|
||||
rate->get("decay_rate", &m_emission_decay_rate);
|
||||
}
|
||||
|
||||
|
||||
//std::cout << "m_min_rate = " << m_min_rate << "\n";
|
||||
//std::cout << "m_max_rate = " << m_max_rate << "\n";
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
const XMLNode* lifetime = xml->getNode("lifetime");
|
||||
if (lifetime != NULL)
|
||||
{
|
||||
lifetime->get("min", &m_lifetime_min);
|
||||
lifetime->get("max", &m_lifetime_max);
|
||||
}
|
||||
|
||||
|
||||
//std::cout << "m_lifetime_min = " << m_lifetime_min << "\n";
|
||||
//std::cout << "m_lifetime_max = " << m_lifetime_max << "\n";
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
const XMLNode* size = xml->getNode("size");
|
||||
if (size != NULL)
|
||||
{
|
||||
size->get("min", &m_min_size);
|
||||
size->get("max", &m_max_size);
|
||||
}
|
||||
|
||||
|
||||
//std::cout << "m_particle_size = " << m_particle_size << "\n";
|
||||
//std::cout << "m_min_size = " << m_min_size << "\n";
|
||||
//std::cout << "m_max_size = " << m_max_size << "\n";
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
const XMLNode* color = xml->getNode("color");
|
||||
if (color != NULL)
|
||||
{
|
||||
color->get("min", &m_min_start_color);
|
||||
color->get("max", &m_max_start_color);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
const XMLNode* fadeout = xml->getNode("fadeout");
|
||||
if (fadeout != NULL)
|
||||
{
|
||||
fadeout->get("time", &m_fadeout_time);
|
||||
}
|
||||
|
||||
|
||||
//std::cout << "m_fadeout_time = " << m_fadeout_time << "\n";
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
const XMLNode* gravity = xml->getNode("gravity");
|
||||
if (gravity != NULL)
|
||||
{
|
||||
gravity->get("strength", &m_gravity_strength);
|
||||
gravity->get("only-force-time", &m_force_lost_to_gravity_time);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
const XMLNode* fadeaway = xml->getNode("fade-away");
|
||||
if (fadeaway != NULL)
|
||||
{
|
||||
fadeaway->get("start", &m_fade_away_start);
|
||||
fadeaway->get("end", &m_fade_away_end);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
const XMLNode* materials = xml->getNode("materials");
|
||||
if (materials != NULL)
|
||||
{
|
||||
material_manager->pushTempMaterial(materials, file);
|
||||
m_material_file = material_manager->getLatestMaterial()->getTexFname();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
delete xml;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ ParticleKindManager::~ParticleKindManager()
|
||||
void ParticleKindManager::cleanup()
|
||||
{
|
||||
cleanUpTrackSpecificGfx();
|
||||
|
||||
|
||||
std::map<std::string, ParticleKind*>::iterator it;
|
||||
for (it = m_kinds.begin(); it != m_kinds.end(); it++)
|
||||
{
|
||||
@ -97,7 +97,7 @@ ParticleKind* ParticleKindManager::getParticles(const std::string &name)
|
||||
// not found in track directory, let's try globally...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
i = m_kinds.find(name);
|
||||
if (i == m_kinds.end())
|
||||
{
|
||||
|
@ -31,14 +31,14 @@ PerCameraNode::PerCameraNode(scene::ISceneNode* parent, scene::ISceneManager* mg
|
||||
if (camera)
|
||||
setName(camera->getName());
|
||||
#endif
|
||||
|
||||
|
||||
m_camera = camera;
|
||||
m_child = mgr->addMeshSceneNode(mesh, this);
|
||||
//m_child = mgr->addCubeSceneNode(0.5f, this, -1, core::vector3df(0,0,0), core::vector3df(0,0,0), core::vector3df(3.0f,0.2f,3.0f));
|
||||
//RelativeTransformationMatrix.setTranslation( core::vector3df(-0.5,-1,3) );
|
||||
|
||||
|
||||
setAutomaticCulling(scene::EAC_OFF);
|
||||
|
||||
|
||||
parent->addChild(this);
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ PerCameraNode::~PerCameraNode()
|
||||
void PerCameraNode::render()
|
||||
{
|
||||
scene::ICameraSceneNode* curr_cam = irr_driver->getSceneManager()->getActiveCamera();
|
||||
|
||||
|
||||
// Only register children nodes if the right camera is in use
|
||||
if (curr_cam == m_camera) ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
@ -76,7 +76,7 @@ void PerCameraNode::OnRegisterSceneNode()
|
||||
void PerCameraNode::setCamera(scene::ICameraSceneNode* camera)
|
||||
{
|
||||
m_camera = camera;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
if (camera)
|
||||
setName(camera->getName());
|
||||
|
@ -43,12 +43,12 @@ PostProcessing::PostProcessing(video::IVideoDriver* video_driver)
|
||||
{
|
||||
m_supported = true;
|
||||
}
|
||||
|
||||
|
||||
//Check which texture dimensions are supported on this hardware
|
||||
bool nonsquare = video_driver->queryFeature(video::EVDF_TEXTURE_NSQUARE);
|
||||
bool nonpower = video_driver->queryFeature(video::EVDF_TEXTURE_NPOT);
|
||||
if (!nonpower) {
|
||||
Log::warn("PostProcessing",
|
||||
Log::warn("PostProcessing",
|
||||
"Only power of two textures are supported.");
|
||||
}
|
||||
if (!nonsquare) {
|
||||
@ -60,7 +60,7 @@ PostProcessing::PostProcessing(video::IVideoDriver* video_driver)
|
||||
// Render target
|
||||
core::dimension2du opt = video_driver->getScreenSize()
|
||||
.getOptimalSize(!nonpower, !nonsquare);
|
||||
m_render_target =
|
||||
m_render_target =
|
||||
video_driver->addRenderTargetTexture(opt, "postprocess");
|
||||
if(!m_render_target)
|
||||
{
|
||||
@ -68,9 +68,9 @@ PostProcessing::PostProcessing(video::IVideoDriver* video_driver)
|
||||
"for post-processing, disabling it.");
|
||||
UserConfigParams::m_postprocess_enabled = false;
|
||||
}
|
||||
|
||||
|
||||
// Material and shaders
|
||||
IGPUProgrammingServices* gpu =
|
||||
IGPUProgrammingServices* gpu =
|
||||
video_driver->getGPUProgrammingServices();
|
||||
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
|
||||
(file_manager->getShaderDir() + "motion_blur.vert").c_str(),
|
||||
@ -95,7 +95,7 @@ PostProcessing::~PostProcessing()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialises post processing at the (re-)start of a race. This sets up
|
||||
* the vertices, normals and texture coordinates for each
|
||||
* the vertices, normals and texture coordinates for each
|
||||
*/
|
||||
void PostProcessing::reset()
|
||||
{
|
||||
@ -108,11 +108,11 @@ void PostProcessing::reset()
|
||||
for(unsigned int i=0; i<n; i++)
|
||||
{
|
||||
m_boost_time[i] = 0.0f;
|
||||
|
||||
|
||||
const core::recti &vp = Camera::getCamera(i)->getViewport();
|
||||
// Map viewport to [-1,1] x [-1,1]. First define the coordinates
|
||||
// left, right, top, bottom:
|
||||
float right = vp.LowerRightCorner.X < UserConfigParams::m_width
|
||||
float right = vp.LowerRightCorner.X < UserConfigParams::m_width
|
||||
? 0.0f : 1.0f;
|
||||
float left = vp.UpperLeftCorner.X > 0.0f ? 0.0f : -1.0f;
|
||||
float top = vp.UpperLeftCorner.Y > 0.0f ? 0.0f : 1.0f;
|
||||
@ -125,7 +125,7 @@ void PostProcessing::reset()
|
||||
m_vertices[i].v1.Pos = core::vector3df(left, top, 0);
|
||||
m_vertices[i].v2.Pos = core::vector3df(right, top, 0);
|
||||
m_vertices[i].v3.Pos = core::vector3df(right, bottom, 0);
|
||||
// Define the texture coordinates of each vertex, which must
|
||||
// Define the texture coordinates of each vertex, which must
|
||||
// be in [0,1]x[0,1]
|
||||
m_vertices[i].v0.TCoords = core::vector2df(left ==-1.0f ? 0.0f : 0.5f,
|
||||
bottom==-1.0f ? 0.0f : 0.5f);
|
||||
@ -137,10 +137,10 @@ void PostProcessing::reset()
|
||||
bottom==-1.0f ? 0.0f : 0.5f);
|
||||
// Set normal and color:
|
||||
core::vector3df normal(0,0,1);
|
||||
m_vertices[i].v0.Normal = m_vertices[i].v1.Normal =
|
||||
m_vertices[i].v0.Normal = m_vertices[i].v1.Normal =
|
||||
m_vertices[i].v2.Normal = m_vertices[i].v3.Normal = normal;
|
||||
video::SColor white(0xFF, 0xFF, 0xFF, 0xFF);
|
||||
m_vertices[i].v0.Color = m_vertices[i].v1.Color =
|
||||
m_vertices[i].v0.Color = m_vertices[i].v1.Color =
|
||||
m_vertices[i].v2.Color = m_vertices[i].v3.Color = white;
|
||||
|
||||
m_center[i].X=(m_vertices[i].v0.TCoords.X
|
||||
@ -167,15 +167,15 @@ void PostProcessing::beginCapture()
|
||||
bool any_boost = false;
|
||||
for(unsigned int i=0; i<m_boost_time.size(); i++)
|
||||
any_boost |= m_boost_time[i]>0.0f;
|
||||
|
||||
|
||||
// Don't capture the input when we have no post-processing to add
|
||||
// it will be faster and this ay we won't lose anti-aliasing
|
||||
if(!any_boost)
|
||||
if(!any_boost)
|
||||
{
|
||||
m_used_pp_this_frame = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
m_used_pp_this_frame = true;
|
||||
irr_driver->getVideoDriver()->setRenderTarget(m_render_target, true, true);
|
||||
} // beginCapture
|
||||
@ -188,7 +188,7 @@ void PostProcessing::endCapture()
|
||||
if(!m_supported || !UserConfigParams::m_postprocess_enabled ||
|
||||
!m_used_pp_this_frame)
|
||||
return;
|
||||
|
||||
|
||||
irr_driver->getVideoDriver()->setRenderTarget(video::ERT_FRAME_BUFFER,
|
||||
true, true, 0);
|
||||
} // endCapture
|
||||
@ -222,7 +222,7 @@ void PostProcessing::render()
|
||||
{
|
||||
if(!m_supported || !UserConfigParams::m_postprocess_enabled)
|
||||
return;
|
||||
|
||||
|
||||
if (!m_used_pp_this_frame)
|
||||
{
|
||||
return;
|
||||
@ -230,10 +230,10 @@ void PostProcessing::render()
|
||||
|
||||
u16 indices[6] = {0, 1, 2, 3, 0, 2};
|
||||
|
||||
for(m_current_camera=0; m_current_camera<Camera::getNumCameras();
|
||||
for(m_current_camera=0; m_current_camera<Camera::getNumCameras();
|
||||
m_current_camera++)
|
||||
{
|
||||
// Draw the fullscreen quad while applying the corresponding
|
||||
// Draw the fullscreen quad while applying the corresponding
|
||||
// post-processing shaders
|
||||
video::IVideoDriver* video_driver = irr_driver->getVideoDriver();
|
||||
video_driver->setMaterial(m_blur_material);
|
||||
@ -244,7 +244,7 @@ void PostProcessing::render()
|
||||
} // render
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Implement IShaderConstantsSetCallback. Shader constants setter for
|
||||
/** Implement IShaderConstantsSetCallback. Shader constants setter for
|
||||
* post-processing */
|
||||
void PostProcessing::OnSetConstants(video::IMaterialRendererServices *services,
|
||||
s32 user_data)
|
||||
@ -255,7 +255,7 @@ void PostProcessing::OnSetConstants(video::IMaterialRendererServices *services,
|
||||
|
||||
// Scale the boost time to get a usable boost amount:
|
||||
float boost_amount = m_boost_time[m_current_camera] * 0.7f;
|
||||
|
||||
|
||||
// Especially for single screen the top of the screen is less blurred
|
||||
// in the fragment shader by multiplying the blurr factor by
|
||||
// (max_tex_height - texcoords.t), where max_tex_height is the maximum
|
||||
@ -266,9 +266,9 @@ void PostProcessing::OnSetConstants(video::IMaterialRendererServices *services,
|
||||
boost_amount *= 2.0f;
|
||||
|
||||
services->setPixelShaderConstant("boost_amount", &boost_amount, 1);
|
||||
services->setPixelShaderConstant("center",
|
||||
services->setPixelShaderConstant("center",
|
||||
&(m_center[m_current_camera].X), 2);
|
||||
services->setPixelShaderConstant("direction",
|
||||
services->setPixelShaderConstant("direction",
|
||||
&(m_direction[m_current_camera].X), 2);
|
||||
|
||||
// Use a radius of 0.15 when showing a single kart, otherwise (2-4 karts
|
||||
|
@ -44,56 +44,56 @@ const float TEXTURE_Y_TILES[RAIN_RING_COUNT] = { 8.0f, 7.0f, 6.0f, 4.0f, 4.0f };
|
||||
Rain::Rain(Camera *camera, irr::scene::ISceneNode* parent)
|
||||
{
|
||||
m_lightning = camera->getIndex()==0;
|
||||
|
||||
if (m_lightning)
|
||||
|
||||
if (m_lightning)
|
||||
m_thunder_sound = sfx_manager->createSoundSource("thunder");
|
||||
|
||||
|
||||
Material* m = material_manager->getMaterial("rain.png");
|
||||
assert(m != NULL);
|
||||
|
||||
|
||||
RandomGenerator g;
|
||||
m_next_lightning = (float)g.get(35);
|
||||
|
||||
|
||||
for (int r=0; r<RAIN_RING_COUNT; r++)
|
||||
{
|
||||
m_x[r] = r/(float)RAIN_RING_COUNT;
|
||||
m_y[r] = r/(float)RAIN_RING_COUNT;
|
||||
|
||||
|
||||
scene::SMeshBuffer *buffer = new scene::SMeshBuffer();
|
||||
|
||||
|
||||
buffer->Material.setTexture(0, m->getTexture());
|
||||
m->setMaterialProperties(&buffer->Material, NULL);
|
||||
buffer->Material.ZWriteEnable = false;
|
||||
buffer->Material.BackfaceCulling = false;
|
||||
|
||||
|
||||
m_materials.push_back(&buffer->Material);
|
||||
|
||||
|
||||
video::S3DVertex v;
|
||||
v.Color.set(255,255,255,255);
|
||||
|
||||
|
||||
// create a cylinder mesh
|
||||
const int VERTICES = 17;
|
||||
|
||||
|
||||
for (int vid=0; vid<VERTICES*2; vid+=2)
|
||||
{
|
||||
const float ratio = float(vid) / float(VERTICES-1);
|
||||
const float angle = ratio * 2.0f * M_PI;
|
||||
|
||||
|
||||
v.Pos.X = cos(angle)*RAIN_RADIUS[r];
|
||||
v.Pos.Y = RAIN_Y_TO;
|
||||
v.Pos.Z = sin(angle)*RAIN_RADIUS[r];
|
||||
|
||||
|
||||
// offset the X coord in texturing so you don't see textures from
|
||||
// the different rings lining up
|
||||
v.TCoords.X = ratio*TEXTURE_X_TILES[r] + r/3.0f;
|
||||
v.TCoords.Y = TEXTURE_Y_TILES[r];
|
||||
buffer->Vertices.push_back(v);
|
||||
|
||||
|
||||
v.Pos.Y = RAIN_Y_FROM;
|
||||
|
||||
|
||||
v.TCoords.Y = 0.0f;
|
||||
buffer->Vertices.push_back(v);
|
||||
|
||||
|
||||
if (vid > 0)
|
||||
{
|
||||
buffer->Indices.push_back(vid-2);
|
||||
@ -108,12 +108,12 @@ Rain::Rain(Camera *camera, irr::scene::ISceneNode* parent)
|
||||
scene::SMesh* mesh = new scene::SMesh();
|
||||
mesh->addMeshBuffer(buffer);
|
||||
mesh->recalculateBoundingBox();
|
||||
|
||||
m_node[r] = irr_driver->addPerCameraMesh(mesh,
|
||||
|
||||
m_node[r] = irr_driver->addPerCameraMesh(mesh,
|
||||
camera->getCameraSceneNode(),
|
||||
parent);
|
||||
mesh->drop();
|
||||
|
||||
|
||||
buffer->drop();
|
||||
}
|
||||
} // Rain
|
||||
@ -127,7 +127,7 @@ Rain::~Rain()
|
||||
m_node[r]->drop(); // drop STK's reference
|
||||
m_node[r]->remove(); // Then remove it from the scene graph.
|
||||
}
|
||||
|
||||
|
||||
if (m_lightning && m_thunder_sound != NULL) sfx_manager->deleteSFX(m_thunder_sound);
|
||||
}
|
||||
|
||||
@ -142,16 +142,16 @@ void Rain::update(float dt)
|
||||
m_y[m] = m_y[m] + dt*RAIN_DY;
|
||||
if (m_x[m] > 1.0f) m_x[m] = fmod(m_x[m], 1.0f);
|
||||
if (m_y[m] > 1.0f) m_y[m] = fmod(m_y[m], 1.0f);
|
||||
|
||||
|
||||
core::matrix4& matrix = m_node[m]->getChild()->getMaterial(0).getTextureMatrix(0);
|
||||
|
||||
matrix.setTextureTranslate(m_x[m], m_y[m]);
|
||||
}
|
||||
|
||||
|
||||
if (m_lightning)
|
||||
{
|
||||
m_next_lightning -= dt;
|
||||
|
||||
|
||||
if (m_next_lightning < 0.0f)
|
||||
{
|
||||
RaceGUIBase* gui_base = World::getWorld()->getRaceGUI();
|
||||
@ -160,12 +160,12 @@ void Rain::update(float dt)
|
||||
gui_base->doLightning();
|
||||
if (m_thunder_sound) m_thunder_sound->play();
|
||||
}
|
||||
|
||||
|
||||
RandomGenerator g;
|
||||
m_next_lightning = 35 + (float)g.get(35);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2011 Joerg Henrichs
|
||||
// Copyright (C) 2011 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
@ -80,7 +80,7 @@ void Referee::init()
|
||||
MeshTools::minMax3D(m_st_referee_mesh, &min, &max);
|
||||
Vec3 offset_from_center = -0.5f*(max+min);
|
||||
offset_from_center.setY(0);
|
||||
scene::IMeshManipulator *mani =
|
||||
scene::IMeshManipulator *mani =
|
||||
irr_driver->getVideoDriver()->getMeshManipulator();
|
||||
|
||||
core::matrix4 translate(core::matrix4::EM4CONST_IDENTITY);
|
||||
@ -94,7 +94,7 @@ void Referee::init()
|
||||
node->get("scale", &m_st_scale );
|
||||
node->get("start-rotation", &m_st_start_rotation );
|
||||
|
||||
float angle_to_kart = atan2(m_st_start_offset.getX(),
|
||||
float angle_to_kart = atan2(m_st_start_offset.getX(),
|
||||
m_st_start_offset.getZ())
|
||||
* RAD_TO_DEGREE;
|
||||
m_st_start_rotation.setY(m_st_start_rotation.getY()+angle_to_kart);
|
||||
@ -141,7 +141,7 @@ void Referee::init()
|
||||
{
|
||||
irrMaterial.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
delete node;
|
||||
@ -175,7 +175,7 @@ Referee::Referee()
|
||||
m_scene_node->grab();
|
||||
m_scene_node->setRotation(m_st_start_rotation.toIrrVector());
|
||||
m_scene_node->setScale(m_st_scale.toIrrVector());
|
||||
m_scene_node->setFrameLoop(m_st_first_start_frame,
|
||||
m_scene_node->setFrameLoop(m_st_first_start_frame,
|
||||
m_st_last_start_frame);
|
||||
} // Referee
|
||||
|
||||
@ -199,7 +199,7 @@ Referee::Referee(const AbstractKart &kart)
|
||||
m_scene_node->grab();
|
||||
m_scene_node->setScale(m_st_scale.toIrrVector());
|
||||
m_scene_node->setPosition(core::vector3df(0, kart.getKartHeight() + 0.4f, 0));
|
||||
m_scene_node->setFrameLoop(m_st_first_rescue_frame,
|
||||
m_scene_node->setFrameLoop(m_st_first_rescue_frame,
|
||||
m_st_last_rescue_frame);
|
||||
} // Referee
|
||||
|
||||
@ -244,7 +244,7 @@ void Referee::selectReadySetGo(int rsg)
|
||||
if(m_st_traffic_buffer<0) return;
|
||||
video::SMaterial &m = m_scene_node->getMesh()->getMeshBuffer(m_st_traffic_buffer)->getMaterial();
|
||||
m.setTexture(0, m_st_traffic_lights[rsg]);
|
||||
|
||||
|
||||
// disable lighting, we need to see the traffic light even if facing away
|
||||
// from the sun
|
||||
m.AmbientColor = video::SColor(255, 255, 255, 255);
|
||||
|
@ -46,7 +46,7 @@ Shadow::Shadow(video::ITexture *texture, scene::ISceneNode *node, float scale =
|
||||
v[2].Normal = normal;
|
||||
v[3].Normal = normal;
|
||||
buffer->recalculateBoundingBox();
|
||||
|
||||
|
||||
m_node = irr_driver->addMesh(m_mesh);
|
||||
#ifdef DEBUG
|
||||
m_node->setName("shadow");
|
||||
|
@ -27,8 +27,8 @@
|
||||
|
||||
/** ShowCurve constructor. It just creates an empty scene node.
|
||||
*/
|
||||
ShowCurve::ShowCurve(float width, float height,
|
||||
const irr::video::SColor &color)
|
||||
ShowCurve::ShowCurve(float width, float height,
|
||||
const irr::video::SColor &color)
|
||||
: m_width(width), m_height(height)
|
||||
{
|
||||
m_color = color;
|
||||
@ -61,7 +61,7 @@ void ShowCurve::addEmptyMesh()
|
||||
m.DiffuseColor = m_color;
|
||||
m.EmissiveColor = m_color;
|
||||
m.BackfaceCulling = false;
|
||||
m_mesh = irr_driver->createQuadMesh(&m,
|
||||
m_mesh = irr_driver->createQuadMesh(&m,
|
||||
/*create_one_quad*/ false);
|
||||
m_buffer = m_mesh->getMeshBuffer(0);
|
||||
assert(m_buffer->getVertexType()==video::EVT_STANDARD);
|
||||
@ -119,7 +119,7 @@ void ShowCurve::addPoint(const Vec3 &pnt)
|
||||
indices = m_buffer->getIndices();
|
||||
|
||||
// index = first newly added index
|
||||
unsigned int index = m_buffer->getIndexCount()-24;
|
||||
unsigned int index = m_buffer->getIndexCount()-24;
|
||||
for(unsigned int i=0; i<4; i++)
|
||||
{
|
||||
indices[index ] = n-4 + i;
|
||||
|
@ -72,11 +72,11 @@ void SkidMarks::reset()
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Either adds to an existing skid mark quad, or (if the kart is skidding)
|
||||
/** Either adds to an existing skid mark quad, or (if the kart is skidding)
|
||||
* starts a new skid mark quad.
|
||||
* \param dt Time step.
|
||||
*/
|
||||
void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
video::SColor* custom_color)
|
||||
{
|
||||
//if the kart is gnu, then don't skid because he floats!
|
||||
@ -96,7 +96,7 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
m_kart.getVehicle()->getWheelInfo(2).m_raycastInfo;
|
||||
const btWheelInfo::RaycastInfo raycast_left =
|
||||
m_kart.getVehicle()->getWheelInfo(3).m_raycastInfo;
|
||||
Vec3 delta = raycast_right.m_contactPointWS
|
||||
Vec3 delta = raycast_right.m_contactPointWS
|
||||
- raycast_left.m_contactPointWS;
|
||||
|
||||
// The kart is making skid marks when it's:
|
||||
@ -105,7 +105,7 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
// - not doing the grphical jump
|
||||
// - wheels are in contact with floor, which includes a special case:
|
||||
// the physics force both wheels on one axis to touch the ground or not.
|
||||
// If only one wheel touches the ground, the 2nd one gets the same
|
||||
// If only one wheel touches the ground, the 2nd one gets the same
|
||||
// raycast result --> delta is 0, which is considered to be not skidding.
|
||||
const Skidding *skid = m_kart.getSkidding();
|
||||
bool is_skidding = force_skid_marks ||
|
||||
@ -114,13 +114,13 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
&& m_kart.getSkidding()->getGraphicalJumpOffset()<=0
|
||||
&& raycast_right.m_isInContact
|
||||
&& delta.length2()>=0.0001f );
|
||||
|
||||
|
||||
if(m_skid_marking)
|
||||
{
|
||||
if (!is_skidding) // end skid marking
|
||||
{
|
||||
m_skid_marking = false;
|
||||
// The vertices and indices will not change anymore
|
||||
// The vertices and indices will not change anymore
|
||||
// (till these skid mark quads are deleted)
|
||||
m_left[m_current]->setHardwareMappingHint(scene::EHM_STATIC);
|
||||
m_right[m_current]->setHardwareMappingHint(scene::EHM_STATIC);
|
||||
@ -160,14 +160,14 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
delta.normalize();
|
||||
delta *= m_width;
|
||||
|
||||
SkidMarkQuads *smq_left =
|
||||
SkidMarkQuads *smq_left =
|
||||
new SkidMarkQuads(raycast_left.m_contactPointWS,
|
||||
raycast_left.m_contactPointWS + delta,
|
||||
m_material, m_avoid_z_fighting, custom_color);
|
||||
scene::SMesh *new_mesh = new scene::SMesh();
|
||||
new_mesh->addMeshBuffer(smq_left);
|
||||
|
||||
SkidMarkQuads *smq_right =
|
||||
SkidMarkQuads *smq_right =
|
||||
new SkidMarkQuads(raycast_right.m_contactPointWS - delta,
|
||||
raycast_right.m_contactPointWS,
|
||||
m_material, m_avoid_z_fighting, custom_color);
|
||||
@ -214,7 +214,7 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
//=============================================================================
|
||||
SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
|
||||
const Vec3 &right,
|
||||
video::SMaterial *material,
|
||||
video::SMaterial *material,
|
||||
float z_offset,
|
||||
video::SColor* custom_color)
|
||||
: scene::SMeshBuffer()
|
||||
@ -227,11 +227,11 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
|
||||
SkidMarks::m_start_grey,
|
||||
SkidMarks::m_start_grey,
|
||||
SkidMarks::m_start_grey));
|
||||
|
||||
|
||||
Material = *material;
|
||||
m_aabb = core::aabbox3df(left.toIrrVector());
|
||||
add(left, right);
|
||||
|
||||
|
||||
|
||||
} // SkidMarkQuads
|
||||
|
||||
@ -272,12 +272,12 @@ void SkidMarks::SkidMarkQuads::add(const Vec3 &left,
|
||||
m_aabb.addInternalPoint(left.toIrrVector() );
|
||||
m_aabb.addInternalPoint(right.toIrrVector());
|
||||
setBoundingBox(m_aabb);
|
||||
|
||||
|
||||
setDirty();
|
||||
} // add
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Fades the current skid marks.
|
||||
/** Fades the current skid marks.
|
||||
* \param f fade factor.
|
||||
*/
|
||||
void SkidMarks::SkidMarkQuads::fade(float f)
|
||||
@ -306,5 +306,5 @@ void SkidMarks::SkidMarkQuads::fade(float f)
|
||||
*/
|
||||
void SkidMarks::adjustFog(bool enabled)
|
||||
{
|
||||
m_material->FogEnable = enabled;
|
||||
m_material->FogEnable = enabled;
|
||||
}
|
||||
|
@ -50,18 +50,18 @@ SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
|
||||
m.setFlag(video::EMF_COLOR_MATERIAL, true);
|
||||
|
||||
m.ColorMaterial = video::ECM_DIFFUSE_AND_AMBIENT;
|
||||
|
||||
|
||||
m.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
|
||||
|
||||
createMesh(m);
|
||||
m_node = irr_driver->addMesh(m_mesh);
|
||||
m_mesh->drop();
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
std::string debug_name = m_kart->getIdent()+" (slip-stream)";
|
||||
m_node->setName(debug_name.c_str());
|
||||
#endif
|
||||
m_node->setPosition(core::vector3df(0,
|
||||
m_node->setPosition(core::vector3df(0,
|
||||
0*0.25f+2.5,
|
||||
m_kart->getKartLength()) );
|
||||
m_node->setVisible(false);
|
||||
@ -90,7 +90,7 @@ SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
|
||||
m_debug_mesh = irr_driver->createQuadMesh(&material, true);
|
||||
scene::IMeshBuffer *buffer = m_debug_mesh->getMeshBuffer(0);
|
||||
assert(buffer->getVertexType()==video::EVT_STANDARD);
|
||||
irr::video::S3DVertex* vertices
|
||||
irr::video::S3DVertex* vertices
|
||||
= (video::S3DVertex*)buffer->getVertices();
|
||||
video::SColor red(128, 255, 0, 0);
|
||||
for(unsigned int i=0; i<4; i++)
|
||||
@ -152,7 +152,7 @@ void SlipStream::createMesh(const video::SMaterial &material)
|
||||
float radius[] = {1.5f, 1.0f, 0.5f, 0.0f};
|
||||
|
||||
// The distance of each of the circle from the kart. The number of
|
||||
// entries in this array must be the same as the number of non-zero
|
||||
// entries in this array must be the same as the number of non-zero
|
||||
// entries in the radius[] array above. No 'end of list' entry required.
|
||||
// Note also that in order to avoid a 'bent' in the texture the
|
||||
// difference between the distances must be linearly correlated to the
|
||||
@ -172,7 +172,7 @@ void SlipStream::createMesh(const video::SMaterial &material)
|
||||
// The alpha values for the rings, no 'end of list' entry required.
|
||||
int alphas[] = {0, 255, 0};
|
||||
|
||||
// Loop through all given radius to determine the number
|
||||
// Loop through all given radius to determine the number
|
||||
// of segments to create.
|
||||
unsigned int num_circles=0;
|
||||
while(radius[num_circles]>0.0f) num_circles++;
|
||||
@ -234,7 +234,7 @@ void SlipStream::createMesh(const video::SMaterial &material)
|
||||
buffer->drop();
|
||||
m_mesh = mesh;
|
||||
} // createMesh
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the animation intensity (or speed).
|
||||
* \param f Intensity: 0 = no slip stream,
|
||||
@ -254,7 +254,7 @@ void SlipStream::setIntensity(float f, const AbstractKart *kart)
|
||||
core::vector3df my_pos = m_kart->getNode()->getPosition();
|
||||
my_pos.Y = m_kart->getHoT()+above_terrain;
|
||||
m_node->setPosition(my_pos);
|
||||
|
||||
|
||||
core::vector3df other_pos = kart->getNode()->getPosition();
|
||||
other_pos.Y = kart->getHoT()+above_terrain;
|
||||
core::vector3df diff = other_pos - my_pos;
|
||||
@ -266,11 +266,11 @@ void SlipStream::setIntensity(float f, const AbstractKart *kart)
|
||||
// For real testing in game: this needs some tuning!
|
||||
m_node->setVisible(f!=0);
|
||||
MovingTexture::setSpeed(f, 0);
|
||||
|
||||
|
||||
|
||||
int c = (int)(f*255);
|
||||
if (c > 255) c = 255;
|
||||
|
||||
|
||||
const unsigned int bcount = m_node->getMesh()->getMeshBufferCount();
|
||||
for (unsigned int b=0; b<bcount; b++)
|
||||
{
|
||||
@ -302,7 +302,7 @@ bool SlipStream::isSlipstreamReady() const
|
||||
} // isSlipstreamReady
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the additional force being applied to the kart because of
|
||||
/** Returns the additional force being applied to the kart because of
|
||||
* slipstreaming.
|
||||
*/
|
||||
void SlipStream::updateSlipstreamPower()
|
||||
@ -333,7 +333,7 @@ void SlipStream::setDebugColor(const video::SColor &color)
|
||||
{
|
||||
if(!UserConfigParams::m_slipstream_debug) return;
|
||||
scene::IMeshBuffer *buffer = m_debug_mesh->getMeshBuffer(0);
|
||||
irr::video::S3DVertex* vertices =
|
||||
irr::video::S3DVertex* vertices =
|
||||
(video::S3DVertex*)buffer->getVertices();
|
||||
for(unsigned int i=0; i<4; i++)
|
||||
vertices[i].Color=color;
|
||||
@ -352,9 +352,9 @@ void SlipStream::update(float dt)
|
||||
MovingTexture::update(dt);
|
||||
|
||||
// Update this karts slipstream quad (even for low level AI which don't
|
||||
// use slipstream, since even then player karts can get slipstream,
|
||||
// use slipstream, since even then player karts can get slipstream,
|
||||
// and so have to compare with the modified slipstream quad.
|
||||
m_slipstream_original_quad->transform(m_kart->getTrans(),
|
||||
m_slipstream_original_quad->transform(m_kart->getTrans(),
|
||||
m_slipstream_quad);
|
||||
|
||||
if(m_slipstream_mode==SS_USE)
|
||||
@ -396,24 +396,24 @@ void SlipStream::update(float dt)
|
||||
m_target_kart= world->getKart(i);
|
||||
// Don't test for slipstream with itself, a kart that is being
|
||||
// rescued or exploding, or an eliminated kart
|
||||
if(m_target_kart==m_kart ||
|
||||
if(m_target_kart==m_kart ||
|
||||
m_target_kart->getKartAnimation() ||
|
||||
m_target_kart->isEliminated() ) continue;
|
||||
|
||||
float diff = fabsf(m_target_kart->getXYZ().getY()
|
||||
float diff = fabsf(m_target_kart->getXYZ().getY()
|
||||
- m_kart->getXYZ().getY() );
|
||||
// If the kart is 'on top' of this kart (e.g. up on a bridge),
|
||||
// don't consider it for slipstreaming.
|
||||
|
||||
if(diff>6.0f) continue;
|
||||
// If the kart we are testing against is too slow, no need to test
|
||||
// slipstreaming. Note: We compare the speed of the other kart
|
||||
// against the minimum slipstream speed kart of this kart - not
|
||||
// entirely sure if this makes sense, but it makes it easier to
|
||||
// slipstreaming. Note: We compare the speed of the other kart
|
||||
// against the minimum slipstream speed kart of this kart - not
|
||||
// entirely sure if this makes sense, but it makes it easier to
|
||||
// give karts different slipstream properties.
|
||||
#ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
|
||||
if(m_target_kart->getSpeed() <
|
||||
m_kart->getKartProperties()->getSlipstreamMinSpeed())
|
||||
m_kart->getKartProperties()->getSlipstreamMinSpeed())
|
||||
{
|
||||
if(UserConfigParams::m_slipstream_debug &&
|
||||
m_kart->getController()->isPlayerController())
|
||||
@ -427,10 +427,10 @@ void SlipStream::update(float dt)
|
||||
// slipstream length+0.5*kart_length()+0.5*target_kart_length
|
||||
// away from the other kart
|
||||
Vec3 delta = m_kart->getXYZ() - m_target_kart->getXYZ();
|
||||
float l = m_target_kart->getKartProperties()->getSlipstreamLength()
|
||||
float l = m_target_kart->getKartProperties()->getSlipstreamLength()
|
||||
+ 0.5f*( m_target_kart->getKartLength()
|
||||
+m_kart->getKartLength() );
|
||||
if(delta.length2_2d() > l*l)
|
||||
if(delta.length2_2d() > l*l)
|
||||
{
|
||||
if(UserConfigParams::m_slipstream_debug &&
|
||||
m_kart->getController()->isPlayerController())
|
||||
@ -458,16 +458,16 @@ void SlipStream::update(float dt)
|
||||
m_target_kart->getSlipstream()
|
||||
->setDebugColor(video::SColor(255, 255, 0, 0));
|
||||
|
||||
if(isSlipstreamReady())
|
||||
if(isSlipstreamReady())
|
||||
{
|
||||
// The first time slipstream is ready after collecting
|
||||
// and you are leaving the slipstream area, you get a
|
||||
// zipper bonus.
|
||||
// zipper bonus.
|
||||
if(m_slipstream_mode==SS_COLLECT)
|
||||
{
|
||||
m_slipstream_mode = SS_USE;
|
||||
m_kart->handleZipper();
|
||||
m_slipstream_time =
|
||||
m_slipstream_time =
|
||||
m_kart->getKartProperties()->getSlipstreamCollectTime();
|
||||
return;
|
||||
}
|
||||
@ -482,7 +482,7 @@ void SlipStream::update(float dt)
|
||||
m_kart->getController()->isPlayerController())
|
||||
m_target_kart->getSlipstream()->setDebugColor(video::SColor(255, 0, 255, 0));
|
||||
// Accumulate slipstream credits now
|
||||
m_slipstream_time = m_slipstream_mode==SS_NONE ? dt
|
||||
m_slipstream_time = m_slipstream_mode==SS_NONE ? dt
|
||||
: m_slipstream_time+dt;
|
||||
if(isSlipstreamReady())
|
||||
m_kart->setSlipstreamEffect(9.0f);
|
||||
|
@ -36,14 +36,14 @@ Stars::Stars(scene::ISceneNode* parentKart, core::vector3df center)
|
||||
m_enabled = false;
|
||||
|
||||
video::ITexture* texture = irr_driver->getTexture("starparticle.png");
|
||||
Material* star_material =
|
||||
Material* star_material =
|
||||
material_manager->getMaterial("starparticle.png");
|
||||
|
||||
|
||||
m_center = center;
|
||||
|
||||
|
||||
for (int n=0; n<STAR_AMOUNT; n++)
|
||||
{
|
||||
scene::ISceneNode* billboard =
|
||||
scene::ISceneNode* billboard =
|
||||
irr_driver->addBillboard(core::dimension2df(STAR_SIZE, STAR_SIZE),
|
||||
texture, parentKart);
|
||||
#ifdef DEBUG
|
||||
@ -51,9 +51,9 @@ Stars::Stars(scene::ISceneNode* parentKart, core::vector3df center)
|
||||
#endif
|
||||
star_material->setMaterialProperties(&(billboard->getMaterial(0)), NULL);
|
||||
billboard->setMaterialTexture(0, star_material->getTexture());
|
||||
|
||||
|
||||
billboard->setVisible(false);
|
||||
|
||||
|
||||
m_nodes.push_back(billboard);
|
||||
}
|
||||
} // Stars
|
||||
@ -76,7 +76,7 @@ void Stars::showFor(float time)
|
||||
m_enabled = true;
|
||||
m_remaining_time = time;
|
||||
m_fade_in_time = 1.0f;
|
||||
|
||||
|
||||
const int nodeAmount = m_nodes.size();
|
||||
for (int n=0; n<nodeAmount; n++)
|
||||
{
|
||||
@ -84,7 +84,7 @@ void Stars::showFor(float time)
|
||||
((scene::IBillboardSceneNode*)m_nodes[n])
|
||||
->setSize( core::dimension2df(0.01f, 0.01f) );
|
||||
}
|
||||
|
||||
|
||||
// set stars initial position
|
||||
update(0);
|
||||
} // showFor
|
||||
@ -103,12 +103,12 @@ void Stars::reset()
|
||||
void Stars::update(float delta_t)
|
||||
{
|
||||
if (!m_enabled) return;
|
||||
|
||||
|
||||
m_remaining_time -= delta_t;
|
||||
if (m_remaining_time < 0)
|
||||
{
|
||||
m_enabled = false;
|
||||
|
||||
|
||||
const int nodeAmount = m_nodes.size();
|
||||
for (int n=0; n<nodeAmount; n++)
|
||||
{
|
||||
@ -116,52 +116,52 @@ void Stars::update(float delta_t)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const int nodeAmount = m_nodes.size();
|
||||
for (int n=0; n<nodeAmount; n++)
|
||||
{
|
||||
// do one full rotation every 4 seconds (this "ranges" ranges
|
||||
// do one full rotation every 4 seconds (this "ranges" ranges
|
||||
// from 0 to 1)
|
||||
float angle = (m_remaining_time / 4.0f) - (int)(m_remaining_time / 4);
|
||||
|
||||
|
||||
// each star must be at a different angle
|
||||
angle += n * (1.0f / STAR_AMOUNT);
|
||||
|
||||
|
||||
// keep angle in range [0, 1[
|
||||
angle -= (int)angle;
|
||||
|
||||
|
||||
float radius = RADIUS;
|
||||
|
||||
|
||||
|
||||
// manage "fade-in"
|
||||
if (m_fade_in_time > 0.0f)
|
||||
{
|
||||
float fade = (1.0f - m_fade_in_time);
|
||||
|
||||
|
||||
((scene::IBillboardSceneNode*)m_nodes[n])->setSize(
|
||||
core::dimension2d< f32 >(fade*STAR_SIZE, fade*STAR_SIZE) );
|
||||
|
||||
|
||||
radius *= fade;
|
||||
}
|
||||
// manage "fade-out"
|
||||
else if (m_remaining_time < 1.0f)
|
||||
{
|
||||
radius *= m_remaining_time;
|
||||
|
||||
|
||||
((scene::IBillboardSceneNode*)m_nodes[n])
|
||||
->setSize( core::dimension2df(m_remaining_time*STAR_SIZE,
|
||||
m_remaining_time*STAR_SIZE) );
|
||||
}
|
||||
|
||||
|
||||
// Set position: X and Z are the position in the cirlce,
|
||||
// the Y components shakes the stars up and down like falling coin
|
||||
core::vector3df offset(std::cos(angle*M_PI*2.0f)*radius,
|
||||
core::vector3df offset(std::cos(angle*M_PI*2.0f)*radius,
|
||||
std::cos(angle*M_PI*2.0f+m_remaining_time*4.0f)
|
||||
*radius*0.25f,
|
||||
std::sin(angle*M_PI*2.0f)*radius );
|
||||
m_nodes[n]->setPosition(m_center + offset);
|
||||
} // end for
|
||||
|
||||
|
||||
if (m_fade_in_time > 0.0f) m_fade_in_time -= delta_t;
|
||||
} // update
|
||||
|
||||
|
@ -19,13 +19,13 @@ STKModifiedSpriteBank::STKModifiedSpriteBank(IGUIEnvironment* env) :
|
||||
Environment(env), Driver(0)
|
||||
{
|
||||
m_magic_number = 0xCAFEC001;
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("STKModifiedSpriteBank");
|
||||
#endif
|
||||
|
||||
m_scale = 1.0f;
|
||||
|
||||
|
||||
if (Environment)
|
||||
{
|
||||
Driver = Environment->getVideoDriver();
|
||||
@ -45,7 +45,7 @@ STKModifiedSpriteBank::~STKModifiedSpriteBank()
|
||||
// drop video driver
|
||||
if (Driver)
|
||||
Driver->drop();
|
||||
|
||||
|
||||
m_magic_number = 0xDEADBEEF;
|
||||
} // ~STKModifiedSpriteBank
|
||||
|
||||
@ -54,9 +54,9 @@ core::array< core::rect<s32> >& STKModifiedSpriteBank::getPositions()
|
||||
{
|
||||
assert( m_magic_number == 0xCAFEC001 );
|
||||
copy.clear();
|
||||
|
||||
|
||||
//FIXME: terribly unefficient, CGUIListBox will call this once for every
|
||||
// item xD but I have no choice, short of re-implementing
|
||||
// item xD but I have no choice, short of re-implementing
|
||||
// IGUIListBox too
|
||||
|
||||
for (int n=0; n<(int)Rectangles.size(); n++)
|
||||
@ -67,7 +67,7 @@ core::array< core::rect<s32> >& STKModifiedSpriteBank::getPositions()
|
||||
core::dimension2d<s32>(w,h) )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return copy;
|
||||
} // getPositions
|
||||
|
||||
@ -148,7 +148,7 @@ s32 STKModifiedSpriteBank::addTextureAsSprite(video::ITexture* texture)
|
||||
u32 textureIndex = getTextureCount() - 1;
|
||||
|
||||
u32 rectangleIndex = Rectangles.size();
|
||||
Rectangles.push_back( core::rect<s32>(0,0,
|
||||
Rectangles.push_back( core::rect<s32>(0,0,
|
||||
texture->getOriginalSize().Width,
|
||||
texture->getOriginalSize().Height) );
|
||||
|
||||
@ -167,7 +167,7 @@ s32 STKModifiedSpriteBank::addTextureAsSprite(video::ITexture* texture)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//! draws a sprite in 2d with scale and color
|
||||
void STKModifiedSpriteBank::draw2DSprite(u32 index,
|
||||
void STKModifiedSpriteBank::draw2DSprite(u32 index,
|
||||
const core::position2di& pos,
|
||||
const core::rect<s32>* clip, const video::SColor& color,
|
||||
u32 starttime, u32 currenttime, bool loop, bool center)
|
||||
@ -184,11 +184,11 @@ void STKModifiedSpriteBank::draw2DSprite(u32 index,
|
||||
if (loop)
|
||||
frame = f % Sprites[index].Frames.size();
|
||||
else
|
||||
frame = (f >= Sprites[index].Frames.size())
|
||||
frame = (f >= Sprites[index].Frames.size())
|
||||
? Sprites[index].Frames.size()-1 : f;
|
||||
}
|
||||
|
||||
const video::ITexture* tex =
|
||||
const video::ITexture* tex =
|
||||
Textures[Sprites[index].Frames[frame].textureNumber];
|
||||
if (!tex)
|
||||
return;
|
||||
@ -200,24 +200,24 @@ void STKModifiedSpriteBank::draw2DSprite(u32 index,
|
||||
const core::rect<s32>& r = Rectangles[rn];
|
||||
|
||||
const core::dimension2d<s32>& dim = r.getSize();
|
||||
|
||||
core::rect<s32> dest( pos,
|
||||
core::dimension2d<s32>((int)(dim.Width*m_scale),
|
||||
|
||||
core::rect<s32> dest( pos,
|
||||
core::dimension2d<s32>((int)(dim.Width*m_scale),
|
||||
(int)(dim.Height*m_scale)) );
|
||||
if (center)
|
||||
{
|
||||
dest -= dest.getSize() / 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
draw2DImage (const video::ITexture *texture,
|
||||
draw2DImage (const video::ITexture *texture,
|
||||
const core::rect< s32 > &destRect,
|
||||
const core::rect< s32 > &sourceRect,
|
||||
const core::rect< s32 > &sourceRect,
|
||||
const core::rect< s32 > *clipRect=0,
|
||||
const video::SColor *const colors=0,
|
||||
bool useAlphaChannelOfTexture=false)=0
|
||||
*/
|
||||
Driver->draw2DImage(tex, dest, r /* source rect */, clip,
|
||||
Driver->draw2DImage(tex, dest, r /* source rect */, clip,
|
||||
NULL /* colors */, true);
|
||||
|
||||
} // draw2DSprite
|
||||
@ -287,7 +287,7 @@ void STKModifiedSpriteBank::draw2DSpriteBatch(const core::array<u32>& indices,
|
||||
|
||||
for(u32 i = 0;i < drawBatches.size();i++)
|
||||
{
|
||||
if(!drawBatches[i].positions.empty() &&
|
||||
if(!drawBatches[i].positions.empty() &&
|
||||
!drawBatches[i].sourceRects.empty())
|
||||
Driver->draw2DImageBatch(Textures[i], drawBatches[i].positions,
|
||||
drawBatches[i].sourceRects, clip, color, true);
|
||||
|
@ -31,7 +31,7 @@ class STKModifiedSpriteBank : public IGUISpriteBank
|
||||
public:
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
|
||||
STKModifiedSpriteBank(IGUIEnvironment* env);
|
||||
virtual ~STKModifiedSpriteBank();
|
||||
|
||||
@ -66,14 +66,14 @@ public:
|
||||
assert( m_magic_number == 0xCAFEC001 );
|
||||
m_scale = scale;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// this object was getting access after being freed, I wanna see when/why
|
||||
unsigned int m_magic_number;
|
||||
|
||||
|
||||
float m_scale;
|
||||
|
||||
|
||||
struct SDrawBatch
|
||||
{
|
||||
core::array<core::position2di> positions;
|
||||
|
@ -47,7 +47,7 @@ void AbstractStateManager::enterGameState()
|
||||
{
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
|
||||
|
||||
if (getCurrentScreen() != NULL) getCurrentScreen()->tearDown();
|
||||
m_menu_stack.clear();
|
||||
m_menu_stack.push_back(RACE_STATE_NAME);
|
||||
@ -67,9 +67,9 @@ GameState AbstractStateManager::getGameState()
|
||||
void AbstractStateManager::setGameState(GameState state)
|
||||
{
|
||||
if (m_game_mode == state) return; // no change
|
||||
|
||||
|
||||
m_game_mode = state;
|
||||
|
||||
|
||||
onGameStateChange(state);
|
||||
} // setGameState
|
||||
|
||||
@ -85,20 +85,20 @@ void AbstractStateManager::pushMenu(std::string name)
|
||||
{
|
||||
// currently, only a single in-game menu is supported
|
||||
assert(m_game_mode != INGAME_MENU);
|
||||
|
||||
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
|
||||
|
||||
if (UserConfigParams::logGUI())
|
||||
{
|
||||
std::cout << "[AbstractStateManager::pushMenu] switching to screen "
|
||||
<< name.c_str() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// Send tear-down event to previous menu
|
||||
if (m_menu_stack.size() > 0 && m_game_mode != GAME)
|
||||
if (m_menu_stack.size() > 0 && m_game_mode != GAME)
|
||||
getCurrentScreen()->tearDown();
|
||||
|
||||
|
||||
m_menu_stack.push_back(name);
|
||||
if (m_game_mode == GAME)
|
||||
{
|
||||
@ -109,7 +109,7 @@ void AbstractStateManager::pushMenu(std::string name)
|
||||
setGameState(MENU);
|
||||
}
|
||||
switchToScreen(name.c_str());
|
||||
|
||||
|
||||
onTopMostScreenChanged();
|
||||
} // pushMenu
|
||||
|
||||
@ -120,17 +120,17 @@ void AbstractStateManager::pushScreen(Screen* screen)
|
||||
{
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
|
||||
|
||||
if (UserConfigParams::logGUI())
|
||||
{
|
||||
std::cout << "[AbstractStateManager::pushScreen] switching to screen "
|
||||
<< screen->getName().c_str() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
if (!screen->isLoaded()) screen->loadFromFile();
|
||||
pushMenu(screen->getName());
|
||||
screen->init();
|
||||
|
||||
|
||||
onTopMostScreenChanged();
|
||||
} // pushScreen
|
||||
|
||||
@ -144,24 +144,24 @@ void AbstractStateManager::replaceTopMostScreen(Screen* screen)
|
||||
|
||||
if (!screen->isLoaded()) screen->loadFromFile();
|
||||
std::string name = screen->getName();
|
||||
|
||||
|
||||
if (UserConfigParams::logGUI())
|
||||
{
|
||||
std::cout << "[AbstractStateManager::replaceTopmostScreen] "
|
||||
"switching to screen " << name.c_str() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
assert(m_menu_stack.size() > 0);
|
||||
|
||||
|
||||
// Send tear-down event to previous menu
|
||||
getCurrentScreen()->tearDown();
|
||||
|
||||
|
||||
m_menu_stack[m_menu_stack.size()-1] = name;
|
||||
switchToScreen(name.c_str());
|
||||
|
||||
|
||||
// Send init event to new menu
|
||||
getCurrentScreen()->init();
|
||||
|
||||
|
||||
onTopMostScreenChanged();
|
||||
} // replaceTopMostScreen
|
||||
|
||||
@ -172,21 +172,21 @@ void AbstractStateManager::reshowTopMostMenu()
|
||||
assert(m_game_mode != GAME);
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
|
||||
|
||||
// Send tear-down event to previous menu
|
||||
if (m_menu_stack.size() > 0)
|
||||
if (m_menu_stack.size() > 0)
|
||||
{
|
||||
Screen* currScreen = getCurrentScreen();
|
||||
if (currScreen != NULL) getCurrentScreen()->tearDown();
|
||||
}
|
||||
|
||||
|
||||
switchToScreen( m_menu_stack[m_menu_stack.size()-1].c_str() );
|
||||
|
||||
|
||||
// Send init event to new menu
|
||||
Screen* screen = getCurrentScreen();
|
||||
if (!screen->isLoaded()) screen->loadFromFile();
|
||||
screen->init();
|
||||
|
||||
|
||||
onTopMostScreenChanged();
|
||||
} // reshowTopMostMenu
|
||||
|
||||
@ -195,23 +195,23 @@ void AbstractStateManager::reshowTopMostMenu()
|
||||
void AbstractStateManager::popMenu()
|
||||
{
|
||||
assert(m_game_mode != GAME);
|
||||
|
||||
|
||||
// Send tear-down event to menu
|
||||
getCurrentScreen()->tearDown();
|
||||
m_menu_stack.pop_back();
|
||||
|
||||
|
||||
if (m_menu_stack.size() == 0)
|
||||
{
|
||||
onStackEmptied();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (UserConfigParams::logGUI())
|
||||
{
|
||||
std::cout << "[AbstractStateManager::popMenu] switching to screen "
|
||||
<< m_menu_stack[m_menu_stack.size()-1].c_str() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
if (m_menu_stack[m_menu_stack.size()-1] == RACE_STATE_NAME)
|
||||
{
|
||||
setGameState(GAME);
|
||||
@ -221,12 +221,12 @@ void AbstractStateManager::popMenu()
|
||||
{
|
||||
setGameState(MENU);
|
||||
switchToScreen(m_menu_stack[m_menu_stack.size()-1].c_str());
|
||||
|
||||
|
||||
Screen* screen = getCurrentScreen();
|
||||
if (!screen->isLoaded()) screen->loadFromFile();
|
||||
screen->init();
|
||||
}
|
||||
|
||||
|
||||
onTopMostScreenChanged();
|
||||
} // popMenu
|
||||
|
||||
@ -236,25 +236,25 @@ void AbstractStateManager::resetAndGoToScreen(Screen* screen)
|
||||
{
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
|
||||
|
||||
std::string name = screen->getName();
|
||||
|
||||
|
||||
if (UserConfigParams::logGUI())
|
||||
{
|
||||
std::cout << "[AbstractStateManager::resetAndGoToScreen] "
|
||||
"switching to screen " << name.c_str() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
if (m_game_mode != GAME) getCurrentScreen()->tearDown();
|
||||
m_menu_stack.clear();
|
||||
|
||||
|
||||
if (!screen->isLoaded()) screen->loadFromFile();
|
||||
m_menu_stack.push_back(name);
|
||||
setGameState(MENU);
|
||||
|
||||
|
||||
switchToScreen(name.c_str());
|
||||
getCurrentScreen()->init();
|
||||
|
||||
|
||||
onTopMostScreenChanged();
|
||||
} // resetAndGoToScreen
|
||||
|
||||
@ -266,20 +266,20 @@ void AbstractStateManager::resetAndSetStack(Screen* screens[])
|
||||
assert(screens[0] != NULL);
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
|
||||
|
||||
if (m_game_mode != GAME) getCurrentScreen()->tearDown();
|
||||
m_menu_stack.clear();
|
||||
|
||||
|
||||
for (int n=0; screens[n] != NULL; n++)
|
||||
{
|
||||
m_menu_stack.push_back(screens[n]->getName());
|
||||
}
|
||||
|
||||
|
||||
setGameState(MENU);
|
||||
|
||||
|
||||
switchToScreen(m_menu_stack[m_menu_stack.size()-1].c_str());
|
||||
getCurrentScreen()->init();
|
||||
|
||||
|
||||
onTopMostScreenChanged();
|
||||
} // resetAndSetStack
|
||||
|
||||
|
@ -54,7 +54,7 @@ void AbstractTopLevelContainer::addWidgetsRecursively(
|
||||
Widget* parent)
|
||||
{
|
||||
const unsigned short widgets_amount = widgets.size();
|
||||
|
||||
|
||||
// ------- add widgets
|
||||
for (int n=0; n<widgets_amount; n++)
|
||||
{
|
||||
@ -72,25 +72,25 @@ void AbstractTopLevelContainer::addWidgetsRecursively(
|
||||
widgets[n].getType() != WTYPE_ICON_BUTTON &&
|
||||
widgets[n].getType() != WTYPE_SPACER)
|
||||
{
|
||||
std::cerr << "/!\\ Warning /!\\ : widget "
|
||||
std::cerr << "/!\\ Warning /!\\ : widget "
|
||||
<< widgets[n].m_properties[PROP_ID].c_str()
|
||||
<< " of type " << widgets[n].getType()
|
||||
<< " of type " << widgets[n].getType()
|
||||
<< " has no dimensions" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
if (widgets[n].m_x == -1 || widgets[n].m_y == -1)
|
||||
{
|
||||
std::cerr << "/!\\ Warning /!\\ : widget "
|
||||
std::cerr << "/!\\ Warning /!\\ : widget "
|
||||
<< widgets[n].m_properties[PROP_ID].c_str()
|
||||
<< " of type " << widgets[n].getType()
|
||||
<< " has no position" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
widgets[n].add();
|
||||
}
|
||||
|
||||
|
||||
} // for n in all widgets
|
||||
|
||||
|
||||
} // addWidgetsRecursively
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -102,12 +102,12 @@ void AbstractTopLevelContainer::addWidgetsRecursively(
|
||||
bool isMyChildHelperFunc(const PtrVector<Widget>* within, const Widget* widget)
|
||||
{
|
||||
if (within->size() == 0) return false;
|
||||
|
||||
|
||||
if (within->contains(widget))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const int count = within->size();
|
||||
for (int n=0; n<count; n++)
|
||||
{
|
||||
@ -116,7 +116,7 @@ bool isMyChildHelperFunc(const PtrVector<Widget>* within, const Widget* widget)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -156,24 +156,24 @@ Widget* AbstractTopLevelContainer::getWidget(const int id)
|
||||
* \param name The name of the widget to find
|
||||
* \param within_vector The vector of widgets to look in
|
||||
* \return The result of the search, or NULL if the object is not found */
|
||||
Widget* AbstractTopLevelContainer::getWidget(const char* name,
|
||||
Widget* AbstractTopLevelContainer::getWidget(const char* name,
|
||||
PtrVector<Widget>* within_vector)
|
||||
{
|
||||
const unsigned short widgets_amount = within_vector->size();
|
||||
|
||||
|
||||
for(int n=0; n<widgets_amount; n++)
|
||||
{
|
||||
Widget& widget = (*within_vector)[n];
|
||||
|
||||
|
||||
if (widget.m_properties[PROP_ID] == name) return &widget;
|
||||
|
||||
|
||||
if (widget.searchInsideMe() && widget.m_children.size() > 0)
|
||||
{
|
||||
Widget* el = getWidget(name, &(widget.m_children));
|
||||
if(el != NULL) return el;
|
||||
}
|
||||
} // for n in all widgets
|
||||
|
||||
|
||||
return NULL;
|
||||
} // getWidget
|
||||
|
||||
@ -183,29 +183,29 @@ Widget* AbstractTopLevelContainer::getWidget(const char* name,
|
||||
* \param id The irrlicht ID of the widget to find
|
||||
* \param within_vector The vector to look into
|
||||
* \return The result of the search, or NULL if the object is not found */
|
||||
Widget* AbstractTopLevelContainer::getWidget(const int id,
|
||||
Widget* AbstractTopLevelContainer::getWidget(const int id,
|
||||
PtrVector<Widget>* within_vector)
|
||||
{
|
||||
const unsigned short widgets_amount = within_vector->size();
|
||||
|
||||
|
||||
for (int n=0; n<widgets_amount; n++)
|
||||
{
|
||||
Widget& widget = (*within_vector)[n];
|
||||
|
||||
if (widget.m_element != NULL &&
|
||||
|
||||
if (widget.m_element != NULL &&
|
||||
widget.getIrrlichtElement()->getID() == id) return &widget;
|
||||
|
||||
|
||||
if (widget.searchInsideMe() && widget.getChildren().size() > 0)
|
||||
{
|
||||
// std::cout << "widget = <"
|
||||
// std::cout << "widget = <"
|
||||
// << widget.m_properties[PROP_ID].c_str()
|
||||
// << "> widget.m_children.size()="
|
||||
// << "> widget.m_children.size()="
|
||||
// << widget.m_children.size() << std::endl;
|
||||
Widget* el = getWidget(id, &(widget.m_children));
|
||||
if(el != NULL) return el;
|
||||
}
|
||||
} // for n in all widgets
|
||||
|
||||
|
||||
return NULL;
|
||||
} // getWidget
|
||||
|
||||
@ -219,12 +219,12 @@ Widget* AbstractTopLevelContainer::getFirstWidget(
|
||||
{
|
||||
if (m_first_widget != NULL) return m_first_widget;
|
||||
if (within_vector == NULL) within_vector = &m_widgets;
|
||||
|
||||
|
||||
for (int i = 0; i < within_vector->size(); i++)
|
||||
{
|
||||
if (!within_vector->get(i)->m_focusable) continue;
|
||||
|
||||
// if container, also checks children
|
||||
|
||||
// if container, also checks children
|
||||
// (FIXME: don't hardcode which types to avoid descending into)
|
||||
if (within_vector->get(i)->m_children.size() > 0 &&
|
||||
within_vector->get(i)->getType() != WTYPE_RIBBON &&
|
||||
@ -233,17 +233,17 @@ Widget* AbstractTopLevelContainer::getFirstWidget(
|
||||
Widget* w = getFirstWidget(&within_vector->get(i)->m_children);
|
||||
if (w != NULL) return w;
|
||||
}
|
||||
|
||||
|
||||
Widget* item = within_vector->get(i);
|
||||
if (item->getIrrlichtElement() == NULL ||
|
||||
item->getIrrlichtElement()->getTabOrder() == -1 ||
|
||||
/* non-tabbing items are given such IDs */
|
||||
/* non-tabbing items are given such IDs */
|
||||
item->getIrrlichtElement()->getTabOrder() >= 1000 ||
|
||||
!item->m_focusable)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
return item;
|
||||
} // for i in all widgets of within_vector
|
||||
return NULL;
|
||||
@ -259,11 +259,11 @@ Widget* AbstractTopLevelContainer::getLastWidget(
|
||||
{
|
||||
if (m_last_widget != NULL) return m_last_widget;
|
||||
if (within_vector == NULL) within_vector = &m_widgets;
|
||||
|
||||
|
||||
for (int i = within_vector->size()-1; i >= 0; i--)
|
||||
{
|
||||
if (!within_vector->get(i)->m_focusable) continue;
|
||||
|
||||
|
||||
// if container, also checks children
|
||||
if (within_vector->get(i)->getChildren().size() > 0 &&
|
||||
within_vector->get(i)->getType() != WTYPE_RIBBON &&
|
||||
@ -272,10 +272,10 @@ Widget* AbstractTopLevelContainer::getLastWidget(
|
||||
Widget* w = getLastWidget(&within_vector->get(i)->m_children);
|
||||
if (w != NULL) return w;
|
||||
}
|
||||
|
||||
|
||||
Widget* item = within_vector->get(i);
|
||||
IGUIElement* elem = item->getIrrlichtElement();
|
||||
|
||||
|
||||
if (elem == NULL ||
|
||||
elem->getTabOrder() == -1 ||
|
||||
!Widget::isFocusableId(elem->getTabOrder()) ||
|
||||
@ -283,7 +283,7 @@ Widget* AbstractTopLevelContainer::getLastWidget(
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
return item;
|
||||
} // for i in all widgets of within_vector
|
||||
return NULL;
|
||||
@ -291,7 +291,7 @@ Widget* AbstractTopLevelContainer::getLastWidget(
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** This function is called when screen is removed. This means all irrlicht
|
||||
/** This function is called when screen is removed. This means all irrlicht
|
||||
* widgets this object has pointers to are now gone. All references are set
|
||||
* to NULL to avoid problems.
|
||||
* \param within_vector The vector of widgets to clear
|
||||
@ -300,13 +300,13 @@ void AbstractTopLevelContainer::elementsWereDeleted(PtrVector<Widget>* within_ve
|
||||
{
|
||||
if (within_vector == NULL) within_vector = &m_widgets;
|
||||
const unsigned short widgets_amount = within_vector->size();
|
||||
|
||||
|
||||
for (int n=0; n<widgets_amount; n++)
|
||||
{
|
||||
Widget& widget = (*within_vector)[n];
|
||||
|
||||
|
||||
widget.elementRemoved();
|
||||
|
||||
|
||||
if (widget.m_children.size() > 0)
|
||||
{
|
||||
elementsWereDeleted( &(widget.m_children) );
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -189,7 +189,7 @@ bool EventHandler::OnEvent (const SEvent &event)
|
||||
#else
|
||||
return true; // EVENT_BLOCK
|
||||
#endif
|
||||
|
||||
|
||||
if (event.LogEvent.Level == irr::ELL_WARNING)
|
||||
{
|
||||
printf("[Irrlicht Warning] %s\n", event.LogEvent.Text);
|
||||
@ -201,8 +201,8 @@ bool EventHandler::OnEvent (const SEvent &event)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// nothing to do with other events
|
||||
return false;
|
||||
}
|
||||
@ -222,11 +222,11 @@ void EventHandler::processGUIAction(const PlayerAction action,
|
||||
type, playerID);
|
||||
if (propg == EVENT_BLOCK) return;
|
||||
}
|
||||
|
||||
|
||||
const bool pressedDown = value > Input::MAX_VALUE*2/3;
|
||||
|
||||
|
||||
if (!pressedDown && type == Input::IT_STICKMOTION) return;
|
||||
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PA_STEER_LEFT:
|
||||
@ -234,9 +234,9 @@ void EventHandler::processGUIAction(const PlayerAction action,
|
||||
{
|
||||
Widget* w = GUIEngine::getFocusForPlayer(playerID);
|
||||
if (w == NULL) break;
|
||||
|
||||
|
||||
Widget* widget_to_call = w;
|
||||
|
||||
|
||||
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
|
||||
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
|
||||
notified of clicks onto themselves so they can toggle their state. )
|
||||
@ -249,21 +249,21 @@ void EventHandler::processGUIAction(const PlayerAction action,
|
||||
}
|
||||
widget_to_call = widget_to_call->m_event_handler;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (widget_to_call->leftPressed(playerID) == EVENT_LET)
|
||||
{
|
||||
sendEventToUser(widget_to_call, widget_to_call->m_properties[PROP_ID], playerID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case PA_STEER_RIGHT:
|
||||
case PA_MENU_RIGHT:
|
||||
{
|
||||
Widget* w = GUIEngine::getFocusForPlayer(playerID);
|
||||
if (w == NULL) break;
|
||||
|
||||
|
||||
Widget* widget_to_call = w;
|
||||
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
|
||||
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
|
||||
@ -277,36 +277,36 @@ void EventHandler::processGUIAction(const PlayerAction action,
|
||||
}
|
||||
widget_to_call = widget_to_call->m_event_handler;
|
||||
}
|
||||
|
||||
|
||||
if (widget_to_call->rightPressed(playerID) == EVENT_LET)
|
||||
{
|
||||
sendEventToUser(widget_to_call, widget_to_call->m_properties[PROP_ID], playerID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case PA_ACCEL:
|
||||
case PA_MENU_UP:
|
||||
navigateUp(playerID, type, pressedDown);
|
||||
break;
|
||||
|
||||
|
||||
case PA_BRAKE:
|
||||
case PA_MENU_DOWN:
|
||||
navigateDown(playerID, type, pressedDown);
|
||||
break;
|
||||
|
||||
|
||||
case PA_RESCUE:
|
||||
case PA_MENU_CANCEL:
|
||||
if (pressedDown) GUIEngine::getStateManager()->escapePressed();
|
||||
break;
|
||||
|
||||
|
||||
case PA_FIRE:
|
||||
case PA_MENU_SELECT:
|
||||
if (pressedDown && !isWithinATextBox())
|
||||
{
|
||||
Widget* w = GUIEngine::getFocusForPlayer(playerID);
|
||||
if (w == NULL) break;
|
||||
|
||||
|
||||
// FIXME : consider returned value?
|
||||
onWidgetActivated( w, playerID );
|
||||
}
|
||||
@ -353,23 +353,23 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
|
||||
|
||||
if (type == Input::IT_STICKBUTTON && !pressedDown)
|
||||
return;
|
||||
|
||||
|
||||
Widget* w = GUIEngine::getFocusForPlayer(playerID);
|
||||
if (w != NULL)
|
||||
{
|
||||
el = w->getIrrlichtElement();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// list widgets are a bit special, because up/down keys are also used
|
||||
// to navigate between various list items, not only to navigate between
|
||||
// components
|
||||
if (w != NULL && w->m_type == WTYPE_LIST)
|
||||
{
|
||||
ListWidget* list = (ListWidget*)w;
|
||||
|
||||
|
||||
const bool stay_within_list = list->getSelectionID() > 0;
|
||||
|
||||
|
||||
if (stay_within_list)
|
||||
{
|
||||
list->setSelectionID(list->getSelectionID()-1);
|
||||
@ -380,14 +380,14 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
|
||||
list->setSelectionID(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (w != NULL && w->m_tab_up_root != -1)
|
||||
{
|
||||
Widget* up = GUIEngine::getWidget( w->m_tab_up_root );
|
||||
assert( up != NULL );
|
||||
|
||||
el = up->getIrrlichtElement();
|
||||
|
||||
|
||||
if (el == NULL)
|
||||
{
|
||||
std::cerr << "WARNING : m_tab_down_root is set to an ID for which I can't find the widget\n";
|
||||
@ -400,9 +400,9 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
|
||||
{
|
||||
el = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool found = false;
|
||||
|
||||
|
||||
// find closest widget
|
||||
if (el != NULL && el->getTabGroup() != NULL)
|
||||
{
|
||||
@ -410,50 +410,50 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
|
||||
for (int n=1; n<10 && !found; n++)
|
||||
{
|
||||
closest = GUIEngine::getGUIEnv()->getRootGUIElement()->getElementFromId(el->getTabOrder() - n, true);
|
||||
|
||||
|
||||
if (closest != NULL && Widget::isFocusableId(closest->getID()))
|
||||
{
|
||||
if (NAVIGATION_DEBUG) std::cout << "Navigating up to " << closest->getID() << std::endl;
|
||||
Widget* closestWidget = GUIEngine::getWidget( closest->getID() );
|
||||
|
||||
|
||||
if (playerID != PLAYER_ID_GAME_MASTER && !closestWidget->m_supports_multiplayer) return;
|
||||
|
||||
|
||||
// if a dialog is shown, restrict to items in the dialog
|
||||
if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyChild(closestWidget))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// when focusing a list by going up, select the last item of the list
|
||||
assert (closestWidget != NULL);
|
||||
|
||||
|
||||
closestWidget->setFocusForPlayer(playerID);
|
||||
|
||||
if (closestWidget->m_type == WTYPE_LIST)
|
||||
{
|
||||
IGUIListBox* list = (IGUIListBox*)(closestWidget->m_element);
|
||||
assert(list != NULL);
|
||||
|
||||
|
||||
list->setSelected( list->getItemCount()-1 );
|
||||
return;
|
||||
}
|
||||
found = true;
|
||||
|
||||
|
||||
}
|
||||
} // end for
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!found)
|
||||
{
|
||||
{
|
||||
if (NAVIGATION_DEBUG)
|
||||
{
|
||||
std::cout << "EventHandler::navigateUp : wrap around, selecting the last widget\n";
|
||||
}
|
||||
|
||||
|
||||
// select the last widget
|
||||
Widget* lastWidget = NULL;
|
||||
|
||||
|
||||
if (ModalDialog::isADialogActive())
|
||||
{
|
||||
lastWidget = ModalDialog::getCurrent()->getLastWidget();
|
||||
@ -464,7 +464,7 @@ void EventHandler::navigateUp(const int playerID, Input::InputType type, const b
|
||||
if (screen == NULL) return;
|
||||
lastWidget = screen->getLastWidget();
|
||||
}
|
||||
|
||||
|
||||
if (lastWidget != NULL) lastWidget->setFocusForPlayer(playerID);
|
||||
}
|
||||
}
|
||||
@ -479,23 +479,23 @@ void EventHandler::navigateDown(const int playerID, Input::InputType type, const
|
||||
|
||||
if (type == Input::IT_STICKBUTTON && !pressedDown)
|
||||
return;
|
||||
|
||||
|
||||
Widget* w = GUIEngine::getFocusForPlayer(playerID);
|
||||
if (w != NULL)
|
||||
{
|
||||
el = w->getIrrlichtElement();
|
||||
}
|
||||
//std::cout << "!!! Player " << playerID << " navigating down of " << w->m_element->getID() << std::endl;
|
||||
|
||||
|
||||
// list widgets are a bit special, because up/down keys are also used
|
||||
// to navigate between various list items, not only to navigate between
|
||||
// components
|
||||
if (w != NULL && w->m_type == WTYPE_LIST)
|
||||
{
|
||||
ListWidget* list = (ListWidget*)w;
|
||||
|
||||
|
||||
const bool stay_within_list = list->getSelectionID() < list->getItemCount()-1;
|
||||
|
||||
|
||||
if (stay_within_list)
|
||||
{
|
||||
list->setSelectionID(list->getSelectionID()+1);
|
||||
@ -506,13 +506,13 @@ void EventHandler::navigateDown(const int playerID, Input::InputType type, const
|
||||
list->setSelectionID(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (w != NULL && w->m_tab_down_root != -1)
|
||||
{
|
||||
Widget* down = GUIEngine::getWidget( w->m_tab_down_root );
|
||||
assert(down != NULL);
|
||||
el = down->getIrrlichtElement();
|
||||
|
||||
|
||||
if (el == NULL)
|
||||
{
|
||||
std::cerr << "WARNING : m_tab_down_root is set to an ID for which I can't find the widget\n";
|
||||
@ -525,36 +525,36 @@ void EventHandler::navigateDown(const int playerID, Input::InputType type, const
|
||||
{
|
||||
el = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool found = false;
|
||||
|
||||
|
||||
if (el != NULL && el->getTabGroup() != NULL)
|
||||
{
|
||||
// if the current widget is e.g. 5, search for widget 6, 7, 8, 9, ..., 15 (up to 10 IDs may be missing)
|
||||
for (int n=1; n<10 && !found; n++)
|
||||
{
|
||||
closest = GUIEngine::getGUIEnv()->getRootGUIElement()->getElementFromId(el->getTabOrder() + n, true);
|
||||
|
||||
|
||||
if (closest != NULL && Widget::isFocusableId(closest->getID()))
|
||||
{
|
||||
|
||||
|
||||
Widget* closestWidget = GUIEngine::getWidget( closest->getID() );
|
||||
if (playerID != PLAYER_ID_GAME_MASTER && !closestWidget->m_supports_multiplayer) return;
|
||||
|
||||
|
||||
// if a dialog is shown, restrict to items in the dialog
|
||||
if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyChild(closestWidget))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (NAVIGATION_DEBUG)
|
||||
{
|
||||
std::cout << "Navigating down to " << closestWidget->getID() << "\n";
|
||||
}
|
||||
|
||||
|
||||
assert( closestWidget != NULL );
|
||||
closestWidget->setFocusForPlayer(playerID);
|
||||
|
||||
|
||||
// another list exception : when entering a list, select the first item
|
||||
if (closestWidget->m_type == WTYPE_LIST)
|
||||
{
|
||||
@ -563,20 +563,20 @@ void EventHandler::navigateDown(const int playerID, Input::InputType type, const
|
||||
|
||||
list->setSelected(0);
|
||||
}
|
||||
|
||||
|
||||
found = true;
|
||||
}
|
||||
} // end for
|
||||
}
|
||||
|
||||
|
||||
if (!found)
|
||||
{
|
||||
|
||||
if (NAVIGATION_DEBUG) std::cout << "Navigating down : wrap around\n";
|
||||
|
||||
|
||||
// select the first widget
|
||||
Widget* firstWidget = NULL;
|
||||
|
||||
|
||||
if (ModalDialog::isADialogActive())
|
||||
{
|
||||
//std::cout << "w = ModalDialog::getCurrent()->getFirstWidget();\n";
|
||||
@ -586,9 +586,9 @@ void EventHandler::navigateDown(const int playerID, Input::InputType type, const
|
||||
{
|
||||
Screen* screen = GUIEngine::getCurrentScreen();
|
||||
if (screen == NULL) return;
|
||||
firstWidget = screen->getFirstWidget();
|
||||
firstWidget = screen->getFirstWidget();
|
||||
}
|
||||
|
||||
|
||||
if (firstWidget != NULL) firstWidget->setFocusForPlayer(playerID);
|
||||
}
|
||||
}
|
||||
@ -623,9 +623,9 @@ EventPropagation EventHandler::onWidgetActivated(GUIEngine::Widget* w, const int
|
||||
}
|
||||
if (w->m_event_handler == NULL) return EVENT_LET;
|
||||
}
|
||||
|
||||
|
||||
//std::cout << "**** widget activated : " << w->m_properties[PROP_ID].c_str() << " ****" << std::endl;
|
||||
|
||||
|
||||
Widget* parent = w->m_event_handler;
|
||||
if (w->m_event_handler != NULL)
|
||||
{
|
||||
@ -635,12 +635,12 @@ EventPropagation EventHandler::onWidgetActivated(GUIEngine::Widget* w, const int
|
||||
while (parent->m_event_handler != NULL && parent->m_event_handler != parent)
|
||||
{
|
||||
parent->transmitEvent(w, w->m_properties[PROP_ID], playerID);
|
||||
|
||||
|
||||
parent = parent->m_event_handler;
|
||||
}
|
||||
|
||||
|
||||
if (parent->m_deactivated) return EVENT_BLOCK;
|
||||
|
||||
|
||||
/* notify the found event event handler, and also notify the main callback if the
|
||||
parent event handler says so */
|
||||
if (parent->transmitEvent(w, w->m_properties[PROP_ID], playerID) == EVENT_LET)
|
||||
@ -658,19 +658,19 @@ EventPropagation EventHandler::onWidgetActivated(GUIEngine::Widget* w, const int
|
||||
sendEventToUser(w, id, playerID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
{
|
||||
{
|
||||
if (event.EventType == EET_GUI_EVENT)
|
||||
{
|
||||
if (event.GUIEvent.Caller == NULL) return EVENT_LET;
|
||||
const s32 id = event.GUIEvent.Caller->getID();
|
||||
|
||||
|
||||
switch (event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_BUTTON_CLICKED:
|
||||
@ -680,31 +680,31 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
{
|
||||
Widget* w = GUIEngine::getWidget(id);
|
||||
if (w == NULL) break;
|
||||
|
||||
|
||||
if (w->m_deactivated)
|
||||
{
|
||||
GUIEngine::getCurrentScreen()->onDisabledItemClicked(w->m_properties[PROP_ID].c_str());
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
|
||||
|
||||
// These events are only triggered by mouse (or so I hope)
|
||||
// The player that owns the mouser receives "game master" priviledges
|
||||
return onWidgetActivated(w, PLAYER_ID_GAME_MASTER);
|
||||
|
||||
|
||||
// These events are only triggered by keyboard/mouse (or so I hope...)
|
||||
//const int playerID = input_manager->getPlayerKeyboardID();
|
||||
//if (input_manager->masterPlayerOnly() && playerID != PLAYER_ID_GAME_MASTER) break;
|
||||
//else if (playerID != -1) return onWidgetActivated(w, playerID);
|
||||
//else break;
|
||||
}
|
||||
}
|
||||
case EGET_ELEMENT_HOVERED:
|
||||
{
|
||||
{
|
||||
Widget* w = GUIEngine::getWidget(id);
|
||||
|
||||
|
||||
if (w == NULL) break;
|
||||
|
||||
|
||||
if (!w->m_focusable) return GUIEngine::EVENT_BLOCK;
|
||||
|
||||
|
||||
// When a modal dialog is shown, don't select widgets out of the dialog
|
||||
if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyChild(w))
|
||||
{
|
||||
@ -717,7 +717,7 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// select ribbons on hover
|
||||
if (w->m_event_handler != NULL && w->m_event_handler->m_type == WTYPE_RIBBON)
|
||||
{
|
||||
@ -725,13 +725,13 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
// that all widgets may hook onto
|
||||
RibbonWidget* ribbon = (RibbonWidget*)(w->m_event_handler);
|
||||
if (ribbon == NULL) break;
|
||||
|
||||
|
||||
// give the mouse "game master" priviledges
|
||||
const int playerID = PLAYER_ID_GAME_MASTER; //input_manager->getPlayerKeyboardID();
|
||||
|
||||
|
||||
if (playerID == -1) break;
|
||||
if (input_manager->masterPlayerOnly() && playerID != PLAYER_ID_GAME_MASTER) break;
|
||||
|
||||
|
||||
if (ribbon->mouseHovered(w, playerID) == EVENT_LET) sendEventToUser(ribbon, ribbon->m_properties[PROP_ID], playerID);
|
||||
if (ribbon->m_event_handler != NULL) ribbon->m_event_handler->mouseHovered(w, playerID);
|
||||
ribbon->setFocusForPlayer(playerID);
|
||||
@ -752,7 +752,7 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
/*
|
||||
@ -760,16 +760,16 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
{
|
||||
Widget* el = getWidget(id);
|
||||
if(el == NULL) break;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case EGET_ELEMENT_FOCUSED:
|
||||
|
||||
case EGET_ELEMENT_FOCUSED:
|
||||
{
|
||||
Widget* w = GUIEngine::getWidget(id);
|
||||
if (w == NULL) break;
|
||||
|
||||
|
||||
// forbid list for gaining "irrLicht focus", then they will process key events and
|
||||
// we don't want that since we do our own custom processing for keys
|
||||
if (w->m_type == WTYPE_LIST)
|
||||
@ -778,7 +778,7 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
// cheap way to remove the focus from the element (nope, IGUIEnv::removeFocus doesn't work)
|
||||
// Obviously will not work if the list is the first item of the screen.
|
||||
IGUIElement* elem = getCurrentScreen()->getFirstWidget()->getIrrlichtElement();
|
||||
if (elem->getType() == EGUIET_LIST_BOX)
|
||||
if (elem->getType() == EGUIET_LIST_BOX)
|
||||
{
|
||||
elem = getCurrentScreen()->getLastWidget()->getIrrlichtElement();
|
||||
assert(elem->getType() != EGUIET_LIST_BOX);
|
||||
@ -786,21 +786,21 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
GUIEngine::getGUIEnv()->setFocus( elem );
|
||||
return EVENT_BLOCK; // confirms to irrLicht that we processed it
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case EGET_LISTBOX_CHANGED:
|
||||
{
|
||||
Widget* w = GUIEngine::getWidget(id);
|
||||
if (w == NULL) break;
|
||||
assert(w->getType() == WTYPE_LIST);
|
||||
|
||||
|
||||
const int playerID = input_manager->getPlayerKeyboardID();
|
||||
if (input_manager->masterPlayerOnly() && playerID != PLAYER_ID_GAME_MASTER) break;
|
||||
if (!w->isFocusedForPlayer(playerID)) w->setFocusForPlayer(playerID);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case EGET_EDITBOX_ENTER:
|
||||
@ -814,11 +814,11 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
break;
|
||||
} // end switch
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
EGET_BUTTON_CLICKED, EGET_SCROLL_BAR_CHANGED, EGET_CHECKBOX_CHANGED, EGET_TAB_CHANGED,
|
||||
EGET_MENU_ITEM_SELECTED, EGET_COMBO_BOX_CHANGED, EGET_SPINBOX_CHANGED, EGET_EDITBOX_ENTER,
|
||||
|
||||
|
||||
EGET_LISTBOX_CHANGED, EGET_LISTBOX_SELECTED_AGAIN,
|
||||
EGET_FILE_SELECTED, EGET_FILE_CHOOSE_DIALOG_CANCELLED,
|
||||
EGET_MESSAGEBOX_YES, EGET_MESSAGEBOX_NO, EGET_MESSAGEBOX_OK, EGET_MESSAGEBOX_CANCEL,
|
||||
@ -826,7 +826,7 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
EGET_ELEMENT_FOCUS_LOST, EGET_ELEMENT_FOCUSED, EGET_ELEMENT_HOVERED, EGET_ELEMENT_LEFT,
|
||||
EGET_ELEMENT_CLOSED,
|
||||
*/
|
||||
return EVENT_LET;
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -58,14 +58,14 @@ int atoi_p(const char* val)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool LayoutManager::convertToCoord(std::string& x, int* absolute /* out */, int* percentage /* out */)
|
||||
{
|
||||
{
|
||||
bool is_number;
|
||||
int i;
|
||||
std::istringstream myStream(x);
|
||||
is_number = (myStream >> i)!=0;
|
||||
|
||||
|
||||
if(!is_number) return false;
|
||||
|
||||
|
||||
if( x[x.size()-1] == '%' ) // percentage
|
||||
{
|
||||
*percentage = i;
|
||||
@ -82,13 +82,13 @@ bool LayoutManager::convertToCoord(std::string& x, int* absolute /* out */, int*
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void LayoutManager::readCoords(Widget* self)
|
||||
{
|
||||
{
|
||||
// determine widget position and size if not already done by sizers
|
||||
std::string x = self->m_properties[PROP_X];
|
||||
std::string y = self->m_properties[PROP_Y];
|
||||
std::string width = self->m_properties[PROP_WIDTH];
|
||||
std::string height = self->m_properties[PROP_HEIGHT];
|
||||
|
||||
|
||||
/*
|
||||
// retrieve parent size (or screen size if none). Will be useful for layout
|
||||
// and especially for percentages.
|
||||
@ -111,7 +111,7 @@ void LayoutManager::readCoords(Widget* self)
|
||||
parent_y = parent->m_y;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// ---- try converting to number
|
||||
// x coord
|
||||
{
|
||||
@ -132,7 +132,7 @@ void LayoutManager::readCoords(Widget* self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// y coord
|
||||
{
|
||||
int abs_y = 0x7FFFFFFF, percent_y = 0x7FFFFFFF;
|
||||
@ -152,22 +152,22 @@ void LayoutManager::readCoords(Widget* self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- if this widget has an icon, get icon size. this can helpful determine its optimal size
|
||||
int texture_w = -1, texture_h = -1;
|
||||
|
||||
|
||||
if (self->m_properties[PROP_ICON].size() > 0)
|
||||
{
|
||||
ITexture* texture = irr_driver->getTexture((file_manager->getDataDir() + "/" +
|
||||
self->m_properties[PROP_ICON]).c_str());
|
||||
|
||||
|
||||
if (texture != NULL)
|
||||
{
|
||||
texture_w = texture->getSize().Width;
|
||||
texture_h = texture->getSize().Height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- if this widget has a label, get text size. this can helpful determine its optimal size
|
||||
int label_w = -1, label_h = -1;
|
||||
if (self->m_text.size() > 0)
|
||||
@ -184,10 +184,10 @@ void LayoutManager::readCoords(Widget* self)
|
||||
// User text height to guess checkbox size
|
||||
IGUIFont* font = (self->m_title_font ? GUIEngine::getTitleFont() : GUIEngine::getFont());
|
||||
core::dimension2d< u32 > dim = font->getDimension( L"X" );
|
||||
label_h = dim.Height + self->getHeightNeededAroundLabel();
|
||||
label_h = dim.Height + self->getHeightNeededAroundLabel();
|
||||
label_w = label_h; // a checkbox is square
|
||||
}
|
||||
|
||||
|
||||
if (label_h == -1)
|
||||
{
|
||||
if (self->getType() == WTYPE_TEXTBOX ||
|
||||
@ -202,7 +202,7 @@ void LayoutManager::readCoords(Widget* self)
|
||||
label_h = dim.Height + self->getHeightNeededAroundLabel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- if this widget has children, get their size size. this can helpful determine its optimal size
|
||||
if (self->m_properties[PROP_WIDTH] == "fit" || self->m_properties[PROP_HEIGHT] == "fit")
|
||||
{
|
||||
@ -211,7 +211,7 @@ void LayoutManager::readCoords(Widget* self)
|
||||
|
||||
int child_max_width = -1, child_max_height = -1;
|
||||
int total_width = 0, total_height = 0;
|
||||
|
||||
|
||||
for (int child=0; child<self->m_children.size(); child++)
|
||||
{
|
||||
if (self->m_children[child].m_absolute_w > -1)
|
||||
@ -228,7 +228,7 @@ void LayoutManager::readCoords(Widget* self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (self->m_children[child].m_absolute_h > -1)
|
||||
{
|
||||
if (is_vertical_row)
|
||||
@ -244,7 +244,7 @@ void LayoutManager::readCoords(Widget* self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (self->m_properties[PROP_WIDTH] == "fit")
|
||||
{
|
||||
self->m_absolute_w = (is_horizontal_row ? total_width : child_max_width);
|
||||
@ -254,7 +254,7 @@ void LayoutManager::readCoords(Widget* self)
|
||||
self->m_absolute_h = (is_vertical_row ? total_height : child_max_height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- read dimension
|
||||
// width
|
||||
{
|
||||
@ -268,7 +268,7 @@ void LayoutManager::readCoords(Widget* self)
|
||||
else if(texture_w > -1) self->m_absolute_w = texture_w;
|
||||
else if(label_w > -1) self->m_absolute_w = label_w;
|
||||
}
|
||||
|
||||
|
||||
// height
|
||||
{
|
||||
int abs_h = -1, percent_h = -1;
|
||||
@ -308,26 +308,26 @@ void LayoutManager::applyCoords(Widget* self, AbstractTopLevelContainer* topLeve
|
||||
parent_x = parent->m_x;
|
||||
parent_y = parent->m_y;
|
||||
}
|
||||
|
||||
|
||||
if (self->m_absolute_x > -1) self->m_x = parent_x + self->m_absolute_x;
|
||||
else if (self->m_absolute_reverse_x > -1) self->m_x = parent_x + (parent_w - self->m_absolute_reverse_x);
|
||||
else if (self->m_relative_x > -1) self->m_x = (int)(parent_x + parent_w*self->m_relative_x/100);
|
||||
|
||||
|
||||
if (self->m_absolute_y > -1) self->m_y = parent_y + self->m_absolute_y;
|
||||
else if (self->m_absolute_reverse_y > -1) self->m_y = parent_y + (parent_h - self->m_absolute_reverse_y);
|
||||
else if (self->m_relative_y > -1) self->m_y = (int)(parent_y + parent_h*self->m_relative_y/100);
|
||||
|
||||
|
||||
if (self->m_absolute_w > -1) self->m_w = self->m_absolute_w;
|
||||
else if (self->m_relative_w > -1) self->m_w = (int)round(parent_w*self->m_relative_w/100.0);
|
||||
|
||||
|
||||
if (self->m_absolute_h > -1) self->m_h = self->m_absolute_h;
|
||||
else if (self->m_relative_h > -1) self->m_h = (int)round(parent_h*self->m_relative_h/100.0);
|
||||
|
||||
|
||||
// ---- can't make widget bigger than parent
|
||||
if (self->m_h > (int)parent_h)
|
||||
{
|
||||
float ratio = (float)parent_h / self->m_h;
|
||||
|
||||
|
||||
self->m_w = (int)(self->m_w*ratio);
|
||||
self->m_h = (int)(self->m_h*ratio);
|
||||
}
|
||||
@ -335,23 +335,23 @@ void LayoutManager::applyCoords(Widget* self, AbstractTopLevelContainer* topLeve
|
||||
{
|
||||
// scale down while keeping aspect ratio (don't do this for text widgets though...)
|
||||
float ratio = (float)parent_w / self->m_w;
|
||||
|
||||
|
||||
self->m_w = (int)(self->m_w * ratio);
|
||||
|
||||
|
||||
// FIXME: ugly to hardcode widgets types here
|
||||
if (self->m_type != WTYPE_LABEL && self->m_type != WTYPE_BUBBLE)
|
||||
{
|
||||
self->m_h = (int)(self->m_h * ratio);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------ check for given max size
|
||||
if (self->m_properties[PROP_MAX_WIDTH].size() > 0)
|
||||
{
|
||||
const int max_width = atoi_p( self->m_properties[PROP_MAX_WIDTH].c_str() );
|
||||
if (self->m_w > max_width) self->m_w = max_width;
|
||||
}
|
||||
|
||||
|
||||
if (self->m_properties[PROP_MAX_HEIGHT].size() > 0)
|
||||
{
|
||||
const int max_height = atoi_p( self->m_properties[PROP_MAX_HEIGHT].c_str() );
|
||||
@ -364,20 +364,20 @@ void LayoutManager::applyCoords(Widget* self, AbstractTopLevelContainer* topLeve
|
||||
void LayoutManager::recursivelyReadCoords(PtrVector<Widget>& widgets)
|
||||
{
|
||||
const unsigned short widgets_amount = widgets.size();
|
||||
|
||||
|
||||
// ----- deal with containers' children
|
||||
for (int n=0; n<widgets_amount; n++)
|
||||
{
|
||||
if (widgets[n].m_type == WTYPE_DIV) recursivelyReadCoords(widgets[n].m_children);
|
||||
}
|
||||
|
||||
|
||||
// ----- read x/y/size parameters
|
||||
for (unsigned short n=0; n<widgets_amount; n++)
|
||||
{
|
||||
readCoords(widgets.get(n));
|
||||
}//next widget
|
||||
}//next widget
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void LayoutManager::calculateLayout(PtrVector<Widget>& widgets, AbstractTopLevelContainer* topLevelContainer)
|
||||
@ -392,22 +392,22 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
Widget* parent)
|
||||
{
|
||||
const unsigned short widgets_amount = widgets.size();
|
||||
|
||||
|
||||
for (int n=0; n<widgets_amount; n++)
|
||||
{
|
||||
applyCoords(widgets.get(n), topLevelContainer, parent);
|
||||
}
|
||||
|
||||
|
||||
// ----- manage 'layout's if relevant
|
||||
do // i'm using 'while false' here just to be able to 'break' ...
|
||||
{
|
||||
if(parent == NULL) break;
|
||||
|
||||
|
||||
std::string layout_name = parent->m_properties[PROP_LAYOUT];
|
||||
if(layout_name.size() < 1) break;
|
||||
|
||||
|
||||
bool horizontal = false;
|
||||
|
||||
|
||||
if (!strcmp("horizontal-row", layout_name.c_str()))
|
||||
horizontal = true;
|
||||
else if(!strcmp("vertical-row", layout_name.c_str()))
|
||||
@ -417,9 +417,9 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
std::cerr << "Unknown layout name : " << layout_name.c_str() << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
const int w = parent->m_w, h = parent->m_h;
|
||||
|
||||
|
||||
// find space left after placing all absolutely-sized widgets in a row
|
||||
// (the space left will be divided between remaining widgets later)
|
||||
int left_space = (horizontal ? w : h);
|
||||
@ -433,17 +433,17 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
total_proportion += atoi_p( prop.c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// absolutely-sized widgets
|
||||
left_space -= (horizontal ? widgets[n].m_w : widgets[n].m_h);
|
||||
} // next widget
|
||||
|
||||
|
||||
if (left_space < 0)
|
||||
{
|
||||
fprintf(stderr, "[LayoutManager] WARNING: statically sized widgets took all the place!!\n");
|
||||
left_space = 0;
|
||||
}
|
||||
|
||||
|
||||
// ---- lay widgets in row
|
||||
int x = parent->m_x;
|
||||
int y = parent->m_y;
|
||||
@ -461,13 +461,13 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
<< "' is not a number for widget " << widgets[n].m_properties[PROP_ID].c_str()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
const float fraction = (float)proportion/(float)total_proportion;
|
||||
|
||||
|
||||
if (horizontal)
|
||||
{
|
||||
widgets[n].m_x = x;
|
||||
|
||||
|
||||
std::string align = widgets[n].m_properties[ PROP_ALIGN ];
|
||||
if (align.size() < 1)
|
||||
{
|
||||
@ -507,14 +507,14 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
<< "' is unknown (widget '" << widgets[n].m_properties[PROP_ID].c_str()
|
||||
<< "', in a horiozntal-row layout)\n";
|
||||
}
|
||||
|
||||
|
||||
widgets[n].m_w = (int)(left_space*fraction);
|
||||
if (widgets[n].m_properties[PROP_MAX_WIDTH].size() > 0)
|
||||
{
|
||||
const int max_width = atoi_p( widgets[n].m_properties[PROP_MAX_WIDTH].c_str() );
|
||||
if (widgets[n].m_w > max_width) widgets[n].m_w = max_width;
|
||||
}
|
||||
|
||||
|
||||
if (widgets[n].m_w <= 0)
|
||||
{
|
||||
fprintf(stderr, "WARNING: widget '%s' has a width of %i (left_space = %i, "
|
||||
@ -522,19 +522,19 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
widgets[n].m_w, left_space, fraction, widgets[n].m_properties[PROP_MAX_WIDTH].c_str());
|
||||
widgets[n].m_w = 1;
|
||||
}
|
||||
|
||||
|
||||
x += widgets[n].m_w;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
widgets[n].m_h = (int)(left_space*fraction);
|
||||
|
||||
|
||||
if (widgets[n].m_properties[PROP_MAX_HEIGHT].size() > 0)
|
||||
{
|
||||
const int max_height = atoi_p( widgets[n].m_properties[PROP_MAX_HEIGHT].c_str() );
|
||||
if (widgets[n].m_h > max_height) widgets[n].m_h = max_height;
|
||||
}
|
||||
|
||||
|
||||
if (widgets[n].m_h <= 0)
|
||||
{
|
||||
fprintf(stderr, "WARNING: widget '%s' has a height of %i (left_space = %i, "
|
||||
@ -542,7 +542,7 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
widgets[n].m_h, left_space, fraction, widgets[n].m_properties[PROP_MAX_WIDTH].c_str());
|
||||
widgets[n].m_h = 1;
|
||||
}
|
||||
|
||||
|
||||
std::string align = widgets[n].m_properties[ PROP_ALIGN ];
|
||||
if (align.size() < 1)
|
||||
{
|
||||
@ -572,7 +572,7 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
{
|
||||
widgets[n].m_x = x + w/2 - widgets[n].m_w/2;
|
||||
}
|
||||
else if (align == "right")
|
||||
else if (align == "right")
|
||||
{
|
||||
widgets[n].m_x = x + w - widgets[n].m_w;
|
||||
}
|
||||
@ -583,24 +583,24 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
<< "', in a vertical-row layout)\n";
|
||||
}
|
||||
widgets[n].m_y = y;
|
||||
|
||||
|
||||
y += widgets[n].m_h;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// absolute size
|
||||
|
||||
|
||||
if (horizontal)
|
||||
{
|
||||
widgets[n].m_x = x;
|
||||
|
||||
|
||||
std::string align = widgets[n].m_properties[ PROP_ALIGN ];
|
||||
|
||||
|
||||
if (align.size() < 1)
|
||||
{
|
||||
std::string prop_y = widgets[n].m_properties[ PROP_Y ];
|
||||
|
||||
|
||||
if (prop_y.size() > 0)
|
||||
{
|
||||
if (prop_y[ prop_y.size()-1 ] == '%')
|
||||
@ -636,17 +636,17 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
<< "' is unknown in widget " << widgets[n].m_properties[PROP_ID].c_str()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
x += widgets[n].m_w;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
std::string align = widgets[n].m_properties[ PROP_ALIGN ];
|
||||
|
||||
|
||||
if (align.size() < 1)
|
||||
{
|
||||
std::string prop_x = widgets[n].m_properties[ PROP_X ];
|
||||
|
||||
|
||||
if (prop_x.size() > 0)
|
||||
{
|
||||
if (prop_x[ prop_x.size()-1 ] == '%')
|
||||
@ -682,15 +682,15 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
|
||||
<< "' is unknown in widget " << widgets[n].m_properties[PROP_ID].c_str() << std::endl;
|
||||
}
|
||||
widgets[n].m_y = y;
|
||||
|
||||
|
||||
y += widgets[n].m_h;
|
||||
}
|
||||
} // end if property or absolute size
|
||||
|
||||
|
||||
} // next widget
|
||||
|
||||
|
||||
} while(false);
|
||||
|
||||
|
||||
// ----- also deal with containers' children
|
||||
for (int n=0; n<widgets_amount; n++)
|
||||
{
|
||||
|
@ -65,18 +65,18 @@ void ModalDialog::loadFromFile(const char* xmlFile)
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Screen::parseScreenFileDiv(xml, m_widgets, m_irrlicht_window);
|
||||
delete xml;
|
||||
|
||||
|
||||
loadedFromFile();
|
||||
|
||||
|
||||
LayoutManager::calculateLayout( m_widgets, this );
|
||||
|
||||
|
||||
beforeAddingWidgets();
|
||||
|
||||
|
||||
addWidgetsRecursively(m_widgets);
|
||||
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@ -86,23 +86,23 @@ void ModalDialog::doInit(const float percentWidth, const float percentHeight)
|
||||
{
|
||||
pointer_was_shown = irr_driver->isPointerShown();
|
||||
irr_driver->showPointer();
|
||||
|
||||
|
||||
const core::dimension2d<u32>& frame_size = GUIEngine::getDriver()->getCurrentRenderTargetSize();
|
||||
|
||||
|
||||
const int w = (int)(frame_size.Width*percentWidth);
|
||||
const int h = (int)(frame_size.Height*percentHeight);
|
||||
|
||||
|
||||
assert(frame_size.Width > 0);
|
||||
assert(frame_size.Height > 0);
|
||||
assert(frame_size.Width < 99999);
|
||||
assert(frame_size.Height < 99999);
|
||||
|
||||
|
||||
assert(w > 0);
|
||||
assert(h > 0);
|
||||
|
||||
|
||||
assert((unsigned int)w <= frame_size.Width);
|
||||
assert((unsigned int)h <= frame_size.Height);
|
||||
|
||||
|
||||
if (m_dialog_location == MODAL_DIALOG_LOCATION_CENTER)
|
||||
{
|
||||
m_area = core::rect<s32>(core::position2d<s32>(frame_size.Width/2 - w/2,
|
||||
@ -113,25 +113,25 @@ void ModalDialog::doInit(const float percentWidth, const float percentHeight)
|
||||
{
|
||||
m_area = core::rect<s32>(core::position2d<s32>(frame_size.Width/2 - w/2,
|
||||
frame_size.Height - h - 15),
|
||||
core::dimension2d<s32>(w, h));
|
||||
core::dimension2d<s32>(w, h));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
if (modalWindow != NULL)
|
||||
{
|
||||
delete modalWindow;
|
||||
Log::warn("GUIEngine", "Showing a modal dialog while the previous one is still open. Destroying the previous dialog.");
|
||||
}
|
||||
modalWindow = this;
|
||||
|
||||
|
||||
m_irrlicht_window = GUIEngine::getGUIEnv()->addWindow(m_area, true /* modal */);
|
||||
|
||||
|
||||
GUIEngine::getSkin()->m_dialog = true;
|
||||
GUIEngine::getSkin()->m_dialog_size = 0.0f;
|
||||
|
||||
|
||||
m_previous_mode=input_manager->getMode();
|
||||
input_manager->setMode(InputManager::MENU);
|
||||
}
|
||||
@ -146,19 +146,19 @@ ModalDialog::~ModalDialog()
|
||||
// irrLicht is to stupid to remove focus from deleted widgets
|
||||
// so do it by hand
|
||||
GUIEngine::getGUIEnv()->removeFocus( m_irrlicht_window );
|
||||
|
||||
|
||||
m_irrlicht_window->remove();
|
||||
m_irrlicht_window = NULL;
|
||||
|
||||
|
||||
if (modalWindow == this) modalWindow = NULL;
|
||||
|
||||
|
||||
// restore previous pointer state
|
||||
if (pointer_was_shown) irr_driver->showPointer();
|
||||
else irr_driver->hidePointer();
|
||||
|
||||
input_manager->setMode(m_previous_mode);
|
||||
|
||||
|
||||
|
||||
|
||||
// it's generally not necessay to do that because references
|
||||
// to the deleted widgets will be gone, but some widgets
|
||||
// may want to perform additional cleanup at this time
|
||||
@ -175,14 +175,14 @@ void ModalDialog::clearWindow()
|
||||
m_irrlicht_window->removeChild( w->getIrrlichtElement() );
|
||||
}
|
||||
elementsWereDeleted();
|
||||
m_widgets.clearAndDeleteAll();
|
||||
|
||||
m_widgets.clearAndDeleteAll();
|
||||
|
||||
m_irrlicht_window->remove();
|
||||
m_irrlicht_window = GUIEngine::getGUIEnv()->addWindow( m_area, true /* modal */ );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void ModalDialog::dismiss()
|
||||
{
|
||||
if(modalWindow != NULL) delete modalWindow;
|
||||
@ -215,7 +215,7 @@ ModalDialog* ModalDialog::getCurrent()
|
||||
void ModalDialog::onEnterPressedInternal()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -27,14 +27,14 @@ ScalableFont::ScalableFont(IGUIEnvironment *env, const io::path& filename)
|
||||
#ifdef _DEBUG
|
||||
setDebugName("ScalableFont");
|
||||
#endif
|
||||
|
||||
|
||||
m_fallback_font = NULL;
|
||||
m_fallback_kerning_width = 0;
|
||||
m_fallback_font_scale = 1.0f;
|
||||
m_scale = 1.0f;
|
||||
m_tab_stop = 0.5f;
|
||||
m_is_hollow_copy = false;
|
||||
m_black_border = false;
|
||||
m_black_border = false;
|
||||
m_shadow = false;
|
||||
m_mono_space_digits = false;
|
||||
m_rtl = translations->isRTLLanguage();
|
||||
@ -53,7 +53,7 @@ ScalableFont::ScalableFont(IGUIEnvironment *env, const io::path& filename)
|
||||
Driver->grab();
|
||||
|
||||
setInvisibleCharacters ( L" " );
|
||||
|
||||
|
||||
io::IXMLReader* reader = file_manager->createXMLReader(filename.c_str());
|
||||
if (!load( reader ))
|
||||
{
|
||||
@ -61,7 +61,7 @@ ScalableFont::ScalableFont(IGUIEnvironment *env, const io::path& filename)
|
||||
assert(false);
|
||||
}
|
||||
reader->drop();
|
||||
|
||||
|
||||
assert(Areas.size() > 0);
|
||||
}
|
||||
|
||||
@ -80,18 +80,18 @@ void ScalableFont::updateRTL()
|
||||
{
|
||||
m_rtl = translations->isRTLLanguage();
|
||||
}
|
||||
|
||||
|
||||
void ScalableFont::setShadow(const irr::video::SColor &col)
|
||||
{
|
||||
m_shadow = true;
|
||||
m_shadow_color = col;
|
||||
}
|
||||
|
||||
|
||||
void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
|
||||
{
|
||||
int trim_top = 0;
|
||||
int trim_bottom = 0;
|
||||
|
||||
|
||||
while (xml->read())
|
||||
{
|
||||
if (io::EXN_ELEMENT == xml->getNodeType())
|
||||
@ -101,16 +101,16 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
|
||||
core::stringc filename = xml->getAttributeValue(L"file");
|
||||
/*
|
||||
const wchar_t* iflangis = xml->getAttributeValue(L"iflanguage");
|
||||
|
||||
|
||||
printf("langcode = %s\n", translations->getCurrentLanguageCode().c_str());
|
||||
|
||||
|
||||
if (iflangis != NULL &&
|
||||
core::stringc(iflangis) != translations->getCurrentLanguageCode().c_str())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
io::IXMLReader* included = file_manager->createXMLReader(
|
||||
file_manager->getFontFile(filename.c_str()));
|
||||
if (included != NULL)
|
||||
@ -125,42 +125,42 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
|
||||
core::stringc filename = xml->getAttributeValue(L"filename");
|
||||
core::stringc fn = file_manager->getFontFile(filename.c_str()).c_str();
|
||||
u32 i = (u32)xml->getAttributeValueAsInt(L"index");
|
||||
|
||||
|
||||
float scale=1.0f;
|
||||
if(xml->getAttributeValue(L"scale"))
|
||||
scale = xml->getAttributeValueAsFloat(L"scale");
|
||||
//std::cout << "scale = " << scale << std::endl;
|
||||
|
||||
|
||||
bool excludeFromMaxHeightCalculation = false;
|
||||
if (xml->getAttributeValue(L"excludeFromMaxHeightCalculation"))
|
||||
excludeFromMaxHeightCalculation = (core::stringc(xml->getAttributeValue(L"excludeFromMaxHeightCalculation")) == "true");
|
||||
|
||||
|
||||
core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
|
||||
|
||||
|
||||
//std::cout << "---- Adding font texture " << fn.c_str() << "; alpha=" << alpha.c_str() << std::endl;
|
||||
|
||||
|
||||
|
||||
|
||||
// make sure the sprite bank has enough textures in it
|
||||
while (i+1 > SpriteBank->getTextureCount())
|
||||
{
|
||||
SpriteBank->addTexture(NULL);
|
||||
}
|
||||
|
||||
|
||||
TextureInfo info;
|
||||
info.m_file_name = fn;
|
||||
info.m_has_alpha = (alpha == core::stringw("true"));
|
||||
info.m_scale = scale;
|
||||
info.m_exclude_from_max_height_calculation = excludeFromMaxHeightCalculation;
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
if (m_texture_files.find(i) != m_texture_files.end())
|
||||
{
|
||||
fprintf(stderr, "[ScalableFont] WARNING: Font conflict, two images have texture %i\n", i);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_texture_files[i] = info;
|
||||
|
||||
m_texture_files[i] = info;
|
||||
}
|
||||
else if (core::stringw(L"font") == xml->getNodeName())
|
||||
{
|
||||
@ -174,16 +174,16 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
|
||||
SGUISpriteFrame f;
|
||||
SGUISprite s;
|
||||
core::rect<s32> rectangle;
|
||||
|
||||
|
||||
a.underhang = xml->getAttributeValueAsInt(L"u");
|
||||
a.overhang = xml->getAttributeValueAsInt(L"o");
|
||||
a.spriteno = SpriteBank->getSprites().size();
|
||||
s32 texno = xml->getAttributeValueAsInt(L"i");
|
||||
|
||||
|
||||
// parse rectangle
|
||||
core::stringc rectstr = xml->getAttributeValue(L"r");
|
||||
wchar_t ch = xml->getAttributeValue(L"c")[0];
|
||||
|
||||
|
||||
const c8 *c = rectstr.c_str();
|
||||
s32 val;
|
||||
val = 0;
|
||||
@ -195,7 +195,7 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
|
||||
}
|
||||
rectangle.UpperLeftCorner.X = val;
|
||||
while (*c == L' ' || *c == L',') c++;
|
||||
|
||||
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
@ -205,7 +205,7 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
|
||||
}
|
||||
rectangle.UpperLeftCorner.Y = val + trim_top;
|
||||
while (*c == L' ' || *c == L',') c++;
|
||||
|
||||
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
@ -215,7 +215,7 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
|
||||
}
|
||||
rectangle.LowerRightCorner.X = val;
|
||||
while (*c == L' ' || *c == L',') c++;
|
||||
|
||||
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
@ -224,34 +224,34 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
|
||||
c++;
|
||||
}
|
||||
rectangle.LowerRightCorner.Y = val - trim_bottom;
|
||||
|
||||
|
||||
CharacterMap[ch] = Areas.size();
|
||||
|
||||
|
||||
//std::cout << "Inserting character '" << (int)ch << "' with area " << Areas.size() << std::endl;
|
||||
|
||||
|
||||
// make frame
|
||||
f.rectNumber = SpriteBank->getPositions().size();
|
||||
f.textureNumber = texno;
|
||||
|
||||
|
||||
// add frame to sprite
|
||||
s.Frames.push_back(f);
|
||||
s.frameTime = 0;
|
||||
|
||||
|
||||
// add rectangle to sprite bank
|
||||
SpriteBank->getPositions().push_back(rectangle);
|
||||
a.width = rectangle.getWidth();
|
||||
|
||||
|
||||
// add sprite to sprite bank
|
||||
SpriteBank->getSprites().push_back(s);
|
||||
|
||||
|
||||
// add character to font
|
||||
Areas.push_back(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! loads a font file from xml
|
||||
bool ScalableFont::load(io::IXMLReader* xml)
|
||||
{
|
||||
@ -262,7 +262,7 @@ bool ScalableFont::load(io::IXMLReader* xml)
|
||||
}
|
||||
|
||||
doReadXmlFile(xml);
|
||||
|
||||
|
||||
// set bad character
|
||||
WrongCharacter = getAreaIDFromCharacter(L' ', NULL);
|
||||
|
||||
@ -294,16 +294,16 @@ void ScalableFont::setMaxHeight()
|
||||
for (u32 i=0; i<p.size(); ++i)
|
||||
{
|
||||
t = p[i].getHeight();
|
||||
|
||||
|
||||
// FIXME: consider fallback fonts
|
||||
int texID = sprites[i].Frames[0].textureNumber;
|
||||
|
||||
|
||||
const TextureInfo& info = (*(m_texture_files.find(texID))).second;
|
||||
if (info.m_exclude_from_max_height_calculation) continue;
|
||||
|
||||
|
||||
float char_scale = info.m_scale;
|
||||
t = (int)(t*char_scale);
|
||||
|
||||
|
||||
if (t>MaxHeight)
|
||||
MaxHeight = t;
|
||||
}
|
||||
@ -383,23 +383,23 @@ s32 ScalableFont::getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) c
|
||||
}
|
||||
}
|
||||
|
||||
const ScalableFont::SFontArea &ScalableFont::getAreaFromCharacter(const wchar_t c,
|
||||
const ScalableFont::SFontArea &ScalableFont::getAreaFromCharacter(const wchar_t c,
|
||||
bool* fallback_font) const
|
||||
{
|
||||
const int area_id = getAreaIDFromCharacter(c, fallback_font);
|
||||
|
||||
|
||||
|
||||
|
||||
if(m_mono_space_digits && ( (c>=L'0' && c<=L'9') || c==L' ' ) )
|
||||
{
|
||||
const SFontArea &area = (fallback_font && *fallback_font)
|
||||
? m_fallback_font->Areas[area_id]
|
||||
const SFontArea &area = (fallback_font && *fallback_font)
|
||||
? m_fallback_font->Areas[area_id]
|
||||
: Areas[area_id];
|
||||
m_max_digit_area.spriteno = area.spriteno;
|
||||
return m_max_digit_area;
|
||||
}
|
||||
|
||||
const bool use_fallback_font = (fallback_font && *fallback_font);
|
||||
|
||||
|
||||
if (use_fallback_font)
|
||||
{
|
||||
assert(area_id < (int)m_fallback_font->Areas.size());
|
||||
@ -408,7 +408,7 @@ const ScalableFont::SFontArea &ScalableFont::getAreaFromCharacter(const wchar_t
|
||||
{
|
||||
assert(area_id < (int)Areas.size());
|
||||
}
|
||||
|
||||
|
||||
// Note: fallback_font can be NULL
|
||||
return ( use_fallback_font ? m_fallback_font->Areas[area_id] : Areas[area_id]);
|
||||
} // getAreaFromCharacter
|
||||
@ -424,7 +424,7 @@ void ScalableFont::setInvisibleCharacters( const wchar_t *s )
|
||||
core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
||||
{
|
||||
assert(Areas.size() > 0);
|
||||
|
||||
|
||||
core::dimension2d<u32> dim(0, 0);
|
||||
core::dimension2d<u32> thisLine(0, (int)(MaxHeight*m_scale));
|
||||
|
||||
@ -444,9 +444,9 @@ core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
||||
|
||||
bool fallback = false;
|
||||
const SFontArea &area = getAreaFromCharacter(*p, &fallback);
|
||||
|
||||
|
||||
thisLine.Width += area.underhang;
|
||||
|
||||
|
||||
thisLine.Width += getCharWidth(area, fallback);
|
||||
}
|
||||
|
||||
@ -459,54 +459,54 @@ core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
||||
dim.Height = (int)(dim.Height + 0.9f);
|
||||
|
||||
//std::cout << dim.Width << ", " << dim.Height << std::endl;
|
||||
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
||||
void ScalableFont::draw(const core::stringw& text,
|
||||
const core::rect<s32>& position, video::SColor color,
|
||||
bool hcenter, bool vcenter,
|
||||
|
||||
void ScalableFont::draw(const core::stringw& text,
|
||||
const core::rect<s32>& position, video::SColor color,
|
||||
bool hcenter, bool vcenter,
|
||||
const core::rect<s32>* clip, bool ignoreRTL)
|
||||
{
|
||||
bool previousRTL = m_rtl;
|
||||
if (ignoreRTL) m_rtl = false;
|
||||
|
||||
draw(text, position, color, hcenter, vcenter, clip);
|
||||
|
||||
|
||||
if (ignoreRTL) m_rtl = previousRTL;
|
||||
}
|
||||
|
||||
|
||||
//! draws some text and clips it to the specified rectangle if wanted
|
||||
void ScalableFont::draw(const core::stringw& text,
|
||||
const core::rect<s32>& position, video::SColor color,
|
||||
bool hcenter, bool vcenter,
|
||||
void ScalableFont::draw(const core::stringw& text,
|
||||
const core::rect<s32>& position, video::SColor color,
|
||||
bool hcenter, bool vcenter,
|
||||
const core::rect<s32>* clip)
|
||||
{
|
||||
if (!Driver) return;
|
||||
|
||||
|
||||
if (m_shadow)
|
||||
{
|
||||
m_shadow = false; // avoid infinite recursion
|
||||
|
||||
|
||||
core::rect<s32> shadowpos = position;
|
||||
shadowpos.LowerRightCorner.X += 2;
|
||||
shadowpos.LowerRightCorner.Y += 2;
|
||||
|
||||
draw(text, shadowpos, m_shadow_color, hcenter, vcenter, clip);
|
||||
|
||||
|
||||
m_shadow = true; // set back
|
||||
}
|
||||
|
||||
|
||||
core::position2d<s32> offset = position.UpperLeftCorner;
|
||||
core::dimension2d<s32> text_dimension;
|
||||
|
||||
// When we use the "tab" hack, disable right-alignment, it messes up everything
|
||||
bool has_tab = (text.findFirst(L'\t') != -1);
|
||||
|
||||
if ((m_rtl && !has_tab) || hcenter || vcenter || clip)
|
||||
|
||||
if ((m_rtl && !has_tab) || hcenter || vcenter || clip)
|
||||
{
|
||||
text_dimension = getDimension(text.c_str());
|
||||
|
||||
|
||||
if (hcenter) offset.X += (position.getWidth() - text_dimension.Width) / 2;
|
||||
else if (m_rtl && !has_tab) offset.X += (position.getWidth() - text_dimension.Width);
|
||||
|
||||
@ -518,7 +518,7 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
if (!clippedRect.isValid()) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_rtl && has_tab)
|
||||
{
|
||||
const int where = text.findFirst(L'\t');
|
||||
@ -532,7 +532,7 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
core::array<s32> indices(text_size);
|
||||
core::array<core::position2di> offsets(text_size);
|
||||
std::vector<bool> fallback(text_size);
|
||||
|
||||
|
||||
for (u32 i = 0; i<text_size; i++)
|
||||
{
|
||||
wchar_t c = text[i];
|
||||
@ -540,11 +540,11 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
//hack: one tab character is supported, it moves the cursor to the tab stop
|
||||
if (c == L'\t')
|
||||
{
|
||||
offset.X = (int)(position.UpperLeftCorner.X +
|
||||
offset.X = (int)(position.UpperLeftCorner.X +
|
||||
position.getWidth()*m_tab_stop);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (c == L'\r' || // Windows breaks
|
||||
c == L'\n' ) // Unix breaks
|
||||
{
|
||||
@ -561,7 +561,7 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
fallback[i] = use_fallback_font;
|
||||
offset.X += area.underhang;
|
||||
offsets.push_back(offset);
|
||||
// Invisible character. add something to the array anyway so that
|
||||
// Invisible character. add something to the array anyway so that
|
||||
// indices from the various arrays remain in sync
|
||||
indices.push_back( Invisible.findFirst(c) < 0 ? area.spriteno
|
||||
: -1 );
|
||||
@ -571,7 +571,7 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
// ---- do the actual rendering
|
||||
const int indiceAmount = indices.size();
|
||||
core::array< SGUISprite >& sprites = SpriteBank->getSprites();
|
||||
core::array< core::rect<s32> >& positions = SpriteBank->getPositions();
|
||||
core::array< core::rect<s32> >& positions = SpriteBank->getPositions();
|
||||
core::array< SGUISprite >* fallback_sprites;
|
||||
core::array< core::rect<s32> >* fallback_positions;
|
||||
if(m_fallback_font!=NULL)
|
||||
@ -592,17 +592,17 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
const int spriteID = indices[n];
|
||||
if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue;
|
||||
if (indices[n] == -1) continue;
|
||||
|
||||
|
||||
//assert(sprites[spriteID].Frames.size() > 0);
|
||||
|
||||
|
||||
const int texID = (fallback[n] ?
|
||||
(*fallback_sprites)[spriteID].Frames[0].textureNumber :
|
||||
sprites[spriteID].Frames[0].textureNumber);
|
||||
|
||||
|
||||
core::rect<s32> source = (fallback[n] ?
|
||||
(*fallback_positions)[(*fallback_sprites)[spriteID].Frames[0].rectNumber] :
|
||||
positions[sprites[spriteID].Frames[0].rectNumber]);
|
||||
|
||||
|
||||
const TextureInfo& info = (fallback[n] ?
|
||||
(*(m_fallback_font->m_texture_files.find(texID))).second :
|
||||
(*(m_texture_files.find(texID))).second
|
||||
@ -610,22 +610,22 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
float char_scale = info.m_scale;
|
||||
|
||||
core::dimension2d<s32> size = source.getSize();
|
||||
|
||||
|
||||
float scale = (fallback[n] ? m_scale*m_fallback_font_scale : m_scale);
|
||||
size.Width = (int)(size.Width * scale * char_scale);
|
||||
size.Height = (int)(size.Height * scale * char_scale);
|
||||
|
||||
|
||||
// align vertically if character is smaller
|
||||
int y_shift = (size.Height < MaxHeight*m_scale ? (int)((MaxHeight*m_scale - size.Height)/2.0f) : 0);
|
||||
|
||||
|
||||
core::rect<s32> dest(offsets[n] + core::position2di(0, y_shift), size);
|
||||
|
||||
|
||||
video::SColor colors[] = {color, color, color, color};
|
||||
|
||||
|
||||
video::ITexture* texture = (fallback[n] ?
|
||||
m_fallback_font->SpriteBank->getTexture(texID) :
|
||||
SpriteBank->getTexture(texID) );
|
||||
|
||||
|
||||
/*
|
||||
if (fallback[n])
|
||||
{
|
||||
@ -635,11 +635,11 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
<< offsets[n].X << ", " << offsets[n].Y << std::endl;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if (texture == NULL)
|
||||
{
|
||||
// perform lazy loading
|
||||
|
||||
|
||||
if (fallback[n])
|
||||
{
|
||||
m_fallback_font->lazyLoadTexture(texID);
|
||||
@ -650,20 +650,20 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
lazyLoadTexture(texID);
|
||||
texture = SpriteBank->getTexture(texID);
|
||||
}
|
||||
|
||||
|
||||
if (texture == NULL)
|
||||
{
|
||||
fprintf(stderr, "WARNING: character not found in current font\n");
|
||||
continue; // no such character
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_black_border)
|
||||
{
|
||||
// draw black border
|
||||
video::SColor black(color.getAlpha(),0,0,0);
|
||||
video::SColor black_colors[] = {black, black, black, black};
|
||||
|
||||
|
||||
for (int x_delta=-2; x_delta<=2; x_delta++)
|
||||
{
|
||||
for (int y_delta=-2; y_delta<=2; y_delta++)
|
||||
@ -674,10 +674,10 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
source,
|
||||
clip,
|
||||
black_colors, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fallback[n])
|
||||
{
|
||||
// draw text over
|
||||
@ -691,13 +691,13 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
title_colors, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
driver->draw2DImage(texture,
|
||||
dest,
|
||||
source,
|
||||
clip,
|
||||
colors, true);
|
||||
|
||||
|
||||
#ifdef FONT_DEBUG
|
||||
driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y),
|
||||
core::position2d<s32>(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y),
|
||||
@ -720,14 +720,14 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
void ScalableFont::lazyLoadTexture(int texID)
|
||||
{
|
||||
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
|
||||
|
||||
|
||||
// load texture
|
||||
assert(m_texture_files[texID].m_file_name.size() > 0);
|
||||
SpriteBank->setTexture(texID, Driver->getTexture( m_texture_files[texID].m_file_name ));
|
||||
|
||||
|
||||
// set previous mip-map+filter state
|
||||
//Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap);
|
||||
|
||||
|
||||
// couldn't load texture, abort.
|
||||
if (!SpriteBank->getTexture(texID))
|
||||
{
|
||||
@ -738,7 +738,7 @@ void ScalableFont::lazyLoadTexture(int texID)
|
||||
else
|
||||
{
|
||||
assert(m_texture_files[texID].m_file_name.size() > 0);
|
||||
|
||||
|
||||
// colorkey texture rather than alpha channel?
|
||||
if (! m_texture_files[texID].m_has_alpha)
|
||||
{
|
||||
@ -746,32 +746,32 @@ void ScalableFont::lazyLoadTexture(int texID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ScalableFont::getCharWidth(const SFontArea& area, const bool fallback) const
|
||||
{
|
||||
core::array< SGUISprite >& sprites = SpriteBank->getSprites();
|
||||
core::array< SGUISprite >& sprites = SpriteBank->getSprites();
|
||||
core::array< SGUISprite >* fallback_sprites = (m_fallback_font != NULL ?
|
||||
&m_fallback_font->SpriteBank->getSprites() :
|
||||
NULL);
|
||||
|
||||
|
||||
const int texID = (fallback ?
|
||||
(*fallback_sprites)[area.spriteno].Frames[0].textureNumber :
|
||||
sprites[area.spriteno].Frames[0].textureNumber);
|
||||
|
||||
|
||||
const TextureInfo& info = (fallback ?
|
||||
(*(m_fallback_font->m_texture_files.find(texID))).second :
|
||||
(*(m_texture_files.find(texID))).second
|
||||
);
|
||||
assert(info.m_file_name.size() > 0);
|
||||
const float char_scale = info.m_scale;
|
||||
|
||||
|
||||
//std::cout << "area.spriteno=" << area.spriteno << ", char_scale=" << char_scale << std::endl;
|
||||
|
||||
|
||||
if (fallback) return (int)(((area.width + area.overhang)*m_fallback_font_scale + m_fallback_kerning_width) * m_scale * char_scale);
|
||||
else return (int)((area.width + area.overhang + GlobalKerningWidth) * m_scale * char_scale);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! Calculates the index of the character in the text which is on a specific position.
|
||||
s32 ScalableFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
||||
{
|
||||
@ -782,9 +782,9 @@ s32 ScalableFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
||||
{
|
||||
bool use_fallback_font = false;
|
||||
const SFontArea &a = getAreaFromCharacter(text[idx], &use_fallback_font);
|
||||
|
||||
|
||||
x += getCharWidth(a, use_fallback_font) + a.overhang + a.underhang + GlobalKerningWidth;
|
||||
|
||||
|
||||
if (x >= pixel_x)
|
||||
return idx;
|
||||
|
||||
|
@ -39,7 +39,7 @@ using namespace GUIEngine;
|
||||
#include <assert.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/**
|
||||
/**
|
||||
* \brief Creates a screen populated by the widgets described
|
||||
* in a STK GUI file.
|
||||
* \param filename Name of the XML file describing the screen.
|
||||
@ -116,7 +116,7 @@ void Screen::tearDown()
|
||||
void Screen::loadFromFile()
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
IXMLReader* xml = file_manager->createXMLReader( (file_manager->getGUIDir() + m_filename).c_str() );
|
||||
if (xml == NULL)
|
||||
{
|
||||
@ -124,14 +124,14 @@ void Screen::loadFromFile()
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
parseScreenFileDiv(xml, m_widgets);
|
||||
m_loaded = true;
|
||||
calculateLayout();
|
||||
|
||||
|
||||
// invoke callback so that the class deriving from Screen is aware of this event
|
||||
loadedFromFile();
|
||||
|
||||
|
||||
delete xml;
|
||||
} // loadFromFile
|
||||
|
||||
@ -148,10 +148,10 @@ void Screen::unload()
|
||||
{
|
||||
assert(w->m_magic_number == 0xCAFEC001);
|
||||
}
|
||||
|
||||
|
||||
m_loaded = false;
|
||||
m_widgets.clearAndDeleteAll();
|
||||
|
||||
|
||||
// invoke callback so that the class deriving from Screen is aware of this event
|
||||
unloaded();
|
||||
} // unload
|
||||
@ -180,11 +180,11 @@ void Screen::addWidgets()
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
if (!m_loaded) loadFromFile();
|
||||
|
||||
|
||||
addWidgetsRecursively( m_widgets );
|
||||
|
||||
//std::cout << "*****ScreenAddWidgets " << m_filename.c_str() << " : focusing the first widget*****\n";
|
||||
|
||||
|
||||
// select the first widget (for first players only; if other players need some focus the Screen must provide it).
|
||||
Widget* w = getFirstWidget();
|
||||
//std::cout << "First widget is " << (w == NULL ? "null" : w->m_properties[PROP_ID].c_str()) << std::endl;
|
||||
|
@ -39,14 +39,14 @@ void Screen::parseScreenFileDiv(irr::io::IXMLReader* xml, PtrVector<Widget>& app
|
||||
// parse XML file
|
||||
while (xml && xml->read())
|
||||
{
|
||||
|
||||
|
||||
switch (xml->getNodeType())
|
||||
{
|
||||
case irr::io::EXN_TEXT:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case irr::io::EXN_ELEMENT:
|
||||
{
|
||||
/* find which type of widget is specified by the current tag, and instanciate it */
|
||||
@ -181,15 +181,15 @@ void Screen::parseScreenFileDiv(irr::io::IXMLReader* xml, PtrVector<Widget>& app
|
||||
<< xml->getNodeName() << "'" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* retrieve the created widget */
|
||||
Widget& widget = append_to[append_to.size()-1];
|
||||
|
||||
|
||||
/* read widget properties using macro magic */
|
||||
|
||||
|
||||
#define READ_PROPERTY( prop_name, prop_flag ) const wchar_t* prop_name = xml->getAttributeValue( L###prop_name ); \
|
||||
if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).c_str(); else widget.m_properties[prop_flag] = ""
|
||||
|
||||
|
||||
READ_PROPERTY(id, PROP_ID);
|
||||
READ_PROPERTY(proportion, PROP_PROPORTION);
|
||||
READ_PROPERTY(width, PROP_WIDTH);
|
||||
@ -202,14 +202,14 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).
|
||||
READ_PROPERTY(y, PROP_Y);
|
||||
READ_PROPERTY(layout, PROP_LAYOUT);
|
||||
READ_PROPERTY(align, PROP_ALIGN);
|
||||
|
||||
|
||||
READ_PROPERTY(icon, PROP_ICON);
|
||||
READ_PROPERTY(focus_icon, PROP_FOCUS_ICON);
|
||||
READ_PROPERTY(text_align, PROP_TEXT_ALIGN);
|
||||
READ_PROPERTY(min_value, PROP_MIN_VALUE);
|
||||
READ_PROPERTY(max_value, PROP_MAX_VALUE);
|
||||
READ_PROPERTY(square_items, PROP_SQUARE);
|
||||
|
||||
|
||||
READ_PROPERTY(max_width, PROP_MAX_WIDTH);
|
||||
READ_PROPERTY(max_height, PROP_MAX_HEIGHT);
|
||||
READ_PROPERTY(extend_label, PROP_EXTEND_LABEL);
|
||||
@ -217,27 +217,27 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).
|
||||
READ_PROPERTY(max_rows, PROP_MAX_ROWS);
|
||||
READ_PROPERTY(wrap_around, PROP_WRAP_AROUND);
|
||||
#undef READ_PROPERTY
|
||||
|
||||
|
||||
const wchar_t* text = xml->getAttributeValue( L"text" );
|
||||
|
||||
|
||||
if (text != NULL)
|
||||
{
|
||||
widget.m_text = _(text);
|
||||
widget.m_is_text_rtl = (translations->isRTLLanguage() && widget.m_text != text);
|
||||
}
|
||||
|
||||
|
||||
if (parent != NULL)
|
||||
{
|
||||
widget.setParent(parent);
|
||||
}
|
||||
|
||||
|
||||
/* a new div starts here, continue parsing with this new div as new parent */
|
||||
if (widget.getType() == WTYPE_DIV || widget.getType() == WTYPE_RIBBON)
|
||||
{
|
||||
parseScreenFileDiv( xml, append_to[append_to.size()-1].m_children, parent );
|
||||
}
|
||||
}// end case EXN_ELEMENT
|
||||
|
||||
|
||||
break;
|
||||
case irr::io::EXN_ELEMENT_END:
|
||||
{
|
||||
@ -254,7 +254,7 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).
|
||||
return;
|
||||
if (wcscmp(L"topbar", xml->getNodeName()) == 0)
|
||||
return;
|
||||
|
||||
|
||||
// We're done parsing this 'ribbon', return one step back in
|
||||
// the recursive call.
|
||||
if (wcscmp(L"ribbon", xml->getNodeName()) == 0 ||
|
||||
@ -263,7 +263,7 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default: break;
|
||||
}//end switch
|
||||
} // end while
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,7 @@ using namespace gui;
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
|
||||
|
||||
static bool g_is_within_a_text_box = false;
|
||||
bool isWithinATextBox()
|
||||
{
|
||||
@ -61,7 +61,7 @@ using namespace GUIEngine;
|
||||
Widget::Widget(WidgetType type, bool reserve_id)
|
||||
{
|
||||
m_magic_number = 0xCAFEC001;
|
||||
|
||||
|
||||
m_x = -1;
|
||||
m_y = -1;
|
||||
m_w = -1;
|
||||
@ -82,25 +82,25 @@ Widget::Widget(WidgetType type, bool reserve_id)
|
||||
m_is_bounding_box_round = false;
|
||||
m_has_tooltip = false;
|
||||
m_is_text_rtl = false;
|
||||
|
||||
|
||||
m_absolute_x = m_absolute_y = m_absolute_w = m_absolute_h = -1;
|
||||
m_relative_x = m_relative_y = m_relative_w = m_relative_h = -1;
|
||||
m_absolute_reverse_x = m_absolute_reverse_y = -1;
|
||||
|
||||
|
||||
|
||||
|
||||
m_tab_down_root = -1;
|
||||
m_tab_up_root = -1;
|
||||
|
||||
|
||||
for (int n=0; n<MAX_PLAYER_COUNT; n++)
|
||||
{
|
||||
m_player_focus[n] = false;
|
||||
m_selected[n] = false;
|
||||
}
|
||||
|
||||
|
||||
m_reserved_id = -1;
|
||||
m_deactivated = false;
|
||||
m_badges = 0;
|
||||
|
||||
|
||||
// set a default value, derivates can override this as they wish
|
||||
m_check_inside_me = (m_type == WTYPE_DIV);
|
||||
}
|
||||
@ -110,7 +110,7 @@ Widget::Widget(WidgetType type, bool reserve_id)
|
||||
Widget::~Widget()
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
// If any player focused this widget, unset that focus
|
||||
for (int n=0; n<MAX_PLAYER_COUNT; n++)
|
||||
{
|
||||
@ -119,10 +119,10 @@ Widget::~Widget()
|
||||
GUIEngine::focusNothingForPlayer(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_magic_number = 0xDEADBEEF;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void Widget::setText(const wchar_t *s)
|
||||
{
|
||||
@ -136,9 +136,9 @@ void Widget::setText(const wchar_t *s)
|
||||
void Widget::elementRemoved()
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
m_element = NULL;
|
||||
|
||||
|
||||
// If any player focused this widget, unset that focus
|
||||
for (int n=0; n<MAX_PLAYER_COUNT; n++)
|
||||
{
|
||||
@ -147,13 +147,13 @@ void Widget::elementRemoved()
|
||||
GUIEngine::focusNothingForPlayer(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void Widget::setActivated()
|
||||
{
|
||||
{
|
||||
// even if this one is already active, do it anyway on purpose, maybe the
|
||||
// children widgets need to be updated
|
||||
m_deactivated = false;
|
||||
@ -200,10 +200,10 @@ namespace GUIEngine
|
||||
// IDs must not start at 0, since it appears their GUI engine hardcodes some ID values
|
||||
const unsigned int FOCUSABLE_IDS_BASE = 100;
|
||||
const unsigned int UNFOCUSABLE_IDS_BASE = 1000;
|
||||
|
||||
|
||||
/** Used to assign irrLicht IDs to widgets dynamically */
|
||||
static unsigned int id_counter = FOCUSABLE_IDS_BASE;
|
||||
|
||||
|
||||
/** for items that can't be reached with keyboard navigation but can be clicked */
|
||||
static unsigned int id_counter_2 = UNFOCUSABLE_IDS_BASE;
|
||||
}
|
||||
@ -221,7 +221,7 @@ int Widget::getNewNoFocusID()
|
||||
bool Widget::isFocusableId(const int id)
|
||||
{
|
||||
if (id < 0) return false;
|
||||
|
||||
|
||||
if ((unsigned int)id >= UNFOCUSABLE_IDS_BASE) return false;
|
||||
else return true;
|
||||
}
|
||||
@ -254,29 +254,29 @@ void Widget::add()
|
||||
* for additionnal players
|
||||
*/
|
||||
void Widget::setFocusForPlayer(const int playerID)
|
||||
{
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
// Unset focus flag on previous widget that had focus
|
||||
if (GUIEngine::getFocusForPlayer(playerID) != NULL)
|
||||
{
|
||||
GUIEngine::getFocusForPlayer(playerID)->unfocused(playerID, this);
|
||||
GUIEngine::getFocusForPlayer(playerID)->m_player_focus[playerID] = false;
|
||||
}
|
||||
|
||||
|
||||
m_player_focus[playerID] = true;
|
||||
GUIEngine::Private::g_focus_for_player[playerID] = this;
|
||||
|
||||
// Callback
|
||||
this->focused(playerID);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void Widget::unsetFocusForPlayer(const int playerID)
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
if (m_player_focus[playerID]) this->unfocused(playerID, NULL);
|
||||
m_player_focus[playerID] = false;
|
||||
}
|
||||
@ -289,7 +289,7 @@ void Widget::unsetFocusForPlayer(const int playerID)
|
||||
bool Widget::isFocusedForPlayer(const int playerID)
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
return m_player_focus[playerID];
|
||||
}
|
||||
|
||||
@ -298,12 +298,12 @@ bool Widget::isFocusedForPlayer(const int playerID)
|
||||
void Widget::move(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
|
||||
|
||||
if (m_element != NULL)
|
||||
m_element->setRelativePosition( core::rect < s32 > (x, y, x+w, y+h) );
|
||||
}
|
||||
@ -332,7 +332,7 @@ void Widget::setVisible(bool visible)
|
||||
m_element->setVisible(visible);
|
||||
}
|
||||
m_deactivated = !visible;
|
||||
|
||||
|
||||
const int childrenCount = m_children.size();
|
||||
for (int n=0; n<childrenCount; n++)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border,
|
||||
CurrentTextRect(0,0,1,1), FrameRect(rectangle)
|
||||
{
|
||||
m_rtl = is_rtl;
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIEditBox");
|
||||
#endif
|
||||
@ -311,7 +311,7 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case KEY_KEY_V:
|
||||
if ( !isEnabled() )
|
||||
break;
|
||||
@ -432,7 +432,7 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
||||
textChanged = true;
|
||||
return true;
|
||||
*/
|
||||
|
||||
|
||||
case KEY_END:
|
||||
if (!m_rtl)
|
||||
{
|
||||
@ -862,7 +862,7 @@ void CGUIEditBox::draw()
|
||||
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
|
||||
false, true, &localClipRect);
|
||||
}
|
||||
|
||||
|
||||
// draw mark and marked text
|
||||
if (focus && MarkBegin != MarkEnd && i >= hlineStart && i < hlineStart + hlineCount)
|
||||
{
|
||||
@ -933,12 +933,12 @@ void CGUIEditBox::draw()
|
||||
//CurrentTextRect.UpperLeftCorner.X += charcursorpos;
|
||||
|
||||
setTextRect(0);
|
||||
|
||||
|
||||
core::rect< s32 > caret_rect = CurrentTextRect;
|
||||
caret_rect.UpperLeftCorner.X += charcursorpos - 1;
|
||||
caret_rect.LowerRightCorner.X = caret_rect.UpperLeftCorner.X + 2;
|
||||
irr_driver->getVideoDriver()->draw2DRectangle( video::SColor(255,0,0,0), caret_rect );
|
||||
|
||||
|
||||
/*
|
||||
font->draw(L"_", CurrentTextRect,
|
||||
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
|
||||
|
@ -21,7 +21,7 @@ using namespace gui;
|
||||
public:
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle, bool is_rtl);
|
||||
@ -118,7 +118,7 @@ using namespace gui;
|
||||
virtual irr::gui::IGUIFont* getOverrideFont() const { return NULL; }
|
||||
virtual irr::gui::IGUIFont* getActiveFont() const { return NULL; }
|
||||
virtual void setDrawBackground(bool) { }
|
||||
|
||||
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
@ -155,7 +155,7 @@ using namespace gui;
|
||||
u32 Max;
|
||||
|
||||
bool m_rtl;
|
||||
|
||||
|
||||
bool WordWrap, MultiLine, AutoScroll, PasswordBox;
|
||||
wchar_t PasswordChar;
|
||||
EGUI_ALIGNMENT HAlign, VAlign;
|
||||
|
@ -41,22 +41,22 @@ BubbleWidget::BubbleWidget() : Widget(WTYPE_BUBBLE)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void BubbleWidget::add()
|
||||
{
|
||||
{
|
||||
m_shrinked_size = rect<s32>(m_x, m_y, m_x + m_w - BUBBLE_MARGIN_ON_RIGHT, m_y + m_h);
|
||||
stringw message = getText();
|
||||
|
||||
m_shrinked_size.LowerRightCorner.Y -= BOTTOM_MARGIN;
|
||||
|
||||
|
||||
IGUIStaticText* irrwidget;
|
||||
irrwidget = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), m_shrinked_size,
|
||||
false, true /* word wrap */, m_parent,
|
||||
(m_focusable ? getNewID() : getNewNoFocusID()));
|
||||
irrwidget->setTextRestrainedInside(false);
|
||||
|
||||
|
||||
#if IRRLICHT_VERSION_MAJOR > 1 || (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8)
|
||||
irrwidget->setRightToLeft( translations->isRTLLanguage() );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
m_element = irrwidget;
|
||||
replaceText();
|
||||
@ -91,7 +91,7 @@ void BubbleWidget::replaceText()
|
||||
{
|
||||
m_expanded_size.UpperLeftCorner.Y -= additionalNeededSize/2 + 10;
|
||||
m_expanded_size.LowerRightCorner.Y += additionalNeededSize/2 + 10;
|
||||
|
||||
|
||||
// reduce text to fit in the available space if it's too long
|
||||
if (translations->isRTLLanguage())
|
||||
{
|
||||
@ -128,19 +128,19 @@ void BubbleWidget::setText(const irr::core::stringw &s)
|
||||
void BubbleWidget::updateSize()
|
||||
{
|
||||
core::rect<s32> currsize = m_shrinked_size;
|
||||
|
||||
|
||||
const int y1_top = m_shrinked_size.UpperLeftCorner.Y;
|
||||
const int y1_bottom = m_shrinked_size.LowerRightCorner.Y;
|
||||
|
||||
|
||||
const int y2_top = m_expanded_size.UpperLeftCorner.Y;
|
||||
const int y2_bottom = m_expanded_size.LowerRightCorner.Y;
|
||||
|
||||
|
||||
currsize.UpperLeftCorner.Y = (int)(y1_top + (y2_top - y1_top)*m_zoom);
|
||||
currsize.LowerRightCorner.Y = (int)(y1_bottom
|
||||
currsize.LowerRightCorner.Y = (int)(y1_bottom
|
||||
+(y2_bottom - y1_bottom)*m_zoom);
|
||||
|
||||
m_element->setRelativePosition(currsize);
|
||||
|
||||
|
||||
if (m_zoom > 0.5f)
|
||||
{
|
||||
getIrrlichtElement<IGUIStaticText>()->setText(getText().c_str());
|
||||
@ -159,10 +159,10 @@ EventPropagation BubbleWidget::focused(const int playerID)
|
||||
{
|
||||
// bring element to top (with a hack because irrlicht does not appear to offer a built-in way to do this)
|
||||
m_element->grab();
|
||||
|
||||
|
||||
IGUIElement* parent = m_parent;
|
||||
if (parent == NULL) parent = GUIEngine::getGUIEnv()->getRootGUIElement();
|
||||
|
||||
|
||||
parent->removeChild(m_element);
|
||||
parent->addChild(m_element);
|
||||
m_element->drop();
|
||||
|
@ -39,7 +39,7 @@ void ButtonWidget::add()
|
||||
m_element = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent,
|
||||
(m_reserved_id == -1 ? getNewID() : m_reserved_id),
|
||||
message.c_str(), L"");
|
||||
|
||||
|
||||
m_id = m_element->getID();
|
||||
m_element->setTabOrder(m_id);
|
||||
m_element->setTabGroup(false);
|
||||
@ -51,7 +51,7 @@ void ButtonWidget::setLabel(const irr::core::stringw &label)
|
||||
{
|
||||
// This method should only be called AFTER a widget is added
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
m_element->setText( label.c_str() );
|
||||
setText(label);
|
||||
}
|
||||
|
@ -39,23 +39,23 @@ void CheckBoxWidget::add()
|
||||
rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h);
|
||||
//stringw& message = m_text;
|
||||
//m_element = GUIEngine::getGUIEnv()->addCheckBox(true /* checked */, widget_size, NULL, ++id_counter, message.c_str());
|
||||
|
||||
|
||||
m_element = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, getNewID(), L"");
|
||||
m_id = m_element->getID();
|
||||
m_element->setTabOrder(m_id);
|
||||
m_element->setTabGroup(false);
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation CheckBoxWidget::transmitEvent(Widget* w,
|
||||
const std::string& originator,
|
||||
EventPropagation CheckBoxWidget::transmitEvent(Widget* w,
|
||||
const std::string& originator,
|
||||
const int playerID)
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
|
||||
/* toggle */
|
||||
m_state = !m_state;
|
||||
|
||||
|
||||
/* notify main event handler */
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ DynamicRibbonWidget::DynamicRibbonWidget(const bool combo, const bool multi_row)
|
||||
m_check_inside_me = true;
|
||||
m_supports_multiplayer = true;
|
||||
m_scrolling_enabled = true;
|
||||
|
||||
|
||||
// by default, set all players to have no selection in this ribbon
|
||||
for (int n=0; n<MAX_PLAYER_COUNT; n++)
|
||||
{
|
||||
m_selected_item[n] = -1;
|
||||
}
|
||||
m_selected_item[0] = 0; // only player 0 has a selection by default
|
||||
|
||||
|
||||
m_item_count_hint = 0;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -87,9 +87,9 @@ void estimateIconAreaFor(const int rowCount, const int wantedIconWidth,
|
||||
float icon_height = (float)row_height;
|
||||
float icon_width = row_height * iconAspectRatio;
|
||||
*itemHeight = int(icon_height);
|
||||
|
||||
|
||||
const int icons_per_row = std::min(int(width / icon_width), int(width / wantedIconWidth));
|
||||
|
||||
|
||||
*visibleItems = std::min(maxIcons, icons_per_row * rowCount);
|
||||
*takenArea = int(*visibleItems * icon_width * icon_height);
|
||||
}
|
||||
@ -99,12 +99,12 @@ void DynamicRibbonWidget::add()
|
||||
//printf("****DynamicRibbonWidget::add()****\n");
|
||||
|
||||
m_has_label = (m_properties[PROP_LABELS_LOCATION] == "bottom");
|
||||
|
||||
|
||||
assert( m_properties[PROP_LABELS_LOCATION] == "bottom" ||
|
||||
m_properties[PROP_LABELS_LOCATION] == "each" ||
|
||||
m_properties[PROP_LABELS_LOCATION] == "none" ||
|
||||
m_properties[PROP_LABELS_LOCATION] == "");
|
||||
|
||||
|
||||
if (m_has_label)
|
||||
{
|
||||
// m_label_height contains the height of ONE text line
|
||||
@ -114,7 +114,7 @@ void DynamicRibbonWidget::add()
|
||||
{
|
||||
m_label_height = 0;
|
||||
}
|
||||
|
||||
|
||||
// ----- add dynamic label at bottom
|
||||
if (m_has_label)
|
||||
{
|
||||
@ -127,7 +127,7 @@ void DynamicRibbonWidget::add()
|
||||
m_label->setTextAlignment( EGUIA_CENTER, EGUIA_UPPERLEFT );
|
||||
m_label->setWordWrap(true);
|
||||
}
|
||||
|
||||
|
||||
// ---- add arrow buttons on each side
|
||||
if (m_left_widget != NULL)
|
||||
{
|
||||
@ -138,11 +138,11 @@ void DynamicRibbonWidget::add()
|
||||
}
|
||||
m_left_widget = new IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO, false);
|
||||
m_right_widget = new IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO, false);
|
||||
|
||||
|
||||
const int average_y = m_y + (m_h - m_label_height)/2;
|
||||
m_arrows_w = 40;
|
||||
const int button_h = 50;
|
||||
|
||||
|
||||
// right arrow
|
||||
rect<s32> right_arrow_location = rect<s32>(m_x + m_w - m_arrows_w,
|
||||
average_y - button_h/2,
|
||||
@ -160,7 +160,7 @@ void DynamicRibbonWidget::add()
|
||||
m_right_widget->setHighlightedImage(GUIEngine::getSkin()->getImage("right_arrow::focus"));
|
||||
|
||||
m_children.push_back( m_right_widget );
|
||||
|
||||
|
||||
// left arrow
|
||||
rect<s32> left_arrow_location = rect<s32>(m_x,
|
||||
average_y - button_h/2,
|
||||
@ -179,31 +179,31 @@ void DynamicRibbonWidget::add()
|
||||
m_left_widget->setHighlightedImage(GUIEngine::getSkin()->getImage("left_arrow::focus"));
|
||||
|
||||
m_children.push_back( m_left_widget );
|
||||
|
||||
|
||||
assert( m_left_widget->ok() );
|
||||
assert( m_right_widget->ok() );
|
||||
m_left_widget->m_element->setVisible(true);
|
||||
|
||||
// ---- Determine number of rows
|
||||
|
||||
|
||||
// Find children size (and ratio)
|
||||
m_child_width = atoi(m_properties[PROP_CHILD_WIDTH].c_str());
|
||||
m_child_height = atoi(m_properties[PROP_CHILD_HEIGHT].c_str());
|
||||
|
||||
|
||||
if (m_child_width <= 0 || m_child_height <= 0)
|
||||
{
|
||||
std::cerr << "/!\\ Warning /!\\ : ribbon grid widgets require 'child_width' and 'child_height' arguments" << std::endl;
|
||||
m_child_width = 256;
|
||||
m_child_height = 256;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (m_multi_row)
|
||||
{
|
||||
// determine row amount
|
||||
const float aspect_ratio = (float)m_child_width / (float)m_child_height;
|
||||
// const int count = m_items.size();
|
||||
|
||||
|
||||
m_row_amount = -1;
|
||||
float max_score_so_far = -1;
|
||||
|
||||
@ -219,9 +219,9 @@ void DynamicRibbonWidget::add()
|
||||
int visible_items;
|
||||
int taken_area;
|
||||
int item_height;
|
||||
|
||||
|
||||
int item_count = m_item_count_hint;
|
||||
|
||||
|
||||
if (item_count < 1)
|
||||
{
|
||||
item_count = m_items.size();
|
||||
@ -232,10 +232,10 @@ void DynamicRibbonWidget::add()
|
||||
// No idea so make assumptions
|
||||
item_count = 20;
|
||||
}
|
||||
|
||||
|
||||
estimateIconAreaFor(row_count, m_child_width, m_w, m_h - m_label_height,
|
||||
aspect_ratio, item_count, &visible_items, &taken_area, &item_height);
|
||||
|
||||
|
||||
// FIXME: this system to determine the best number of columns is really complicated!
|
||||
// the score is computed from taken screen area AND visible item count.
|
||||
// A number of rows that allows for the screen space to be used a lot will
|
||||
@ -243,22 +243,22 @@ void DynamicRibbonWidget::add()
|
||||
// will be penalized. A configuration that makes items much smaller than
|
||||
// requested in the XML file will also be penalized.
|
||||
float ratio = (float)item_height / (float)m_child_height;
|
||||
|
||||
|
||||
// huge icons not so good either
|
||||
if (ratio > 1.0f)
|
||||
{
|
||||
ratio = 1.0f - ratio/5.0f;
|
||||
if (ratio < 0.0f) ratio = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
float total_area = (float)(m_w * m_h);
|
||||
const float score = log(2.0f*visible_items) *
|
||||
std::min(ratio, 1.0f) * std::min(taken_area/total_area, 1.0f);
|
||||
|
||||
|
||||
//std::cout << " " << row_count << " rows : " << visible_items << " visible items; area = "
|
||||
// << taken_area << "; size penalty = " << std::min((float)item_height / (float)m_child_height, 1.0f)
|
||||
// << "; score = " << score << "\n";
|
||||
|
||||
|
||||
if (score > max_score_so_far)
|
||||
{
|
||||
m_row_amount = row_count;
|
||||
@ -267,16 +267,16 @@ void DynamicRibbonWidget::add()
|
||||
}
|
||||
assert(m_row_amount != -1);
|
||||
}
|
||||
|
||||
|
||||
// m_row_amount = (int)round((m_h - m_label_height) / (float)m_child_height);
|
||||
|
||||
|
||||
if (m_properties[PROP_MAX_ROWS].size() > 0)
|
||||
{
|
||||
const int max_rows = atoi(m_properties[PROP_MAX_ROWS].c_str());
|
||||
if (max_rows < 1)
|
||||
{
|
||||
std::cout << "/!\\ WARNING : the 'max_rows' property must be an integer greater than zero."
|
||||
<< " Ingoring current value '" << m_properties[PROP_MAX_ROWS] << "'\n";
|
||||
<< " Ingoring current value '" << m_properties[PROP_MAX_ROWS] << "'\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -288,11 +288,11 @@ void DynamicRibbonWidget::add()
|
||||
{
|
||||
m_row_amount = 1;
|
||||
}
|
||||
|
||||
|
||||
assert( m_left_widget->ok() );
|
||||
assert( m_right_widget->ok() );
|
||||
m_left_widget->m_element->setVisible(true);
|
||||
|
||||
|
||||
// get and build a list of IDs (by now we may not yet know everything about items,
|
||||
// but we need to get IDs *now* in order for tabbing to work.
|
||||
m_ids.resize(m_row_amount);
|
||||
@ -301,14 +301,14 @@ void DynamicRibbonWidget::add()
|
||||
m_ids[i] = getNewID();
|
||||
//std::cout << "ribbon : getNewID returns " << m_ids[i] << std::endl;
|
||||
}
|
||||
|
||||
|
||||
buildInternalStructure();
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void DynamicRibbonWidget::buildInternalStructure()
|
||||
{
|
||||
//printf("****DynamicRibbonWidget::buildInternalStructure()****\n");
|
||||
|
||||
|
||||
// ---- Clean-up what was previously there
|
||||
for (int i=0; i<m_children.size(); i++)
|
||||
{
|
||||
@ -322,16 +322,16 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
}
|
||||
}
|
||||
m_rows.clearWithoutDeleting(); // rows already deleted above, don't double-delete
|
||||
|
||||
|
||||
m_left_widget->m_element->setVisible(true);
|
||||
assert( m_left_widget->ok() );
|
||||
assert( m_right_widget->ok() );
|
||||
|
||||
|
||||
// ---- determine column amount
|
||||
const float row_height = (float)(m_h - m_label_height)/(float)m_row_amount;
|
||||
float ratio_zoom = (float)row_height / (float)(m_child_height - m_label_height);
|
||||
m_col_amount = (int)round( m_w / ( m_child_width*ratio_zoom ) );
|
||||
|
||||
|
||||
// ajust column amount to not add more item slots than we actually need
|
||||
const int item_count = m_items.size();
|
||||
//std::cout << "item_count=" << item_count << ", row_amount*m_col_amount=" << m_row_amount*m_col_amount << std::endl;
|
||||
@ -340,10 +340,10 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
m_col_amount = (int)ceil((float)item_count/(float)m_row_amount);
|
||||
//std::cout << "Adjusting m_col_amount to be " << m_col_amount << std::endl;
|
||||
}
|
||||
|
||||
|
||||
assert( m_left_widget->ok() );
|
||||
assert( m_right_widget->ok() );
|
||||
|
||||
|
||||
// Hide arrows when everything is visible
|
||||
if (item_count <= m_row_amount*m_col_amount)
|
||||
{
|
||||
@ -357,7 +357,7 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
m_left_widget->m_element->setVisible(true);
|
||||
m_right_widget->m_element->setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
// ---- add rows
|
||||
int added_item_count = 0;
|
||||
for (int n=0; n<m_row_amount; n++)
|
||||
@ -373,7 +373,7 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
}
|
||||
ribbon->setListener(this);
|
||||
ribbon->m_reserved_id = m_ids[n];
|
||||
|
||||
|
||||
ribbon->m_x = m_x + (m_scrolling_enabled ? m_arrows_w : 0);
|
||||
ribbon->m_y = m_y + (int)(n*row_height);
|
||||
ribbon->m_w = m_w - (m_scrolling_enabled ? m_arrows_w*2 : 0);
|
||||
@ -384,7 +384,7 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
name << this->m_properties[PROP_ID] << "_row" << n;
|
||||
ribbon->m_properties[PROP_ID] = name.str();
|
||||
ribbon->m_event_handler = this;
|
||||
|
||||
|
||||
// add columns
|
||||
for (int i=0; i<m_col_amount; i++)
|
||||
{
|
||||
@ -392,7 +392,7 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
// (Yeah, that's complicated, but screenshots are saved compressed horizontally so it's hard to be clean)
|
||||
IconButtonWidget* icon = new IconButtonWidget(IconButtonWidget::SCALE_MODE_STRETCH, false, true);
|
||||
icon->m_properties[PROP_ICON]="textures/transparence.png";
|
||||
|
||||
|
||||
// set size to get proper ratio (as most textures are saved scaled down to 256x256)
|
||||
icon->m_properties[PROP_WIDTH] = m_properties[PROP_CHILD_WIDTH];
|
||||
icon->m_properties[PROP_HEIGHT] = m_properties[PROP_CHILD_HEIGHT];
|
||||
@ -402,17 +402,17 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
// If we want each icon to have its own label, we must make it non-empty, otherwise
|
||||
// it will assume there is no label and none will be created (FIXME: that's ugly)
|
||||
if (m_properties[PROP_LABELS_LOCATION] == "each") icon->m_text = " ";
|
||||
|
||||
|
||||
// std::cout << "ribbon text = " << m_properties[PROP_TEXT].c_str() << std::endl;
|
||||
|
||||
|
||||
ribbon->m_children.push_back( icon );
|
||||
added_item_count++;
|
||||
|
||||
|
||||
// stop adding columns when we have enough items
|
||||
if (added_item_count == item_count)
|
||||
{
|
||||
assert(!m_scrolling_enabled); // we can see all items, so scrolling must be off
|
||||
break;
|
||||
break;
|
||||
}
|
||||
else if (added_item_count > item_count)
|
||||
{
|
||||
@ -423,15 +423,15 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
m_children.push_back( ribbon );
|
||||
m_rows.push_back( ribbon );
|
||||
ribbon->add();
|
||||
|
||||
|
||||
// stop filling rows when we have enough items
|
||||
if (added_item_count == item_count)
|
||||
{
|
||||
assert(!m_scrolling_enabled); // we can see all items, so scrolling must be off
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!m_scrolling_enabled)
|
||||
{
|
||||
@ -457,7 +457,7 @@ void DynamicRibbonWidget::addItem( const irr::core::stringw& user_name, const st
|
||||
desc.m_badges = badges;
|
||||
desc.m_animated = false;
|
||||
desc.m_image_path_type = image_path_type;
|
||||
|
||||
|
||||
m_items.push_back(desc);
|
||||
}
|
||||
|
||||
@ -476,17 +476,17 @@ void DynamicRibbonWidget::addAnimatedItem( const irr::core::stringw& user_name,
|
||||
desc.m_curr_time = 0.0f;
|
||||
desc.m_time_per_frame = time_per_frame;
|
||||
desc.m_image_path_type = image_path_type;
|
||||
|
||||
|
||||
m_items.push_back(desc);
|
||||
|
||||
|
||||
if (!m_animated_contents)
|
||||
{
|
||||
m_animated_contents = true;
|
||||
|
||||
|
||||
/*
|
||||
FIXME: remove this unclean thing, I think irrlicht provides this feature:
|
||||
virtual void IGUIElement::OnPostRender (u32 timeMs)
|
||||
\brief animate the element and its children.
|
||||
\brief animate the element and its children.
|
||||
*/
|
||||
GUIEngine::needsUpdate.push_back(this);
|
||||
}
|
||||
@ -506,7 +506,7 @@ void DynamicRibbonWidget::elementRemoved()
|
||||
m_rows.clearWithoutDeleting();
|
||||
m_left_widget = NULL;
|
||||
m_right_widget = NULL;
|
||||
|
||||
|
||||
m_hover_listeners.clearAndDeleteAll();
|
||||
}
|
||||
|
||||
@ -519,9 +519,9 @@ void DynamicRibbonWidget::elementRemoved()
|
||||
const std::string& DynamicRibbonWidget::getSelectionIDString(const int playerID)
|
||||
{
|
||||
RibbonWidget* row = (RibbonWidget*)(m_rows.size() == 1 ? m_rows.get(0) : getSelectedRibbon(playerID));
|
||||
|
||||
|
||||
if (row != NULL) return row->getSelectionIDString(playerID);
|
||||
|
||||
|
||||
static const std::string nothing = "";
|
||||
return nothing;
|
||||
}
|
||||
@ -530,9 +530,9 @@ const std::string& DynamicRibbonWidget::getSelectionIDString(const int playerID)
|
||||
irr::core::stringw DynamicRibbonWidget::getSelectionText(const int playerID)
|
||||
{
|
||||
RibbonWidget* row = (RibbonWidget*)(m_rows.size() == 1 ? m_rows.get(0) : getSelectedRibbon(playerID));
|
||||
|
||||
|
||||
if (row != NULL) return row->getSelectionText(playerID);
|
||||
|
||||
|
||||
static const irr::core::stringw nothing = "";
|
||||
return nothing;
|
||||
}
|
||||
@ -548,12 +548,12 @@ RibbonWidget* DynamicRibbonWidget::getRowContaining(Widget* w)
|
||||
if (row->m_children.contains( w ) ) return row;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
RibbonWidget* DynamicRibbonWidget::getSelectedRibbon(const int playerID)
|
||||
{
|
||||
{
|
||||
RibbonWidget* row;
|
||||
for_in (row, m_rows)
|
||||
{
|
||||
@ -562,7 +562,7 @@ RibbonWidget* DynamicRibbonWidget::getSelectedRibbon(const int playerID)
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -577,16 +577,16 @@ void DynamicRibbonWidget::registerHoverListener(DynamicRibbonHoverListener* list
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation DynamicRibbonWidget::rightPressed(const int playerID)
|
||||
{
|
||||
{
|
||||
if (m_deactivated) return EVENT_LET;
|
||||
|
||||
|
||||
RibbonWidget* w = getSelectedRibbon(playerID);
|
||||
if (w != NULL)
|
||||
{
|
||||
updateLabel();
|
||||
|
||||
|
||||
propagateSelection();
|
||||
|
||||
|
||||
const int listenerAmount = m_hover_listeners.size();
|
||||
for (int n=0; n<listenerAmount; n++)
|
||||
{
|
||||
@ -595,25 +595,25 @@ EventPropagation DynamicRibbonWidget::rightPressed(const int playerID)
|
||||
}
|
||||
}
|
||||
//std::cout << "rightpressed (dynamic ribbon) " << m_properties[PROP_ID] << "\n";
|
||||
|
||||
|
||||
assert(m_rows.size() >= 1);
|
||||
if (m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return EVENT_BLOCK;
|
||||
|
||||
|
||||
//std::cout << " rightpressed returning EVENT_LET\n";
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation DynamicRibbonWidget::leftPressed(const int playerID)
|
||||
{
|
||||
{
|
||||
if (m_deactivated) return EVENT_LET;
|
||||
|
||||
|
||||
RibbonWidget* w = getSelectedRibbon(playerID);
|
||||
if (w != NULL)
|
||||
{
|
||||
updateLabel();
|
||||
propagateSelection();
|
||||
|
||||
|
||||
DynamicRibbonHoverListener* listener;
|
||||
for_in( listener, m_hover_listeners )
|
||||
{
|
||||
@ -621,22 +621,22 @@ EventPropagation DynamicRibbonWidget::leftPressed(const int playerID)
|
||||
w->getSelectionText(playerID), playerID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
assert(m_rows.size() >= 1);
|
||||
if (m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return EVENT_BLOCK;
|
||||
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation DynamicRibbonWidget::transmitEvent(Widget* w,
|
||||
EventPropagation DynamicRibbonWidget::transmitEvent(Widget* w,
|
||||
const std::string& originator,
|
||||
const int playerID)
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
|
||||
if (m_deactivated) return EVENT_LET;
|
||||
|
||||
|
||||
if (originator=="left")
|
||||
{
|
||||
scroll(-1);
|
||||
@ -647,7 +647,7 @@ EventPropagation DynamicRibbonWidget::transmitEvent(Widget* w,
|
||||
scroll(1);
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
|
||||
|
||||
// find selection in current ribbon
|
||||
if (m_combo)
|
||||
{
|
||||
@ -658,7 +658,7 @@ EventPropagation DynamicRibbonWidget::transmitEvent(Widget* w,
|
||||
if (m_selected_item[playerID] >= (int)m_items.size()) m_selected_item[playerID] -= m_items.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -669,7 +669,7 @@ EventPropagation DynamicRibbonWidget::mouseHovered(Widget* child, const int play
|
||||
|
||||
updateLabel();
|
||||
propagateSelection();
|
||||
|
||||
|
||||
if (getSelectedRibbon(playerID) != NULL)
|
||||
{
|
||||
DynamicRibbonHoverListener* listener;
|
||||
@ -679,7 +679,7 @@ EventPropagation DynamicRibbonWidget::mouseHovered(Widget* child, const int play
|
||||
getSelectedRibbon(playerID)->getSelectionText(playerID), playerID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -687,21 +687,21 @@ EventPropagation DynamicRibbonWidget::focused(const int playerID)
|
||||
{
|
||||
Widget::focused(playerID);
|
||||
updateLabel();
|
||||
|
||||
|
||||
DynamicRibbonHoverListener* listener;
|
||||
|
||||
|
||||
if (getSelectedRibbon(playerID)->getSelectionIDString(playerID) == "")
|
||||
{
|
||||
//fprintf(stderr, "[DynamicRibbonWidget] WARNING: Can't find selection for player %i, selecting first item\n", playerID);
|
||||
getSelectedRibbon(playerID)->setSelection(0, playerID);
|
||||
}
|
||||
|
||||
|
||||
for_in( listener, m_hover_listeners )
|
||||
{
|
||||
listener->onSelectionChanged(this, getSelectedRibbon(playerID)->getSelectionIDString(playerID),
|
||||
getSelectedRibbon(playerID)->getSelectionText(playerID), playerID);
|
||||
}
|
||||
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
@ -717,27 +717,27 @@ void DynamicRibbonWidget::onRibbonWidgetScroll(const int delta_x)
|
||||
void DynamicRibbonWidget::onRibbonWidgetFocus(RibbonWidget* emitter, const int playerID)
|
||||
{
|
||||
if (m_deactivated) return;
|
||||
|
||||
|
||||
if (emitter->m_selection[playerID] >= emitter->m_children.size())
|
||||
{
|
||||
emitter->m_selection[playerID] = emitter->m_children.size()-1;
|
||||
}
|
||||
|
||||
|
||||
updateLabel(emitter);
|
||||
|
||||
|
||||
DynamicRibbonHoverListener* listener;
|
||||
|
||||
|
||||
if (emitter->getSelectionIDString(playerID) == "")
|
||||
{
|
||||
//fprintf(stderr, "[DynamicRibbonWidget] WARNING: Can't find selection for player %i, selecting first item\n", playerID);
|
||||
emitter->setSelection(0, playerID);
|
||||
}
|
||||
|
||||
|
||||
for_in( listener, m_hover_listeners )
|
||||
{
|
||||
listener->onSelectionChanged(this, emitter->getSelectionIDString(playerID),
|
||||
emitter->getSelectionText(playerID), playerID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -748,19 +748,19 @@ void DynamicRibbonWidget::onRibbonWidgetFocus(RibbonWidget* emitter, const int p
|
||||
void DynamicRibbonWidget::scroll(const int x_delta)
|
||||
{
|
||||
if (m_deactivated) return;
|
||||
|
||||
|
||||
// Refuse to scroll when everything is visible
|
||||
if ((int)m_items.size() <= m_row_amount*m_col_amount) return;
|
||||
|
||||
|
||||
m_scroll_offset += x_delta;
|
||||
|
||||
|
||||
const int max_scroll = std::max(m_col_amount, m_needed_cols) - 1;
|
||||
|
||||
|
||||
if (m_scroll_offset < 0) m_scroll_offset = max_scroll;
|
||||
else if (m_scroll_offset > max_scroll) m_scroll_offset = 0;
|
||||
|
||||
|
||||
updateItemDisplay();
|
||||
|
||||
|
||||
// update selection markers in child ribbon
|
||||
if (m_combo)
|
||||
{
|
||||
@ -771,7 +771,7 @@ void DynamicRibbonWidget::scroll(const int x_delta)
|
||||
if (id < 0) id += m_items.size();
|
||||
ribbon->setSelection(id, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
/** DynamicRibbonWidget is made of several ribbons; each of them thus has
|
||||
@ -779,16 +779,16 @@ void DynamicRibbonWidget::scroll(const int x_delta)
|
||||
(i.e. you remain in the same column when pressing up/down), this method is
|
||||
used to ensure that all children ribbons always select the same column */
|
||||
void DynamicRibbonWidget::propagateSelection()
|
||||
{
|
||||
{
|
||||
for (int p=0; p<MAX_PLAYER_COUNT; p++)
|
||||
{
|
||||
// find selection in current ribbon
|
||||
RibbonWidget* selected_ribbon = (RibbonWidget*)getSelectedRibbon(p);
|
||||
if (selected_ribbon == NULL) continue;
|
||||
|
||||
|
||||
const int relative_selection = selected_ribbon->m_selection[p];
|
||||
float where = 0.0f;
|
||||
|
||||
|
||||
if (selected_ribbon->m_children.size() > 1)
|
||||
{
|
||||
where = (float)relative_selection / (float)(selected_ribbon->m_children.size() - 1);
|
||||
@ -797,7 +797,7 @@ void DynamicRibbonWidget::propagateSelection()
|
||||
{
|
||||
where = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
if (where < 0.0f) where = 0.0f;
|
||||
else if (where > 1.0f) where = 1.0f;
|
||||
|
||||
@ -806,7 +806,7 @@ void DynamicRibbonWidget::propagateSelection()
|
||||
m_selected_item[p] = relative_selection + m_scroll_offset;
|
||||
if (m_selected_item[p] >= (int)m_items.size()) m_selected_item[p] -= m_items.size();
|
||||
}
|
||||
|
||||
|
||||
// set same selection in all ribbons
|
||||
RibbonWidget* ribbon;
|
||||
for_in( ribbon, m_rows )
|
||||
@ -817,22 +817,22 @@ void DynamicRibbonWidget::propagateSelection()
|
||||
ribbon->updateSelection();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void DynamicRibbonWidget::updateLabel(RibbonWidget* from_this_ribbon)
|
||||
{
|
||||
if (!m_has_label) return;
|
||||
|
||||
|
||||
// only the master player can update the label
|
||||
const int playerID = PLAYER_ID_GAME_MASTER;
|
||||
|
||||
|
||||
RibbonWidget* row = from_this_ribbon ? from_this_ribbon : (RibbonWidget*)getSelectedRibbon(playerID);
|
||||
if (row == NULL) return;
|
||||
|
||||
|
||||
std::string selection_id = row->getSelectionIDString(playerID);
|
||||
|
||||
|
||||
const int amount = m_items.size();
|
||||
for (int n=0; n<amount; n++)
|
||||
{
|
||||
@ -842,7 +842,7 @@ void DynamicRibbonWidget::updateLabel(RibbonWidget* from_this_ribbon)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (selection_id == RibbonWidget::NO_ITEM_ID) m_label->setText( L"" );
|
||||
else m_label->setText( L"Unknown Item" );
|
||||
}
|
||||
@ -860,22 +860,22 @@ void DynamicRibbonWidget::updateItemDisplay()
|
||||
buildInternalStructure();
|
||||
m_previous_item_count = m_items.size();
|
||||
}
|
||||
|
||||
|
||||
// ---- some variables
|
||||
int icon_id = 0;
|
||||
|
||||
|
||||
const int row_amount = m_rows.size();
|
||||
const int item_amount = m_items.size();
|
||||
|
||||
|
||||
//FIXME: isn't this set by 'buildInternalStructure' already?
|
||||
m_needed_cols = (int)ceil( (float)item_amount / (float)row_amount );
|
||||
|
||||
|
||||
//const int max_scroll = std::max(m_col_amount, m_needed_cols) - 1;
|
||||
|
||||
|
||||
// the number of items that fit perfectly the number of rows we have
|
||||
// (this value will be useful to compute scrolling)
|
||||
int fitting_item_amount = (m_scrolling_enabled ? m_needed_cols * row_amount : m_items.size());
|
||||
|
||||
|
||||
// ---- to determine which items go in which cell of the dynamic ribbon now,
|
||||
// we create a temporary 2D table and fill them with the ID of the item
|
||||
// they need to display.
|
||||
@ -884,67 +884,67 @@ void DynamicRibbonWidget::updateItemDisplay()
|
||||
item_placement.resize(row_amount);
|
||||
for(int i=0; i<row_amount; i++)
|
||||
item_placement[i].resize(m_needed_cols);
|
||||
|
||||
|
||||
int counter = 0;
|
||||
|
||||
|
||||
#if CHATTY_ABOUT_ITEM_PLACEMENT
|
||||
std::cout << m_items.size() << " items to be placed:\n{\n";
|
||||
#endif
|
||||
|
||||
|
||||
for (int c=0; c<m_needed_cols; c++)
|
||||
{
|
||||
for (int r=0; r<row_amount; r++)
|
||||
{
|
||||
|
||||
|
||||
#if CHATTY_ABOUT_ITEM_PLACEMENT
|
||||
std::cout << " ";
|
||||
#endif
|
||||
|
||||
|
||||
const int items_in_row = m_rows[r].m_children.size();
|
||||
if (c >= items_in_row)
|
||||
{
|
||||
item_placement[r][c] = -1;
|
||||
|
||||
|
||||
#if CHATTY_ABOUT_ITEM_PLACEMENT
|
||||
std::cout << item_placement[r][c] << " ";
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int newVal = counter + m_scroll_offset*row_amount;
|
||||
while (newVal >= fitting_item_amount) newVal -= fitting_item_amount;
|
||||
item_placement[r][c] = newVal;
|
||||
|
||||
|
||||
#if CHATTY_ABOUT_ITEM_PLACEMENT
|
||||
std::cout << newVal << " ";
|
||||
#endif
|
||||
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
|
||||
#if CHATTY_ABOUT_ITEM_PLACEMENT
|
||||
std::cout << "\n";
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if CHATTY_ABOUT_ITEM_PLACEMENT
|
||||
std::cout << "}\n";
|
||||
#endif
|
||||
|
||||
|
||||
// ---- iterate through the rows, and set the items of each row to match those of the table
|
||||
for (int n=0; n<row_amount; n++)
|
||||
{
|
||||
RibbonWidget& row = m_rows[n];
|
||||
|
||||
|
||||
//std::cout << "Row " << n << "\n{\n";
|
||||
|
||||
|
||||
const unsigned int items_in_row = row.m_children.size();
|
||||
for (unsigned int i=0; i<items_in_row; i++)
|
||||
{
|
||||
IconButtonWidget* icon = dynamic_cast<IconButtonWidget*>(&row.m_children[i]);
|
||||
assert(icon != NULL);
|
||||
|
||||
|
||||
//FIXME : it is a bit hackish
|
||||
if(i < item_placement[n].size())
|
||||
{
|
||||
@ -955,16 +955,16 @@ void DynamicRibbonWidget::updateItemDisplay()
|
||||
m_items[icon_id].m_all_images[0] :
|
||||
m_items[icon_id].m_sshot_file);
|
||||
icon->setImage( item_icon.c_str(), m_items[icon_id].m_image_path_type );
|
||||
|
||||
|
||||
icon->m_properties[PROP_ID] = m_items[icon_id].m_code_name;
|
||||
icon->setLabel(m_items[icon_id].m_user_name);
|
||||
icon->m_text = m_items[icon_id].m_user_name;
|
||||
icon->m_badges = m_items[icon_id].m_badges;
|
||||
|
||||
|
||||
//std::cout << " item " << i << " is " << m_items[icon_id].m_code_name << "\n";
|
||||
|
||||
|
||||
//std::wcout << L"Setting widget text '" << icon->m_text.c_str() << L"'\n";
|
||||
|
||||
|
||||
// if the ribbon has no "ribbon-wide" label, call will do nothing
|
||||
row.setLabel(i, m_items[icon_id].m_user_name);
|
||||
}
|
||||
@ -988,19 +988,19 @@ void DynamicRibbonWidget::update(float dt)
|
||||
for (int n=0; n<row_amount; n++)
|
||||
{
|
||||
RibbonWidget& row = m_rows[n];
|
||||
|
||||
|
||||
const int items_in_row = row.m_children.size();
|
||||
for (int i=0; i<items_in_row; i++)
|
||||
{
|
||||
int col_scroll = i + m_scroll_offset;
|
||||
int item_id = (col_scroll)*row_amount + n;
|
||||
if (item_id >= (int)m_items.size()) item_id -= m_items.size();
|
||||
|
||||
|
||||
assert(item_id >= 0);
|
||||
assert(item_id < (int)m_items.size());
|
||||
|
||||
|
||||
//m_items[icon_id].
|
||||
|
||||
|
||||
if (m_items[item_id].m_animated)
|
||||
{
|
||||
const int frameBefore = (int)(m_items[item_id].m_curr_time / m_items[item_id].m_time_per_frame);
|
||||
@ -1008,13 +1008,13 @@ void DynamicRibbonWidget::update(float dt)
|
||||
m_items[item_id].m_curr_time += dt;
|
||||
int frameAfter = (int)(m_items[item_id].m_curr_time / m_items[item_id].m_time_per_frame);
|
||||
if (frameAfter == frameBefore) continue; // no frame change yet
|
||||
|
||||
|
||||
if (frameAfter >= (int)m_items[item_id].m_all_images.size())
|
||||
{
|
||||
m_items[item_id].m_curr_time = 0;
|
||||
frameAfter = 0;
|
||||
}
|
||||
|
||||
|
||||
IconButtonWidget* icon = dynamic_cast<IconButtonWidget*>(&row.m_children[i]);
|
||||
icon->setImage( m_items[item_id].m_all_images[frameAfter].c_str() );
|
||||
}
|
||||
@ -1029,7 +1029,7 @@ bool DynamicRibbonWidget::findItemInRows(const char* name, int* p_row, int* p_id
|
||||
{
|
||||
int row = -1;
|
||||
int id = -1;
|
||||
|
||||
|
||||
for (int r=0; r<m_rows.size(); r++)
|
||||
{
|
||||
id = m_rows[r].findItemNamed(name);
|
||||
@ -1039,7 +1039,7 @@ bool DynamicRibbonWidget::findItemInRows(const char* name, int* p_row, int* p_id
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*p_row = row;
|
||||
*p_id = id;
|
||||
return (row != -1);
|
||||
@ -1047,37 +1047,37 @@ bool DynamicRibbonWidget::findItemInRows(const char* name, int* p_row, int* p_id
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool DynamicRibbonWidget::setSelection(int item_id, const int playerID,
|
||||
const bool focusIt,
|
||||
bool DynamicRibbonWidget::setSelection(int item_id, const int playerID,
|
||||
const bool focusIt,
|
||||
bool evenIfDeactivated)
|
||||
{
|
||||
if (m_deactivated && !evenIfDeactivated) return false;
|
||||
|
||||
|
||||
//printf("****DynamicRibbonWidget::setSelection()****\n");
|
||||
|
||||
if ((unsigned int)item_id >= m_items.size()) return false;
|
||||
|
||||
|
||||
m_selected_item[playerID] = item_id;
|
||||
|
||||
|
||||
const std::string& name = m_items[item_id].m_code_name;
|
||||
|
||||
|
||||
int row;
|
||||
int id;
|
||||
|
||||
|
||||
int iterations = 0; // a safeguard to avoid infinite loops (should not happen normally)
|
||||
|
||||
|
||||
while (!findItemInRows(name.c_str(), &row, &id))
|
||||
{
|
||||
// if we get here it means the item is scrolled out. Try to find it.
|
||||
scroll(1);
|
||||
|
||||
|
||||
if (iterations > 50)
|
||||
{
|
||||
assert(false);
|
||||
std::cerr << "DynamicRibbonWidget::setSelection cannot find item " << item_id << " (" << name.c_str() << ")\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
iterations++;
|
||||
}
|
||||
|
||||
@ -1100,17 +1100,17 @@ bool DynamicRibbonWidget::setSelection(int item_id, const int playerID,
|
||||
playerID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
propagateSelection();
|
||||
return true;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
bool DynamicRibbonWidget::setSelection(const std::string &item_codename,
|
||||
bool DynamicRibbonWidget::setSelection(const std::string &item_codename,
|
||||
const int playerID, const bool focusIt,
|
||||
bool evenIfDeactivated)
|
||||
{
|
||||
if (m_deactivated && !evenIfDeactivated) return false;
|
||||
|
||||
|
||||
const int item_count = m_items.size();
|
||||
for (int n=0; n<item_count; n++)
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ IconButtonWidget::IconButtonWidget(ScaleMode scale_mode, const bool tab_stop,
|
||||
m_tab_stop = tab_stop;
|
||||
m_focusable = focusable;
|
||||
m_scale_mode = scale_mode;
|
||||
|
||||
|
||||
m_icon_path_type = pathType;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -66,7 +66,7 @@ void IconButtonWidget::add()
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_texture == NULL)
|
||||
{
|
||||
Log::error("icon_button",
|
||||
@ -82,22 +82,22 @@ void IconButtonWidget::add()
|
||||
{
|
||||
if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE)
|
||||
{
|
||||
m_highlight_texture =
|
||||
m_highlight_texture =
|
||||
irr_driver->getTexture(m_properties[PROP_FOCUS_ICON]);
|
||||
}
|
||||
else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE)
|
||||
{
|
||||
m_highlight_texture =
|
||||
m_highlight_texture =
|
||||
irr_driver->getTexture(file_manager->getDataDir() +
|
||||
m_properties[PROP_FOCUS_ICON]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// irrlicht widgets don't support scaling while keeping aspect ratio
|
||||
// so, happily, let's implement it ourselves
|
||||
float useAspectRatio = -1.0f;
|
||||
|
||||
|
||||
if (m_scale_mode == SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO)
|
||||
{
|
||||
useAspectRatio = (float)m_texture_w / (float)m_texture_h;
|
||||
@ -106,10 +106,10 @@ void IconButtonWidget::add()
|
||||
{
|
||||
useAspectRatio = m_custom_aspect_ratio;
|
||||
}
|
||||
|
||||
|
||||
int suggested_h = m_h;
|
||||
int suggested_w = (int)((useAspectRatio < 0 ? m_w : useAspectRatio * suggested_h));
|
||||
|
||||
|
||||
if (suggested_w > m_w)
|
||||
{
|
||||
const float needed_scale_factor = (float)m_w / (float)suggested_w;
|
||||
@ -118,12 +118,12 @@ void IconButtonWidget::add()
|
||||
}
|
||||
const int x_from = m_x + (m_w - suggested_w)/2; // center horizontally
|
||||
const int y_from = m_y + (m_h - suggested_h)/2; // center vertically
|
||||
|
||||
|
||||
rect<s32> widget_size = rect<s32>(x_from,
|
||||
y_from,
|
||||
x_from + suggested_w,
|
||||
y_from + suggested_h);
|
||||
|
||||
|
||||
IGUIButton* btn = GUIEngine::getGUIEnv()->addButton(widget_size,
|
||||
m_parent,
|
||||
(m_tab_stop ? getNewID() : getNewNoFocusID()),
|
||||
@ -132,17 +132,17 @@ void IconButtonWidget::add()
|
||||
btn->setTabStop(m_tab_stop);
|
||||
m_element = btn;
|
||||
m_id = m_element->getID();
|
||||
|
||||
|
||||
// ---- label if any
|
||||
const stringw& message = getText();
|
||||
if (message.size() > 0)
|
||||
{
|
||||
const int label_extra_size =
|
||||
const int label_extra_size =
|
||||
( m_properties[PROP_EXTEND_LABEL].size() == 0 ?
|
||||
0 : atoi(m_properties[PROP_EXTEND_LABEL].c_str()) );
|
||||
|
||||
|
||||
const bool word_wrap = (m_properties[PROP_WORD_WRAP] == "true");
|
||||
|
||||
|
||||
if (m_properties[PROP_LABELS_LOCATION] == "hover")
|
||||
{
|
||||
widget_size = rect<s32>(m_x - label_extra_size/2,
|
||||
@ -160,32 +160,32 @@ void IconButtonWidget::add()
|
||||
m_y + m_h + (word_wrap ? GUIEngine::getFontHeight()*2 :
|
||||
GUIEngine::getFontHeight()));
|
||||
}
|
||||
|
||||
|
||||
m_label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size,
|
||||
false, word_wrap, m_parent);
|
||||
m_label->setTextAlignment(EGUIA_CENTER, EGUIA_UPPERLEFT);
|
||||
m_label->setTabStop(false);
|
||||
m_label->setNotClipped(true);
|
||||
|
||||
|
||||
if (m_properties[PROP_LABELS_LOCATION] == "hover")
|
||||
{
|
||||
m_label->setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
const int max_w = m_label->getAbsolutePosition().getWidth();
|
||||
|
||||
|
||||
if (!word_wrap &&
|
||||
(int)GUIEngine::getFont()->getDimension(message.c_str()).Width > max_w + 4) // arbitrarily allow for 4 pixels
|
||||
{
|
||||
m_label->setOverrideFont( GUIEngine::getSmallFont() );
|
||||
}
|
||||
|
||||
|
||||
#if IRRLICHT_VERSION_MAJOR > 1 || (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8)
|
||||
m_label->setRightToLeft( translations->isRTLLanguage() );
|
||||
m_label->setTextRestrainedInside(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ---- IDs
|
||||
m_id = m_element->getID();
|
||||
if (m_tab_stop) m_element->setTabOrder(m_id);
|
||||
@ -200,9 +200,9 @@ void IconButtonWidget::setImage(const char* path_to_texture, IconPathType pathTy
|
||||
{
|
||||
m_icon_path_type = pathType;
|
||||
}
|
||||
|
||||
|
||||
m_properties[PROP_ICON] = path_to_texture;
|
||||
|
||||
|
||||
if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE)
|
||||
{
|
||||
m_texture = irr_driver->getTexture(m_properties[PROP_ICON]);
|
||||
@ -212,10 +212,10 @@ void IconButtonWidget::setImage(const char* path_to_texture, IconPathType pathTy
|
||||
std::string file = file_manager->getDataDir() + m_properties[PROP_ICON];
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
}
|
||||
|
||||
|
||||
if (!m_texture)
|
||||
{
|
||||
Log::error("icon_button", "Texture '%s' not found!\n",
|
||||
Log::error("icon_button", "Texture '%s' not found!\n",
|
||||
m_properties[PROP_ICON].c_str());
|
||||
std::string file = file_manager->getDataDir() + "gui/main_help.png";
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
@ -232,13 +232,13 @@ void IconButtonWidget::setImage(ITexture* texture)
|
||||
if (texture != NULL)
|
||||
{
|
||||
m_texture = texture;
|
||||
|
||||
|
||||
m_texture_w = m_texture->getSize().Width;
|
||||
m_texture_h = m_texture->getSize().Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("icon_button",
|
||||
Log::error("icon_button",
|
||||
"setImage invoked with NULL image pointer\n");
|
||||
std::string file = file_manager->getDataDir() + "gui/main_help.png";
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
@ -248,14 +248,14 @@ void IconButtonWidget::setImage(ITexture* texture)
|
||||
void IconButtonWidget::setLabel(stringw new_label)
|
||||
{
|
||||
if (m_label == NULL) return;
|
||||
|
||||
|
||||
m_label->setText( new_label.c_str() );
|
||||
|
||||
|
||||
const bool word_wrap = (m_properties[PROP_WORD_WRAP] == "true");
|
||||
const int max_w = m_label->getAbsolutePosition().getWidth();
|
||||
|
||||
|
||||
if (!word_wrap &&
|
||||
(int)GUIEngine::getFont()->getDimension(new_label.c_str()).Width
|
||||
(int)GUIEngine::getFont()->getDimension(new_label.c_str()).Width
|
||||
> max_w + 4) // arbitrarily allow for 4 pixels
|
||||
{
|
||||
m_label->setOverrideFont( GUIEngine::getSmallFont() );
|
||||
@ -269,7 +269,7 @@ void IconButtonWidget::setLabel(stringw new_label)
|
||||
EventPropagation IconButtonWidget::focused(const int playerID)
|
||||
{
|
||||
Widget::focused(playerID);
|
||||
|
||||
|
||||
if (m_label != NULL && m_properties[PROP_LABELS_LOCATION] == "hover")
|
||||
{
|
||||
m_label->setVisible(true);
|
||||
|
@ -42,7 +42,7 @@ LabelWidget::LabelWidget(bool title, bool bright) : Widget(WTYPE_LABEL)
|
||||
m_has_color = false;
|
||||
m_scroll_speed = 0;
|
||||
m_scroll_offset = 0;
|
||||
|
||||
|
||||
if (bright)
|
||||
{
|
||||
m_has_color = true;
|
||||
@ -58,12 +58,12 @@ void LabelWidget::add()
|
||||
rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h);
|
||||
const bool word_wrap = m_properties[PROP_WORD_WRAP] == "true";
|
||||
stringw message = getText();
|
||||
|
||||
|
||||
EGUI_ALIGNMENT align = EGUIA_UPPERLEFT;
|
||||
if (m_properties[PROP_TEXT_ALIGN] == "center") align = EGUIA_CENTER;
|
||||
else if (m_properties[PROP_TEXT_ALIGN] == "right") align = EGUIA_LOWERRIGHT;
|
||||
EGUI_ALIGNMENT valign = EGUIA_CENTER ; //TODO: make label v-align configurable through XML file?
|
||||
|
||||
|
||||
IGUIStaticText* irrwidget;
|
||||
if (m_scroll_speed != 0)
|
||||
{
|
||||
@ -83,15 +83,15 @@ void LabelWidget::add()
|
||||
#if IRRLICHT_VERSION_MAJOR > 1 || (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8)
|
||||
irrwidget->setRightToLeft( m_is_text_rtl );
|
||||
#endif
|
||||
|
||||
|
||||
m_element = irrwidget;
|
||||
irrwidget->setTextAlignment( align, valign );
|
||||
|
||||
|
||||
if (m_has_color)
|
||||
{
|
||||
irrwidget->setOverrideColor(m_color);
|
||||
}
|
||||
|
||||
|
||||
if (m_title_font)
|
||||
{
|
||||
irrwidget->setOverrideColor( video::SColor(255,255,255,255) );
|
||||
@ -99,20 +99,20 @@ void LabelWidget::add()
|
||||
}
|
||||
//irrwidget->setBackgroundColor( video::SColor(255,255,0,0) );
|
||||
//irrwidget->setDrawBackground(true);
|
||||
|
||||
|
||||
m_id = m_element->getID();
|
||||
|
||||
|
||||
m_element->setTabStop(false);
|
||||
m_element->setTabGroup(false);
|
||||
|
||||
|
||||
if (m_scroll_speed > 0)
|
||||
{
|
||||
IGUIFont* font = m_title_font ? GUIEngine::getTitleFont()
|
||||
IGUIFont* font = m_title_font ? GUIEngine::getTitleFont()
|
||||
: GUIEngine::getFont();
|
||||
core::dimension2du r = font->getDimension(getText().c_str());
|
||||
|
||||
|
||||
//m_scroll_offset = (float)r.Width;
|
||||
|
||||
|
||||
// start scrolled off
|
||||
m_scroll_offset = -999;
|
||||
}
|
||||
@ -127,30 +127,30 @@ void LabelWidget::add()
|
||||
void LabelWidget::setText(const wchar_t *text, bool expandIfNeeded)
|
||||
{
|
||||
m_scroll_offset = 0;
|
||||
|
||||
|
||||
if (expandIfNeeded)
|
||||
{
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
const int fwidth = (m_title_font ? GUIEngine::getTitleFont() : GUIEngine::getFont())->getDimension(text).Width;
|
||||
core::rect<s32> rect = m_element->getRelativePosition();
|
||||
|
||||
|
||||
if (rect.getWidth() < fwidth)
|
||||
{
|
||||
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + fwidth;
|
||||
m_element->setRelativePosition(rect);
|
||||
m_element->updateAbsolutePosition();
|
||||
|
||||
|
||||
//((IGUIStaticText*)m_element)->setBackgroundColor( video::SColor(255,255,0,0) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_scroll_speed > 0)
|
||||
{
|
||||
//m_scroll_offset = (float)m_element->getAbsolutePosition().getWidth();
|
||||
m_scroll_offset = (float)m_w;
|
||||
}
|
||||
|
||||
|
||||
Widget::setText(text);
|
||||
} // setText
|
||||
|
||||
@ -162,8 +162,8 @@ void LabelWidget::update(float dt)
|
||||
{
|
||||
if (m_scroll_speed != 0)
|
||||
{
|
||||
m_scroll_offset -= dt*m_scroll_speed*5.0f;
|
||||
m_element->setRelativePosition( core::position2di( /*m_x +*/ (int)m_scroll_offset,
|
||||
m_scroll_offset -= dt*m_scroll_speed*5.0f;
|
||||
m_element->setRelativePosition( core::position2di( /*m_x +*/ (int)m_scroll_offset,
|
||||
/*m_y*/ 0 ) );
|
||||
}
|
||||
} // update
|
||||
@ -173,7 +173,7 @@ bool LabelWidget::scrolledOff() const
|
||||
{
|
||||
// This method may only be called after this widget has been add()ed
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
return m_scroll_offset <= -m_element->getAbsolutePosition().getWidth();
|
||||
}
|
||||
|
||||
|
@ -48,14 +48,14 @@ void ListWidget::setIcons(STKModifiedSpriteBank* icons, int size)
|
||||
{
|
||||
m_use_icons = (icons != NULL);
|
||||
m_icons = icons;
|
||||
|
||||
|
||||
if (m_use_icons)
|
||||
{
|
||||
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
|
||||
assert(list != NULL);
|
||||
|
||||
|
||||
list->setSpriteBank(m_icons);
|
||||
|
||||
|
||||
// determine needed height
|
||||
int item_height = 0;
|
||||
if (size > 0)
|
||||
@ -72,13 +72,13 @@ void ListWidget::setIcons(STKModifiedSpriteBank* icons, int size)
|
||||
if (h > item_height) item_height = h;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (item_height > 0)
|
||||
{
|
||||
list->setItemHeight( item_height );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -86,26 +86,26 @@ void ListWidget::setIcons(STKModifiedSpriteBank* icons, int size)
|
||||
void ListWidget::add()
|
||||
{
|
||||
const int header_height = GUIEngine::getFontHeight() + 15;
|
||||
|
||||
|
||||
rect<s32> widget_size = (m_header.size() > 0 ? rect<s32>(m_x, m_y + header_height, m_x + m_w, m_y + m_h) :
|
||||
rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h) );
|
||||
|
||||
|
||||
IGUIListBox* list = GUIEngine::getGUIEnv()->addListBox (widget_size, m_parent, getNewID());
|
||||
list->setAutoScrollEnabled(false);
|
||||
|
||||
|
||||
m_element = list;
|
||||
m_element->setTabOrder( list->getID() );
|
||||
|
||||
|
||||
if (m_header.size() > 0)
|
||||
{
|
||||
//const int col_size = m_w / m_header.size();
|
||||
|
||||
|
||||
int proportion_total = 0;
|
||||
for (unsigned int n=0; n<m_header.size(); n++)
|
||||
{
|
||||
proportion_total += m_header[n].m_proportion;
|
||||
}
|
||||
|
||||
|
||||
int x = m_x;
|
||||
for (unsigned int n=0; n<m_header.size(); n++)
|
||||
{
|
||||
@ -113,32 +113,32 @@ void ListWidget::add()
|
||||
name << m_properties[PROP_ID];
|
||||
name << "_column_";
|
||||
name << n;
|
||||
|
||||
|
||||
ButtonWidget* header = new ButtonWidget();
|
||||
|
||||
|
||||
header->m_reserved_id = getNewNoFocusID();
|
||||
|
||||
|
||||
header->m_y = m_y;
|
||||
header->m_h = header_height;
|
||||
|
||||
|
||||
header->m_x = x;
|
||||
header->m_w = (int)(m_w * float(m_header[n].m_proportion)
|
||||
/float(proportion_total));
|
||||
|
||||
|
||||
x += header->m_w;
|
||||
|
||||
|
||||
header->setText( m_header[n].m_text );
|
||||
header->m_properties[PROP_ID] = name.str();
|
||||
|
||||
|
||||
header->add();
|
||||
header->m_event_handler = this;
|
||||
|
||||
|
||||
header->getIrrlichtElement()->setTabStop(false);
|
||||
|
||||
|
||||
m_children.push_back(header);
|
||||
m_header_elements.push_back(header);
|
||||
}
|
||||
|
||||
|
||||
m_check_inside_me = true;
|
||||
}
|
||||
}
|
||||
@ -149,29 +149,29 @@ void ListWidget::clear()
|
||||
{
|
||||
// May only be called AFTER this widget has been add()ed
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
|
||||
assert(list != NULL);
|
||||
|
||||
|
||||
list->clear();
|
||||
m_items.clear();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ListWidget::addItem(const std::string& internalName,
|
||||
void ListWidget::addItem(const std::string& internalName,
|
||||
const irr::core::stringw& name, const int icon)
|
||||
{
|
||||
// May only be called AFTER this widget has been add()ed
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
ListItem newItem;
|
||||
newItem.m_label = name;
|
||||
newItem.m_internal_name = internalName;
|
||||
|
||||
|
||||
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
|
||||
assert(list != NULL);
|
||||
|
||||
|
||||
if (m_use_icons && icon != -1)
|
||||
{
|
||||
u32 itemID = list->addItem( name.c_str(), icon );
|
||||
@ -192,13 +192,13 @@ void ListWidget::renameItem(const int itemID, const irr::core::stringw newName,
|
||||
{
|
||||
// May only be called AFTER this widget has been add()ed
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
|
||||
assert(list != NULL);
|
||||
|
||||
|
||||
m_items[itemID].m_label = newName;
|
||||
list->setItem(itemID, newName.c_str(), icon);
|
||||
|
||||
|
||||
list->setItemOverrideColor( itemID, EGUI_LBC_TEXT , video::SColor(255,0,0,0) );
|
||||
list->setItemOverrideColor( itemID, EGUI_LBC_TEXT_HIGHLIGHT, video::SColor(255,255,255,255) );
|
||||
}
|
||||
@ -246,7 +246,7 @@ int ListWidget::getSelectionID() const
|
||||
{
|
||||
// May only be called AFTER this widget has been add()ed
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
return getIrrlichtElement<IGUIListBox>()->getSelected();
|
||||
}
|
||||
|
||||
@ -256,17 +256,17 @@ void ListWidget::setSelectionID(const int index)
|
||||
{
|
||||
// May only be called AFTER this widget has been add()ed
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
IGUIListBox* irritem = getIrrlichtElement<IGUIListBox>();
|
||||
|
||||
|
||||
// auto-scroll to item when selecting something, don't auto-scroll when selecting nothing
|
||||
if (index != -1)
|
||||
{
|
||||
irritem->setAutoScrollEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
irritem->setSelected(index);
|
||||
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
irritem->setAutoScrollEnabled(false);
|
||||
@ -279,10 +279,10 @@ int ListWidget::getItemCount() const
|
||||
{
|
||||
// May only be called AFTER this widget has been add()ed
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
const int count = getIrrlichtElement<IGUIListBox>()->getItemCount();
|
||||
assert((int)m_items.size() == count);
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ void ListWidget::elementRemoved()
|
||||
{
|
||||
Widget::elementRemoved();
|
||||
m_items.clear();
|
||||
|
||||
|
||||
for (int n=0; n<m_header_elements.size(); n++)
|
||||
{
|
||||
m_header_elements[n].elementRemoved();
|
||||
@ -307,12 +307,12 @@ void ListWidget::elementRemoved()
|
||||
int ListWidget::getItemID(const std::string internalName) const
|
||||
{
|
||||
const int count = m_items.size();
|
||||
|
||||
|
||||
for (int i=0; i<count; i++)
|
||||
{
|
||||
if (m_items[i].m_internal_name == internalName) return i;
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -322,9 +322,9 @@ void ListWidget::markItemRed(const int id, bool red)
|
||||
{
|
||||
// May only be called AFTER this widget has been add()ed
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
IGUIListBox* irritem = getIrrlichtElement<IGUIListBox>();
|
||||
|
||||
|
||||
if (red)
|
||||
{
|
||||
irritem->setItemOverrideColor( id, EGUI_LBC_TEXT, video::SColor(255,255,0,0) );
|
||||
@ -343,9 +343,9 @@ void ListWidget::markItemBlue(const int id, bool blue)
|
||||
{
|
||||
// May only be called AFTER this widget has been add()ed
|
||||
assert(m_element != NULL);
|
||||
|
||||
|
||||
IGUIListBox* irritem = getIrrlichtElement<IGUIListBox>();
|
||||
|
||||
|
||||
if (blue)
|
||||
{
|
||||
irritem->setItemOverrideColor( id, EGUI_LBC_TEXT, video::SColor(255,0,0,255) );
|
||||
@ -360,19 +360,19 @@ void ListWidget::markItemBlue(const int id, bool blue)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
EventPropagation ListWidget::transmitEvent(Widget* w,
|
||||
const std::string& originator,
|
||||
EventPropagation ListWidget::transmitEvent(Widget* w,
|
||||
const std::string& originator,
|
||||
const int playerID)
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
|
||||
if (originator.find(m_properties[PROP_ID] + "_column_") != std::string::npos)
|
||||
{
|
||||
{
|
||||
int col = originator[ (m_properties[PROP_ID] + "_column_").size() ] - '0';
|
||||
|
||||
m_selected_column = m_header_elements.get(col);
|
||||
|
||||
|
||||
/** \brief Allows sort icon to change depending on sort order **/
|
||||
m_sort_desc = !m_sort_desc;
|
||||
/*
|
||||
@ -382,11 +382,11 @@ EventPropagation ListWidget::transmitEvent(Widget* w,
|
||||
}
|
||||
m_header_elements[col].getIrrlichtElement<IGUIButton>()->setPressed(true);
|
||||
*/
|
||||
|
||||
|
||||
if (m_listener) m_listener->onColumnClicked(col);
|
||||
|
||||
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
@ -29,17 +29,17 @@ ModelViewWidget::ModelViewWidget() :
|
||||
m_type = WTYPE_MODEL_VIEW;
|
||||
m_rtt_provider = NULL;
|
||||
m_rotation_mode = ROTATE_OFF;
|
||||
|
||||
|
||||
// so that the base class doesn't complain there is no icon defined
|
||||
m_properties[PROP_ICON]="gui/main_help.png";
|
||||
|
||||
|
||||
m_rtt_unsupported = false;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
ModelViewWidget::~ModelViewWidget()
|
||||
{
|
||||
GUIEngine::needsUpdate.remove(this);
|
||||
|
||||
|
||||
delete m_rtt_provider;
|
||||
m_rtt_provider = NULL;
|
||||
}
|
||||
@ -48,18 +48,18 @@ void ModelViewWidget::add()
|
||||
{
|
||||
// so that the base class doesn't complain there is no icon defined
|
||||
m_properties[PROP_ICON]="gui/main_help.png";
|
||||
|
||||
|
||||
IconButtonWidget::add();
|
||||
|
||||
/*
|
||||
FIXME: remove this unclean thing, I think irrlicht provides this feature:
|
||||
virtual void IGUIElement::OnPostRender (u32 timeMs)
|
||||
\brief animate the element and its children.
|
||||
\brief animate the element and its children.
|
||||
*/
|
||||
GUIEngine::needsUpdate.push_back(this);
|
||||
|
||||
|
||||
angle = 0;
|
||||
|
||||
|
||||
} // add
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -69,7 +69,7 @@ void ModelViewWidget::clearModels()
|
||||
m_model_location.clear();
|
||||
m_model_scale.clear();
|
||||
m_model_frames.clear();
|
||||
|
||||
|
||||
delete m_rtt_provider;
|
||||
m_rtt_provider = NULL;
|
||||
}
|
||||
@ -78,22 +78,22 @@ void ModelViewWidget::addModel(irr::scene::IMesh* mesh, const Vec3& location,
|
||||
const Vec3& scale, const int frame)
|
||||
{
|
||||
if(!mesh) return;
|
||||
|
||||
|
||||
m_models.push_back(mesh);
|
||||
m_model_location.push_back(location);
|
||||
m_model_scale.push_back(scale);
|
||||
m_model_frames.push_back(frame);
|
||||
|
||||
|
||||
/*
|
||||
((IGUIMeshViewer*)m_element)->setMesh( mesh );
|
||||
|
||||
|
||||
video::SMaterial mat = mesh->getMeshBuffer(0)->getMaterial(); //mesh_view->getMaterial();
|
||||
mat.setFlag(EMF_LIGHTING , false);
|
||||
//mat.setFlag(EMF_GOURAUD_SHADING, false);
|
||||
//mat.setFlag(EMF_NORMALIZE_NORMALS, true);
|
||||
((IGUIMeshViewer*)m_element)->setMaterial(mat);
|
||||
*/
|
||||
|
||||
|
||||
delete m_rtt_provider;
|
||||
m_rtt_provider = NULL;
|
||||
}
|
||||
@ -101,7 +101,7 @@ void ModelViewWidget::addModel(irr::scene::IMesh* mesh, const Vec3& location,
|
||||
void ModelViewWidget::update(float delta)
|
||||
{
|
||||
if (m_rtt_unsupported) return;
|
||||
|
||||
|
||||
if (m_rotation_mode == ROTATE_CONTINUOUSLY)
|
||||
{
|
||||
angle += delta*m_rotation_speed;
|
||||
@ -116,7 +116,7 @@ void ModelViewWidget::update(float delta)
|
||||
|
||||
int distance_with_positive_rotation;
|
||||
int distance_with_negative_rotation;
|
||||
|
||||
|
||||
if (angle < m_rotation_target)
|
||||
{
|
||||
distance_with_positive_rotation = (int)(m_rotation_target - angle);
|
||||
@ -127,11 +127,11 @@ void ModelViewWidget::update(float delta)
|
||||
distance_with_positive_rotation = (int)(angle_distance_from_end + m_rotation_target);
|
||||
distance_with_negative_rotation = (int)(angle - m_rotation_target);
|
||||
}
|
||||
|
||||
|
||||
//std::cout << "distance_with_positive_rotation=" << distance_with_positive_rotation <<
|
||||
//" distance_with_negative_rotation=" << distance_with_negative_rotation << " angle="<< angle <<std::endl;
|
||||
|
||||
if (distance_with_positive_rotation < distance_with_negative_rotation)
|
||||
|
||||
if (distance_with_positive_rotation < distance_with_negative_rotation)
|
||||
{
|
||||
angle += m_rotation_speed * delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
|
||||
}
|
||||
@ -145,7 +145,7 @@ void ModelViewWidget::update(float delta)
|
||||
// stop rotating when target reached
|
||||
if (fabsf(angle - m_rotation_target) < 2.0f) m_rotation_mode = ROTATE_OFF;
|
||||
}
|
||||
|
||||
|
||||
if (m_rtt_provider == NULL)
|
||||
{
|
||||
std::string name = "model view ";
|
||||
@ -153,7 +153,7 @@ void ModelViewWidget::update(float delta)
|
||||
m_rtt_provider = new IrrDriver::RTTProvider(core::dimension2d< u32 >(512, 512), name, false);
|
||||
m_rtt_provider->setupRTTScene(m_models, m_model_location, m_model_scale, m_model_frames);
|
||||
}
|
||||
|
||||
|
||||
m_texture = m_rtt_provider->renderToTexture(angle);
|
||||
if (m_texture != NULL)
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ void ProgressBarWidget::add()
|
||||
rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h);
|
||||
stringw& message = m_text;
|
||||
m_element = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, getNewNoFocusID(), message.c_str(), L"");
|
||||
|
||||
|
||||
m_id = m_element->getID();
|
||||
m_element->setTabStop(false);
|
||||
m_element->setTabGroup(false);
|
||||
|
@ -53,45 +53,45 @@ RibbonWidget::RibbonWidget(const RibbonType type) : Widget(WTYPE_RIBBON)
|
||||
m_selection[n] = -1;
|
||||
}
|
||||
m_selection[0] = 0; // only player 0 has a selection by default
|
||||
|
||||
|
||||
m_ribbon_type = type;
|
||||
m_mouse_focus = NULL;
|
||||
m_listener = NULL;
|
||||
|
||||
m_check_inside_me = true;
|
||||
m_supports_multiplayer = (type == RIBBON_TOOLBAR);
|
||||
|
||||
|
||||
updateSelection();
|
||||
} // RibbonWidget
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void RibbonWidget::add()
|
||||
{
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
assert(m_x > -10.0f);
|
||||
assert(m_y > -10.0f);
|
||||
assert(m_w > 0.0f);
|
||||
assert(m_h > 0.0f);
|
||||
|
||||
|
||||
|
||||
|
||||
m_labels.clearWithoutDeleting();
|
||||
|
||||
|
||||
rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h);
|
||||
|
||||
|
||||
int id = (m_reserved_id == -1 ? getNewID() : m_reserved_id);
|
||||
|
||||
IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size,
|
||||
|
||||
IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size,
|
||||
m_parent, id, L"");
|
||||
m_element = btn;
|
||||
|
||||
|
||||
const int subbuttons_amount = m_children.size();
|
||||
|
||||
|
||||
// For some ribbon types, we can have unequal sizes depending on whether
|
||||
// items have labels or not
|
||||
int with_label = 0;
|
||||
int without_label = 0;
|
||||
|
||||
// ---- check how much space each child button will take and fit
|
||||
|
||||
// ---- check how much space each child button will take and fit
|
||||
// them within available space
|
||||
int total_needed_space = 0;
|
||||
for (int i=0; i<subbuttons_amount; i++)
|
||||
@ -99,64 +99,64 @@ void RibbonWidget::add()
|
||||
// FIXME: why do I manually invoke the Layout Manager here?
|
||||
LayoutManager::readCoords(m_children.get(i));
|
||||
LayoutManager::applyCoords(m_children.get(i), NULL, this);
|
||||
|
||||
if (m_children[i].m_type != WTYPE_ICON_BUTTON &&
|
||||
|
||||
if (m_children[i].m_type != WTYPE_ICON_BUTTON &&
|
||||
m_children[i].m_type != WTYPE_BUTTON)
|
||||
{
|
||||
fprintf(stderr, "/!\\ Warning /!\\ : ribbon widgets can only have "
|
||||
"(icon)button widgets as children\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// ribbon children must not be keyboard navigatable, the parent
|
||||
|
||||
// ribbon children must not be keyboard navigatable, the parent
|
||||
// ribbon takes care of that
|
||||
if (m_children[i].m_type == WTYPE_ICON_BUTTON)
|
||||
{
|
||||
IconButtonWidget* icon = ((IconButtonWidget*)m_children.get(i));
|
||||
icon->m_tab_stop = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool has_label_underneath = m_children[i].m_text.size() > 0;
|
||||
if (m_children[i].m_properties[PROP_LABELS_LOCATION].size() > 0)
|
||||
{
|
||||
has_label_underneath = false;
|
||||
}
|
||||
|
||||
|
||||
if (has_label_underneath) with_label++;
|
||||
else without_label++;
|
||||
|
||||
|
||||
total_needed_space += m_children[i].m_w;
|
||||
}
|
||||
|
||||
|
||||
int free_w_space = m_w - total_needed_space;
|
||||
|
||||
|
||||
//int biggest_y = 0;
|
||||
const int button_y = 10;
|
||||
float global_zoom = 1;
|
||||
|
||||
|
||||
const int min_free_space = 50;
|
||||
global_zoom = (float)m_w / (float)( m_w - free_w_space + min_free_space );
|
||||
//free_w_space = (int)(m_w - total_needed_space*global_zoom);
|
||||
|
||||
|
||||
const int one_button_space =
|
||||
(int)round((float)m_w / (float)subbuttons_amount);
|
||||
|
||||
|
||||
int widget_x = -1;
|
||||
|
||||
|
||||
// ---- add children
|
||||
for (int i=0; i<subbuttons_amount; i++)
|
||||
{
|
||||
{
|
||||
// ---- tab ribbons
|
||||
if (getRibbonType() == RIBBON_TABS)
|
||||
{
|
||||
const int large_tab = (int)((with_label + without_label)
|
||||
*one_button_space
|
||||
*one_button_space
|
||||
/ (with_label + without_label/2.0f));
|
||||
const int small_tab = large_tab/2;
|
||||
|
||||
|
||||
stringw& message = m_children[i].m_text;
|
||||
|
||||
|
||||
|
||||
if (message.size() == 0)
|
||||
{
|
||||
@ -168,31 +168,31 @@ void RibbonWidget::add()
|
||||
if (widget_x == -1) widget_x = large_tab/2;
|
||||
else widget_x += large_tab/2;
|
||||
}
|
||||
|
||||
|
||||
IGUIButton * subbtn = NULL;
|
||||
rect<s32> subsize = rect<s32>(widget_x - large_tab/2+2, 0,
|
||||
widget_x + large_tab/2-2, m_h);
|
||||
|
||||
|
||||
if (message.size() == 0)
|
||||
{
|
||||
subsize = rect<s32>(widget_x - small_tab/2+2, 0,
|
||||
widget_x + small_tab/2-2, m_h);
|
||||
}
|
||||
|
||||
|
||||
if (m_children[i].m_type == WTYPE_BUTTON)
|
||||
{
|
||||
subbtn = GUIEngine::getGUIEnv()
|
||||
->addButton(subsize, btn, getNewNoFocusID(),
|
||||
->addButton(subsize, btn, getNewNoFocusID(),
|
||||
message.c_str(), L"");
|
||||
subbtn->setTabStop(false);
|
||||
subbtn->setTabGroup(false);
|
||||
|
||||
|
||||
if ((int)GUIEngine::getFont()->getDimension(message.c_str())
|
||||
.Width > subsize.getWidth() &&
|
||||
message.findFirst(L' ') == -1 &&
|
||||
message.findFirst(L' ') == -1 &&
|
||||
message.findFirst(L'\u00AD') == -1 )
|
||||
{
|
||||
// if message too long and contains no space and no soft
|
||||
// if message too long and contains no space and no soft
|
||||
// hyphen, make the font smaller
|
||||
subbtn->setOverrideFont(GUIEngine::getSmallFont());
|
||||
}
|
||||
@ -203,7 +203,7 @@ void RibbonWidget::add()
|
||||
0,
|
||||
subsize.getHeight()+15,
|
||||
subsize.getHeight());
|
||||
|
||||
|
||||
if (message.size() == 0)
|
||||
{
|
||||
const int x = subsize.getWidth()/2 - subsize.getHeight()/2;
|
||||
@ -213,22 +213,22 @@ void RibbonWidget::add()
|
||||
x + subsize.getHeight(),
|
||||
subsize.getHeight());
|
||||
}
|
||||
|
||||
|
||||
// label at the *right* of the icon (for tabs)
|
||||
rect<s32> label_part = rect<s32>(subsize.getHeight()+15,
|
||||
0,
|
||||
subsize.getWidth()-15,
|
||||
subsize.getHeight());
|
||||
|
||||
// use the same ID for all subcomponents; since event handling
|
||||
// is done per-ID, no matter which one your hover, this
|
||||
|
||||
// use the same ID for all subcomponents; since event handling
|
||||
// is done per-ID, no matter which one your hover, this
|
||||
// widget will get it
|
||||
int same_id = getNewNoFocusID();
|
||||
subbtn = GUIEngine::getGUIEnv()->addButton(subsize, btn,
|
||||
subbtn = GUIEngine::getGUIEnv()->addButton(subsize, btn,
|
||||
same_id, L"", L"");
|
||||
|
||||
IGUIButton* icon =
|
||||
GUIEngine::getGUIEnv()->addButton(icon_part, subbtn,
|
||||
|
||||
IGUIButton* icon =
|
||||
GUIEngine::getGUIEnv()->addButton(icon_part, subbtn,
|
||||
same_id, L"");
|
||||
icon->setScaleImage(true);
|
||||
std::string filename = file_manager->getDataDir()
|
||||
@ -238,19 +238,19 @@ void RibbonWidget::add()
|
||||
icon->setDrawBorder(false);
|
||||
icon->setTabStop(false);
|
||||
|
||||
IGUIStaticText* label =
|
||||
GUIEngine::getGUIEnv()->addStaticText(message.c_str(),
|
||||
IGUIStaticText* label =
|
||||
GUIEngine::getGUIEnv()->addStaticText(message.c_str(),
|
||||
label_part,
|
||||
false /* border */,
|
||||
true /* word wrap */,
|
||||
subbtn, same_id);
|
||||
|
||||
|
||||
if ((int)GUIEngine::getFont()->getDimension(message.c_str())
|
||||
.Width > label_part.getWidth()&&
|
||||
message.findFirst(L' ') == -1 &&
|
||||
message.findFirst(L' ') == -1 &&
|
||||
message.findFirst(L'\u00AD') == -1 )
|
||||
{
|
||||
// if message too long and contains no space and no soft
|
||||
// if message too long and contains no space and no soft
|
||||
// hyphen, make the font smaller
|
||||
label->setOverrideFont(GUIEngine::getSmallFont());
|
||||
}
|
||||
@ -258,7 +258,7 @@ void RibbonWidget::add()
|
||||
label->setTabStop(false);
|
||||
label->setNotClipped(true);
|
||||
m_labels.push_back(label);
|
||||
|
||||
|
||||
subbtn->setTabStop(false);
|
||||
subbtn->setTabGroup(false);
|
||||
}
|
||||
@ -266,9 +266,9 @@ void RibbonWidget::add()
|
||||
{
|
||||
fprintf(stderr, "Invalid tab bar contents\n");
|
||||
}
|
||||
|
||||
|
||||
m_children[i].m_element = subbtn;
|
||||
|
||||
|
||||
if (message.size() == 0) widget_x += small_tab/2;
|
||||
else widget_x += large_tab/2;
|
||||
}
|
||||
@ -276,68 +276,68 @@ void RibbonWidget::add()
|
||||
else if (m_children[i].m_type == WTYPE_ICON_BUTTON)
|
||||
{
|
||||
if (widget_x == -1) widget_x = one_button_space/2;
|
||||
|
||||
|
||||
// find how much space to keep for the label under the button.
|
||||
// consider font size, whether the label is multiline, etc...
|
||||
bool has_label = m_children[i].m_text.size() > 0;
|
||||
|
||||
|
||||
if (m_children[i].m_properties[PROP_LABELS_LOCATION].size() > 0)
|
||||
{
|
||||
has_label = false;
|
||||
}
|
||||
|
||||
const int needed_space_under_button = has_label
|
||||
? GUIEngine::getFontHeight()
|
||||
|
||||
const int needed_space_under_button = has_label
|
||||
? GUIEngine::getFontHeight()
|
||||
: 10;
|
||||
|
||||
float imageRatio =
|
||||
|
||||
float imageRatio =
|
||||
(float)m_children[i].m_w / (float)m_children[i].m_h;
|
||||
|
||||
|
||||
// calculate the size of the image
|
||||
std::string filename = file_manager->getDataDir()
|
||||
+ m_children[i].m_properties[PROP_ICON];
|
||||
video::ITexture* image =
|
||||
video::ITexture* image =
|
||||
irr_driver->getTexture((filename).c_str());
|
||||
float image_h = (float)image->getSize().Height;
|
||||
float image_w = image_h*imageRatio;
|
||||
|
||||
// scale to fit (FIXME: calculate the right value directly...)
|
||||
float zoom = global_zoom;
|
||||
|
||||
|
||||
if (button_y + image_h*zoom + needed_space_under_button > m_h)
|
||||
{
|
||||
// scale down
|
||||
while (button_y + image_h*zoom +
|
||||
while (button_y + image_h*zoom +
|
||||
needed_space_under_button > m_h) zoom -= 0.01f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// scale up
|
||||
while (button_y + image_h*zoom +
|
||||
while (button_y + image_h*zoom +
|
||||
needed_space_under_button < m_h) zoom += 0.01f;
|
||||
}
|
||||
|
||||
|
||||
// ---- add bitmap button part
|
||||
// backup and restore position in case the same object is added
|
||||
// backup and restore position in case the same object is added
|
||||
// multiple times (FIXME: unclean)
|
||||
int old_x = m_children[i].m_x;
|
||||
int old_y = m_children[i].m_y;
|
||||
int old_w = m_children[i].m_w;
|
||||
int old_h = m_children[i].m_h;
|
||||
|
||||
|
||||
m_children[i].m_x = widget_x - (int)(image_w*zoom/2.0f);
|
||||
m_children[i].m_y = button_y;
|
||||
m_children[i].m_w = (int)(image_w*zoom);
|
||||
m_children[i].m_h = (int)(image_h*zoom);
|
||||
|
||||
|
||||
IconButtonWidget* icon = ((IconButtonWidget*)m_children.get(i));
|
||||
|
||||
|
||||
if (icon->m_properties[PROP_EXTEND_LABEL].size() == 0)
|
||||
{
|
||||
icon->m_properties[PROP_EXTEND_LABEL] =
|
||||
icon->m_properties[PROP_EXTEND_LABEL] =
|
||||
StringUtils::toString(one_button_space - icon->m_w);
|
||||
}
|
||||
|
||||
|
||||
m_children.get(i)->m_parent = btn;
|
||||
m_children.get(i)->add();
|
||||
|
||||
@ -346,24 +346,24 @@ void RibbonWidget::add()
|
||||
m_children[i].m_y = old_y;
|
||||
m_children[i].m_w = old_w;
|
||||
m_children[i].m_h = old_h;
|
||||
|
||||
// the label itself will be added by the icon widget. since it
|
||||
// adds the label outside of the widget area it is assigned to,
|
||||
|
||||
// the label itself will be added by the icon widget. since it
|
||||
// adds the label outside of the widget area it is assigned to,
|
||||
// the label will appear in the area we want at the bottom
|
||||
|
||||
|
||||
widget_x += one_button_space;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
fprintf(stderr,
|
||||
"/!\\ Warning /!\\ : Invalid contents type in ribbon\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//m_children[i].id = subbtn->getID();
|
||||
m_children[i].m_event_handler = this;
|
||||
}// next sub-button
|
||||
|
||||
|
||||
id = m_element->getID();
|
||||
m_element->setTabOrder(id);
|
||||
m_element->setTabGroup(false);
|
||||
@ -376,30 +376,30 @@ void RibbonWidget::addTextChild(const wchar_t* text, const std::string id)
|
||||
{
|
||||
// This method should only be called BEFORE a widget is added
|
||||
assert(m_element == NULL);
|
||||
|
||||
|
||||
ButtonWidget* item = new ButtonWidget();
|
||||
item->m_text = text;
|
||||
item->m_properties[PROP_ID] = id;
|
||||
|
||||
|
||||
m_children.push_back(item);
|
||||
} // addTextChild
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void RibbonWidget::addIconChild(const wchar_t* text, const std::string &id,
|
||||
const int w, const int h,
|
||||
const int w, const int h,
|
||||
const std::string &icon,
|
||||
const IconButtonWidget::IconPathType icon_path_type)
|
||||
{
|
||||
// This method should only be called BEFORE a widget is added
|
||||
assert(m_element == NULL);
|
||||
|
||||
|
||||
IconButtonWidget* ribbon_item = new IconButtonWidget();
|
||||
|
||||
|
||||
ribbon_item->m_properties[PROP_ID] = id;
|
||||
|
||||
|
||||
ribbon_item->setImage(icon.c_str(), icon_path_type);
|
||||
|
||||
|
||||
ribbon_item->m_properties[PROP_WIDTH] = StringUtils::toString(w);
|
||||
ribbon_item->m_properties[PROP_HEIGHT] = StringUtils::toString(h);
|
||||
|
||||
@ -413,7 +413,7 @@ void RibbonWidget::clearAllChildren()
|
||||
{
|
||||
// This method should only be called BEFORE a widget is added
|
||||
assert(m_element == NULL);
|
||||
|
||||
|
||||
m_children.clearAndDeleteAll();
|
||||
} // clearAllChildren
|
||||
|
||||
@ -423,7 +423,7 @@ void RibbonWidget::removeChildNamed(const char* name)
|
||||
{
|
||||
// This method should only be called BEFORE a widget is added
|
||||
assert(m_element == NULL);
|
||||
|
||||
|
||||
Widget* child;
|
||||
for_in (child, m_children)
|
||||
{
|
||||
@ -440,7 +440,7 @@ void RibbonWidget::removeChildNamed(const char* name)
|
||||
void RibbonWidget::select(std::string item, const int mousePlayerID)
|
||||
{
|
||||
const int subbuttons_amount = m_children.size();
|
||||
|
||||
|
||||
for (int i=0; i<subbuttons_amount; i++)
|
||||
{
|
||||
if (m_children[i].m_properties[PROP_ID] == item)
|
||||
@ -450,7 +450,7 @@ void RibbonWidget::select(std::string item, const int mousePlayerID)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // select
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -461,7 +461,7 @@ EventPropagation RibbonWidget::rightPressed(const int playerID)
|
||||
if (m_children.size() < 2) return EVENT_LET;
|
||||
|
||||
m_selection[playerID]++;
|
||||
|
||||
|
||||
if (m_selection[playerID] >= m_children.size())
|
||||
{
|
||||
if (m_listener != NULL) m_listener->onRibbonWidgetScroll(1);
|
||||
@ -469,7 +469,7 @@ EventPropagation RibbonWidget::rightPressed(const int playerID)
|
||||
m_selection[playerID] = m_event_handler ? m_children.size()-1 : 0;
|
||||
}
|
||||
updateSelection();
|
||||
|
||||
|
||||
if (m_ribbon_type == RIBBON_COMBO || m_ribbon_type == RIBBON_TABS)
|
||||
{
|
||||
const int mousePlayerID = input_manager->getPlayerKeyboardID();
|
||||
@ -478,16 +478,16 @@ EventPropagation RibbonWidget::rightPressed(const int playerID)
|
||||
m_mouse_focus = m_children.get(m_selection[playerID]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if we reached a filler item, move again (but don't wrap)
|
||||
if (getSelectionIDString(playerID) == RibbonWidget::NO_ITEM_ID)
|
||||
if (getSelectionIDString(playerID) == RibbonWidget::NO_ITEM_ID)
|
||||
{
|
||||
if (m_selection[playerID] + 1 < m_children.size())
|
||||
{
|
||||
rightPressed(playerID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return m_ribbon_type != RIBBON_TOOLBAR ? EVENT_LET : EVENT_BLOCK;
|
||||
} // rightPressed
|
||||
|
||||
@ -497,19 +497,19 @@ EventPropagation RibbonWidget::leftPressed(const int playerID)
|
||||
if (m_deactivated) return EVENT_LET;
|
||||
// empty ribbon, or only one item (can't move left)
|
||||
if (m_children.size() < 2) return EVENT_LET;
|
||||
|
||||
|
||||
m_selection[playerID]--;
|
||||
if (m_selection[playerID] < 0)
|
||||
{
|
||||
if (m_listener != NULL) m_listener->onRibbonWidgetScroll(-1);
|
||||
|
||||
m_selection[playerID] = m_event_handler
|
||||
? 0
|
||||
m_selection[playerID] = m_event_handler
|
||||
? 0
|
||||
: m_children.size()-1;
|
||||
}
|
||||
|
||||
updateSelection();
|
||||
|
||||
|
||||
if (m_ribbon_type == RIBBON_COMBO)
|
||||
{
|
||||
const int mousePlayerID = input_manager->getPlayerKeyboardID();
|
||||
@ -518,13 +518,13 @@ EventPropagation RibbonWidget::leftPressed(const int playerID)
|
||||
m_mouse_focus = m_children.get(m_selection[playerID]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if we reached a filler item, move again (but don't wrap)
|
||||
if (getSelectionIDString(playerID) == RibbonWidget::NO_ITEM_ID)
|
||||
if (getSelectionIDString(playerID) == RibbonWidget::NO_ITEM_ID)
|
||||
{
|
||||
if (m_selection[playerID] > 0) leftPressed(playerID);
|
||||
}
|
||||
|
||||
|
||||
if (m_ribbon_type != RIBBON_TOOLBAR)
|
||||
{
|
||||
//GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
|
||||
@ -539,11 +539,11 @@ EventPropagation RibbonWidget::leftPressed(const int playerID)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
EventPropagation RibbonWidget::focused(const int playerID)
|
||||
{
|
||||
{
|
||||
Widget::focused(playerID);
|
||||
|
||||
|
||||
if (m_children.size() < 1) return EVENT_LET; // empty ribbon
|
||||
|
||||
|
||||
if (m_ribbon_type == RIBBON_COMBO || m_ribbon_type == RIBBON_TABS)
|
||||
{
|
||||
const int mousePlayerID = input_manager->getPlayerKeyboardID();
|
||||
@ -561,10 +561,10 @@ EventPropagation RibbonWidget::focused(const int playerID)
|
||||
m_children.get(m_selection[playerID])->focused(playerID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_listener != NULL) m_listener->onRibbonWidgetFocus( this, playerID );
|
||||
|
||||
|
||||
|
||||
return EVENT_LET;
|
||||
} // focused
|
||||
|
||||
@ -579,24 +579,24 @@ void RibbonWidget::unfocused(const int playerID, Widget* new_focus)
|
||||
m_children.get(m_selection[playerID])->unfocused(playerID, new_focus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//if (m_selection[0] != -1) m_children.get(m_selection[0])->unfocused(0);
|
||||
} // unfocused
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
EventPropagation RibbonWidget::mouseHovered(Widget* child,
|
||||
EventPropagation RibbonWidget::mouseHovered(Widget* child,
|
||||
const int mousePlayerID)
|
||||
{
|
||||
if (m_deactivated) return EVENT_LET;
|
||||
|
||||
|
||||
const int subbuttons_amount = m_children.size();
|
||||
|
||||
|
||||
if (m_ribbon_type == RIBBON_COMBO || m_ribbon_type == RIBBON_TABS)
|
||||
{
|
||||
//std::cout << "SETTING m_mouse_focus\n";
|
||||
m_mouse_focus = child;
|
||||
}
|
||||
|
||||
|
||||
// In toolbar ribbons, hovering selects
|
||||
if (m_ribbon_type == RIBBON_TOOLBAR)
|
||||
{
|
||||
@ -605,15 +605,15 @@ EventPropagation RibbonWidget::mouseHovered(Widget* child,
|
||||
if (m_children.get(i) == child)
|
||||
{
|
||||
// Was already selected, don't send another event
|
||||
if (m_selection[mousePlayerID] == i) return EVENT_BLOCK;
|
||||
|
||||
if (m_selection[mousePlayerID] == i) return EVENT_BLOCK;
|
||||
|
||||
// Don't change selection on hover for others
|
||||
m_selection[mousePlayerID] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateSelection();
|
||||
return EVENT_BLOCK;
|
||||
} // mouseHovered
|
||||
@ -638,9 +638,9 @@ const std::string& RibbonWidget::getSelectionIDString(const int playerID)
|
||||
void RibbonWidget::updateSelection()
|
||||
{
|
||||
const int subbuttons_amount = m_children.size();
|
||||
|
||||
|
||||
// FIXME: m_selection, m_selected, m_mouse_focus... what a mess...
|
||||
|
||||
|
||||
//std::cout << "----\n";
|
||||
// Update selection flags for mouse player
|
||||
for (int p=0; p<MAX_PLAYER_COUNT; p++)
|
||||
@ -656,22 +656,22 @@ void RibbonWidget::updateSelection()
|
||||
if (new_val) m_children[i].focused(PLAYER_ID_GAME_MASTER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_listener) m_listener->onSelectionChange();
|
||||
} // updateSelection
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
EventPropagation RibbonWidget::transmitEvent(Widget* w,
|
||||
EventPropagation RibbonWidget::transmitEvent(Widget* w,
|
||||
const std::string& originator,
|
||||
const int playerID)
|
||||
{
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
|
||||
|
||||
if (!m_deactivated)
|
||||
{
|
||||
const int subbuttons_amount = m_children.size();
|
||||
|
||||
|
||||
for (int i=0; i<subbuttons_amount; i++)
|
||||
{
|
||||
if (m_children[i].m_properties[PROP_ID] == originator)
|
||||
@ -680,13 +680,13 @@ EventPropagation RibbonWidget::transmitEvent(Widget* w,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateSelection();
|
||||
}
|
||||
|
||||
|
||||
// bring focus back to enclosing ribbon widget
|
||||
this->setFocusForPlayer( playerID );
|
||||
|
||||
|
||||
if (m_selection[playerID] != -1)
|
||||
{
|
||||
if (m_children[m_selection[playerID]].m_deactivated)
|
||||
@ -697,7 +697,7 @@ EventPropagation RibbonWidget::transmitEvent(Widget* w,
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return EVENT_LET;
|
||||
} // transmitEvent
|
||||
|
||||
@ -709,7 +709,7 @@ void RibbonWidget::setLabel(const int id, irr::core::stringw new_name)
|
||||
|
||||
// ignore this call for ribbons without labels
|
||||
if (m_labels.size() == 0) return;
|
||||
|
||||
|
||||
assert(id >= 0);
|
||||
assert(id < m_labels.size());
|
||||
m_labels[id].setText( new_name.c_str() );
|
||||
@ -718,14 +718,14 @@ void RibbonWidget::setLabel(const int id, irr::core::stringw new_name)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int RibbonWidget::findItemNamed(const char* internalName)
|
||||
{
|
||||
{
|
||||
const int size = m_children.size();
|
||||
|
||||
|
||||
//printf("Ribbon : Looking for %s among %i items\n", internalName, size);
|
||||
|
||||
|
||||
for (int n=0; n<size; n++)
|
||||
{
|
||||
//printf(" Ribbon : Looking for %s in item %i : %s\n",
|
||||
//printf(" Ribbon : Looking for %s in item %i : %s\n",
|
||||
// internalName, n, m_children[n].m_properties[PROP_ID].c_str());
|
||||
if (m_children[n].m_properties[PROP_ID] == internalName) return n;
|
||||
}
|
||||
|
@ -39,13 +39,13 @@ using namespace irr::video;
|
||||
SpinnerWidget::SpinnerWidget(const bool gauge) : Widget(WTYPE_SPINNER)
|
||||
{
|
||||
m_gauge = gauge;
|
||||
|
||||
|
||||
m_listener = NULL;
|
||||
m_graphical = false;
|
||||
m_check_inside_me = true; //FIXME: not sure this is necessary
|
||||
m_supports_multiplayer = true;
|
||||
m_value = -1;
|
||||
|
||||
|
||||
m_min = 0;
|
||||
m_max = 999;
|
||||
}
|
||||
@ -57,9 +57,9 @@ void SpinnerWidget::add()
|
||||
// retrieve min and max values
|
||||
std::string min_s = m_properties[PROP_MIN_VALUE];
|
||||
std::string max_s = m_properties[PROP_MAX_VALUE];
|
||||
|
||||
|
||||
m_wrap_around = (m_properties[PROP_WRAP_AROUND] == "true");
|
||||
|
||||
|
||||
if (min_s.size() > 0)
|
||||
{
|
||||
int i;
|
||||
@ -74,7 +74,7 @@ void SpinnerWidget::add()
|
||||
std::cerr << "WARNING : invalid value for spinner widget minimum value : '" << min_s << "'\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (max_s.size() > 0)
|
||||
{
|
||||
int i;
|
||||
@ -89,26 +89,26 @@ void SpinnerWidget::add()
|
||||
std::cerr << "WARNING : invalid value for spinner widget maximal value : '" << max_s << "'\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_value == -1)
|
||||
{
|
||||
m_value = (m_min + m_max)/2;
|
||||
}
|
||||
|
||||
|
||||
// create sub-widgets if they don't already exist
|
||||
if (m_children.size() == 0)
|
||||
{
|
||||
std::string& icon = m_properties[PROP_ICON];
|
||||
m_graphical = icon.size()>0;
|
||||
|
||||
|
||||
//FIXME: unclean to create "fake" button/label/icon widgets!!
|
||||
m_children.push_back( new Widget(WTYPE_BUTTON) );
|
||||
m_children.push_back( new Widget(m_graphical ? WTYPE_ICON_BUTTON : WTYPE_LABEL) );
|
||||
m_children.push_back( new Widget(WTYPE_BUTTON) );
|
||||
}
|
||||
|
||||
|
||||
int widgetID;
|
||||
|
||||
|
||||
if (m_reserved_id != -1)
|
||||
{
|
||||
widgetID = m_reserved_id;
|
||||
@ -117,13 +117,13 @@ void SpinnerWidget::add()
|
||||
{
|
||||
widgetID = getNewID();
|
||||
}
|
||||
|
||||
|
||||
rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h);
|
||||
IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, widgetID, L"");
|
||||
m_element = btn;
|
||||
|
||||
|
||||
m_element->setTabOrder( m_element->getID() );
|
||||
|
||||
|
||||
// left arrow
|
||||
rect<s32> subsize_left_arrow = rect<s32>(0 ,0, m_h, m_h);
|
||||
IGUIButton * left_arrow = GUIEngine::getGUIEnv()->addButton(subsize_left_arrow, btn, getNewNoFocusID(), L" ");
|
||||
@ -132,18 +132,18 @@ void SpinnerWidget::add()
|
||||
m_children[0].m_event_handler = this;
|
||||
m_children[0].m_properties[PROP_ID] = "left";
|
||||
m_children[0].m_id = m_children[0].m_element->getID();
|
||||
|
||||
|
||||
m_badge_x_shift = subsize_left_arrow.getWidth();
|
||||
|
||||
|
||||
// label
|
||||
if (m_graphical)
|
||||
{
|
||||
ITexture* texture = getTexture();
|
||||
assert(texture != NULL);
|
||||
|
||||
|
||||
const int texture_width = texture->getSize().Width;
|
||||
const int free_h_space = m_w - m_h*2 - texture_width; // to center image
|
||||
|
||||
|
||||
rect<s32> subsize_label = rect<s32>(m_h + free_h_space/2, 0, m_w - m_h+ free_h_space/2, m_h);
|
||||
IGUIImage * subbtn = GUIEngine::getGUIEnv()->addImage(subsize_label, btn, getNewNoFocusID());
|
||||
m_children[1].m_element = subbtn;
|
||||
@ -151,7 +151,7 @@ void SpinnerWidget::add()
|
||||
m_children[1].m_event_handler = this;
|
||||
m_children[1].m_properties[PROP_ID] = "spinnerbody";
|
||||
subbtn->setUseAlphaChannel(true);
|
||||
|
||||
|
||||
subbtn->setImage(texture);
|
||||
//subbtn->setScaleImage(true);
|
||||
}
|
||||
@ -168,15 +168,15 @@ void SpinnerWidget::add()
|
||||
label->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
|
||||
label->setTabStop(false);
|
||||
label->setNotClipped(true);
|
||||
|
||||
|
||||
|
||||
|
||||
if (m_labels.size() > 0)
|
||||
{
|
||||
label->setText(m_labels[m_value].c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// right arrow
|
||||
rect<s32> subsize_right_arrow = rect<s32>(m_w - m_h, 0, m_w, m_h);
|
||||
IGUIButton * right_arrow = GUIEngine::getGUIEnv()->addButton(subsize_right_arrow, btn, getNewNoFocusID(), L" ");
|
||||
@ -185,7 +185,7 @@ void SpinnerWidget::add()
|
||||
m_children[2].m_event_handler = this;
|
||||
m_children[2].m_properties[PROP_ID] = "right";
|
||||
m_children[2].m_id = m_children[2].m_element->getID();
|
||||
|
||||
|
||||
// refresh display
|
||||
setValue(m_value);
|
||||
}
|
||||
@ -207,18 +207,18 @@ ITexture* SpinnerWidget::getTexture()
|
||||
void SpinnerWidget::move(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
Widget::move(x, y, w, h);
|
||||
|
||||
|
||||
rect<s32> subsize_left_arrow = rect<s32>(0 ,0, h, h);
|
||||
m_children[0].m_element->setRelativePosition(subsize_left_arrow);
|
||||
|
||||
|
||||
if (m_graphical)
|
||||
{
|
||||
ITexture* texture = getTexture();
|
||||
assert(texture != NULL);
|
||||
|
||||
|
||||
const int texture_width = texture->getSize().Width;
|
||||
const int free_h_space = w-h*2-texture_width; // to center image
|
||||
|
||||
|
||||
rect<s32> subsize_label = rect<s32>(h+free_h_space/2, 0, w-h+free_h_space/2, h);
|
||||
m_children[1].m_element->setRelativePosition(subsize_label);
|
||||
}
|
||||
@ -227,7 +227,7 @@ void SpinnerWidget::move(const int x, const int y, const int w, const int h)
|
||||
rect<s32> subsize_label = rect<s32>(h, 0, w-h, h);
|
||||
m_children[1].m_element->setRelativePosition(subsize_label);
|
||||
}
|
||||
|
||||
|
||||
rect<s32> subsize_right_arrow = rect<s32>(w-h, 0, w, h);
|
||||
m_children[2].m_element->setRelativePosition(subsize_right_arrow);
|
||||
}
|
||||
@ -238,7 +238,7 @@ EventPropagation SpinnerWidget::rightPressed(const int playerID)
|
||||
{
|
||||
// if widget is deactivated, do nothing
|
||||
if (m_deactivated) return EVENT_BLOCK;
|
||||
|
||||
|
||||
//std::cout << "Right pressed\n";
|
||||
if (m_value+1 <= m_max)
|
||||
{
|
||||
@ -248,9 +248,9 @@ EventPropagation SpinnerWidget::rightPressed(const int playerID)
|
||||
{
|
||||
setValue(m_min);
|
||||
}
|
||||
|
||||
|
||||
//GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
|
||||
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
@ -260,7 +260,7 @@ EventPropagation SpinnerWidget::leftPressed(const int playerID)
|
||||
{
|
||||
// if widget is deactivated, do nothing
|
||||
if (m_deactivated) return EVENT_BLOCK;
|
||||
|
||||
|
||||
//std::cout << "Left pressed\n";
|
||||
if (m_value-1 >= m_min)
|
||||
{
|
||||
@ -270,23 +270,23 @@ EventPropagation SpinnerWidget::leftPressed(const int playerID)
|
||||
{
|
||||
setValue(m_max);
|
||||
}
|
||||
|
||||
|
||||
//GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
|
||||
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
EventPropagation SpinnerWidget::transmitEvent(Widget* w,
|
||||
const std::string& originator,
|
||||
EventPropagation SpinnerWidget::transmitEvent(Widget* w,
|
||||
const std::string& originator,
|
||||
const int playerID)
|
||||
{
|
||||
assert(m_magic_number == 0xCAFEC001);
|
||||
|
||||
// if widget is deactivated, do nothing
|
||||
if (m_deactivated) return EVENT_BLOCK;
|
||||
|
||||
|
||||
if (originator == "left")
|
||||
{
|
||||
leftPressed(playerID);
|
||||
@ -305,8 +305,8 @@ EventPropagation SpinnerWidget::transmitEvent(Widget* w,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (m_element != NULL) setFocusForPlayer( playerID );
|
||||
return EVENT_LET;
|
||||
}
|
||||
@ -325,7 +325,7 @@ void SpinnerWidget::addLabel(stringw label)
|
||||
m_labels.push_back(label);
|
||||
m_min = 0;
|
||||
m_max = m_labels.size()-1;
|
||||
|
||||
|
||||
if (m_element != NULL) setValue(0);
|
||||
}
|
||||
|
||||
@ -334,7 +334,7 @@ void SpinnerWidget::addLabel(stringw label)
|
||||
void SpinnerWidget::setValue(const int new_value)
|
||||
{
|
||||
m_value = new_value;
|
||||
|
||||
|
||||
if (m_graphical)
|
||||
{
|
||||
std::ostringstream icon;
|
||||
@ -346,7 +346,7 @@ void SpinnerWidget::setValue(const int new_value)
|
||||
{
|
||||
assert(new_value >= 0);
|
||||
assert(new_value < (int)m_labels.size());
|
||||
|
||||
|
||||
m_children[1].m_element->setText(m_labels[new_value].c_str() );
|
||||
}
|
||||
else if (m_text.size() > 0 && m_children.size() > 0)
|
||||
@ -376,7 +376,7 @@ stringw SpinnerWidget::getStringValue() const
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
/** To avoid compiler warnings about missing return statements. */
|
||||
return "";
|
||||
}
|
||||
@ -394,7 +394,7 @@ void SpinnerWidget::setValue(irr::core::stringw new_value)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::cerr << "ERROR [SpinnerWidget::setValue] : cannot find element named '"
|
||||
<< irr::core::stringc(new_value.c_str()).c_str() << "'\n";
|
||||
assert(false);
|
||||
@ -405,7 +405,7 @@ void SpinnerWidget::setValue(irr::core::stringw new_value)
|
||||
void SpinnerWidget::setActivated()
|
||||
{
|
||||
Widget::setActivated();
|
||||
|
||||
|
||||
setText(L"");
|
||||
setValue( getValue() ); // Update the display
|
||||
}
|
||||
@ -415,7 +415,7 @@ void SpinnerWidget::setActivated()
|
||||
void SpinnerWidget::setDeactivated()
|
||||
{
|
||||
Widget::setDeactivated();
|
||||
|
||||
|
||||
setText(L"-");
|
||||
setValue( getValue() ); // Update the display
|
||||
}
|
||||
|
@ -32,21 +32,21 @@ using namespace irr;
|
||||
class MyCGUIEditBox : public CGUIEditBox
|
||||
{
|
||||
PtrVector<GUIEngine::ITextBoxWidgetListener, REF> m_listeners;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
MyCGUIEditBox(const wchar_t* text, bool border, gui::IGUIEnvironment* environment,
|
||||
gui:: IGUIElement* parent, s32 id, const core::rect<s32>& rectangle) :
|
||||
CGUIEditBox(text, border, environment, parent, id, rectangle, translations->isRTLLanguage())
|
||||
{
|
||||
if (translations->isRTLLanguage()) setTextAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_CENTER);
|
||||
}
|
||||
|
||||
|
||||
void addListener(GUIEngine::ITextBoxWidgetListener* listener)
|
||||
{
|
||||
m_listeners.push_back(listener);
|
||||
}
|
||||
|
||||
|
||||
void clearListeners()
|
||||
{
|
||||
m_listeners.clearWithoutDeleting();
|
||||
@ -55,7 +55,7 @@ public:
|
||||
virtual bool OnEvent(const SEvent& event)
|
||||
{
|
||||
bool out = CGUIEditBox::OnEvent(event);
|
||||
|
||||
|
||||
if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
|
||||
{
|
||||
for (int n=0; n<m_listeners.size(); n++)
|
||||
@ -63,10 +63,10 @@ public:
|
||||
m_listeners[n].onTextUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
using namespace GUIEngine;
|
||||
@ -85,15 +85,15 @@ TextBoxWidget::TextBoxWidget() : Widget(WTYPE_TEXTBOX)
|
||||
void TextBoxWidget::add()
|
||||
{
|
||||
rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h);
|
||||
|
||||
|
||||
// Don't call TextBoxWidget::getText(), which assumes that the irrlicht
|
||||
// widget already exists.
|
||||
// widget already exists.
|
||||
const stringw& text = Widget::getText();
|
||||
|
||||
|
||||
m_element = new MyCGUIEditBox(text.c_str(), true /* border */, GUIEngine::getGUIEnv(),
|
||||
(m_parent ? m_parent : GUIEngine::getGUIEnv()->getRootGUIElement()),
|
||||
getNewID(), widget_size);
|
||||
|
||||
|
||||
//m_element = GUIEngine::getGUIEnv()->addEditBox(text.c_str(), widget_size,
|
||||
// true /* border */, m_parent, getNewID());
|
||||
m_id = m_element->getID();
|
||||
@ -122,7 +122,7 @@ stringw TextBoxWidget::getText() const
|
||||
{
|
||||
const IGUIEditBox* textCtrl = Widget::getIrrlichtElement<IGUIEditBox>();
|
||||
assert(textCtrl != NULL);
|
||||
|
||||
|
||||
return stringw(textCtrl->getText());
|
||||
}
|
||||
|
||||
@ -131,7 +131,7 @@ stringw TextBoxWidget::getText() const
|
||||
EventPropagation TextBoxWidget::focused(const int playerID)
|
||||
{
|
||||
assert(playerID == 0); // No support for multiple players in text areas!
|
||||
|
||||
|
||||
// special case : to work, the text box must receive "irrLicht focus", STK focus is not enough
|
||||
GUIEngine::getGUIEnv()->setFocus(m_element);
|
||||
setWithinATextBox(true);
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "utils/translation.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
/** Convert thjis binding to XML attributes. The full XML node is actually
|
||||
/** Convert thjis binding to XML attributes. The full XML node is actually
|
||||
* written by device_config, so we only have to add the attributes here.
|
||||
*/
|
||||
void Binding::serialize(std::ofstream& stream) const
|
||||
@ -30,7 +30,7 @@ void Binding::serialize(std::ofstream& stream) const
|
||||
stream << "id=\"" << m_id << "\" "
|
||||
<< "event=\"" << m_type << "\" "
|
||||
<< "character=\"" << m_character << "\" ";
|
||||
|
||||
|
||||
// Only serialize the direction for stick motions
|
||||
if (m_type == Input::IT_STICKMOTION)
|
||||
{
|
||||
@ -74,7 +74,7 @@ bool Binding::deserialize(irr::io::IrrXMLReader* xml)
|
||||
} // deserialize
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns a string representing this binding, which can be displayed on the
|
||||
/** Returns a string representing this binding, which can be displayed on the
|
||||
* screen.
|
||||
*/
|
||||
irr::core::stringw Binding::getAsString() const
|
||||
@ -90,7 +90,7 @@ irr::core::stringw Binding::getAsString() const
|
||||
s = "?";
|
||||
if(m_character)
|
||||
s[0]=m_character;
|
||||
|
||||
|
||||
switch(m_id)
|
||||
{
|
||||
#ifdef WIN32
|
||||
@ -246,10 +246,10 @@ irr::core::stringw Binding::getAsString() const
|
||||
case irr::KEY_PA1 : s = "pa1"; break;
|
||||
case irr::KEY_OEM_CLEAR : s = "oem clear"; break;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case Input::IT_STICKMOTION:
|
||||
|
||||
|
||||
if (m_id == Input::HAT_H_ID)
|
||||
{
|
||||
//I18N: to appear in input configuration screen, for gamepad hats
|
||||
@ -280,6 +280,6 @@ irr::core::stringw Binding::getAsString() const
|
||||
default:
|
||||
s = "?";
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
} // GetKeyAsString
|
||||
|
@ -71,42 +71,42 @@ bool DeviceManager::initialize()
|
||||
m_keyboard_configs.push_back(new KeyboardConfig());
|
||||
created = true;
|
||||
}
|
||||
|
||||
|
||||
const int keyboard_amount = m_keyboard_configs.size();
|
||||
for (int n=0; n<keyboard_amount; n++)
|
||||
{
|
||||
m_keyboards.push_back(new KeyboardDevice(m_keyboard_configs.get(n)));
|
||||
}
|
||||
|
||||
if(UserConfigParams::logMisc())
|
||||
|
||||
if(UserConfigParams::logMisc())
|
||||
printf("Initializing gamepad support.\n");
|
||||
|
||||
irr_driver->getDevice()->activateJoysticks(m_irrlicht_gamepads);
|
||||
int num_gamepads = m_irrlicht_gamepads.size();
|
||||
int num_gamepads = m_irrlicht_gamepads.size();
|
||||
if(UserConfigParams::logMisc())
|
||||
{
|
||||
printf("Irrlicht reports %d gamepads are attached to the system.\n",
|
||||
printf("Irrlicht reports %d gamepads are attached to the system.\n",
|
||||
num_gamepads);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Create GamePadDevice for each physical gamepad and find a GamepadConfig to match
|
||||
for (int id = 0; id < num_gamepads; id++)
|
||||
{
|
||||
core::stringc name = m_irrlicht_gamepads[id].Name;
|
||||
|
||||
|
||||
// Some linux systems report a disk accelerometer as a gamepad, skip that
|
||||
if (name.find("LIS3LV02DL") != -1) continue;
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
// On Windows, unless we use DirectInput, all gamepads are given the
|
||||
// On Windows, unless we use DirectInput, all gamepads are given the
|
||||
// same name ('microsoft pc-joystick driver'). This makes configuration
|
||||
// totally useless, so append an ID to the name. We can't test for the
|
||||
// name, since the name is even translated.
|
||||
name = name + " " + StringUtils::toString(id).c_str();
|
||||
#endif
|
||||
|
||||
|
||||
if (UserConfigParams::logMisc())
|
||||
{
|
||||
printf("#%d: %s detected...", id, name.c_str());
|
||||
@ -114,7 +114,7 @@ bool DeviceManager::initialize()
|
||||
// Returns true if new configuration was created
|
||||
if (getConfigForGamepad(id, name, &gamepadConfig) == true)
|
||||
{
|
||||
if(UserConfigParams::logMisc())
|
||||
if(UserConfigParams::logMisc())
|
||||
printf("creating new configuration.\n");
|
||||
created = true;
|
||||
}
|
||||
@ -125,7 +125,7 @@ bool DeviceManager::initialize()
|
||||
}
|
||||
|
||||
gamepadConfig->setPlugged();
|
||||
gamepadDevice = new GamePadDevice(id,
|
||||
gamepadDevice = new GamePadDevice(id,
|
||||
name.c_str(),
|
||||
m_irrlicht_gamepads[id].Axes,
|
||||
m_irrlicht_gamepads[id].Buttons,
|
||||
@ -141,13 +141,13 @@ bool DeviceManager::initialize()
|
||||
void DeviceManager::setAssignMode(const PlayerAssignMode assignMode)
|
||||
{
|
||||
m_assign_mode = assignMode;
|
||||
|
||||
|
||||
#if INPUT_MODE_DEBUG
|
||||
if (assignMode == NO_ASSIGN) std::cout << "====== DeviceManager::setAssignMode(NO_ASSIGN) ======\n";
|
||||
if (assignMode == ASSIGN) std::cout << "====== DeviceManager::setAssignMode(ASSIGN) ======\n";
|
||||
if (assignMode == DETECT_NEW) std::cout << "====== DeviceManager::setAssignMode(DETECT_NEW) ======\n";
|
||||
#endif
|
||||
|
||||
|
||||
// when going back to no-assign mode, do some cleanup
|
||||
if (assignMode == NO_ASSIGN)
|
||||
{
|
||||
@ -180,7 +180,7 @@ GamePadDevice* DeviceManager::getGamePadFromIrrID(const int id)
|
||||
// -----------------------------------------------------------------------------
|
||||
/**
|
||||
* Check if we already have a config object for gamepad 'irr_id' as reported by
|
||||
* irrLicht, If no, create one. Returns true if new configuration was created,
|
||||
* irrLicht, If no, create one. Returns true if new configuration was created,
|
||||
* otherwise false.
|
||||
*/
|
||||
bool DeviceManager::getConfigForGamepad(const int irr_id,
|
||||
@ -189,7 +189,7 @@ bool DeviceManager::getConfigForGamepad(const int irr_id,
|
||||
{
|
||||
bool found = false;
|
||||
bool configCreated = false;
|
||||
|
||||
|
||||
// Find appropriate configuration
|
||||
for(int n=0; n < m_gamepad_configs.size(); n++)
|
||||
{
|
||||
@ -199,14 +199,14 @@ bool DeviceManager::getConfigForGamepad(const int irr_id,
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If we can't find an appropriate configuration then create one.
|
||||
if (!found)
|
||||
{
|
||||
if(irr_id < (int)(m_irrlicht_gamepads.size()))
|
||||
{
|
||||
*config = new GamepadConfig( name.c_str(),
|
||||
m_irrlicht_gamepads[irr_id].Axes,
|
||||
*config = new GamepadConfig( name.c_str(),
|
||||
m_irrlicht_gamepads[irr_id].Axes,
|
||||
m_irrlicht_gamepads[irr_id].Buttons );
|
||||
}
|
||||
#ifdef ENABLE_WIIUSE
|
||||
@ -265,17 +265,17 @@ bool DeviceManager::deleteConfig(DeviceConfig* config)
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_keyboard_configs.erase(config))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (m_gamepad_configs.erase(config))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
} // deleteConfig
|
||||
|
||||
@ -286,9 +286,9 @@ InputDevice* DeviceManager::mapKeyboardInput( int btnID, InputManager::InputDriv
|
||||
PlayerAction *action /* out */ )
|
||||
{
|
||||
const int keyboard_amount = m_keyboards.size();
|
||||
|
||||
|
||||
//std::cout << "mapKeyboardInput " << btnID << " to " << keyboard_amount << " keyboards\n";
|
||||
|
||||
|
||||
for (int n=0; n<keyboard_amount; n++)
|
||||
{
|
||||
KeyboardDevice *keyboard = m_keyboards.get(n);
|
||||
@ -312,7 +312,7 @@ InputDevice* DeviceManager::mapKeyboardInput( int btnID, InputManager::InputDriv
|
||||
return keyboard;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NULL; // no appropriate binding found
|
||||
} // mapKeyboardInput
|
||||
|
||||
@ -329,14 +329,14 @@ InputDevice *DeviceManager::mapGamepadInput( Input::InputType type,
|
||||
{
|
||||
GamePadDevice *gPad = getGamePadFromIrrID(deviceID);
|
||||
|
||||
if (gPad != NULL)
|
||||
if (gPad != NULL)
|
||||
{
|
||||
if (gPad->processAndMapInput(type, btnID, value, mode, gPad->getPlayer(), action))
|
||||
{
|
||||
if (m_single_player != NULL)
|
||||
{
|
||||
*player = m_single_player;
|
||||
|
||||
|
||||
// in single-player mode, assign the gamepad as needed
|
||||
if (gPad->getPlayer() != m_single_player) gPad->setPlayer(m_single_player);
|
||||
}
|
||||
@ -344,7 +344,7 @@ InputDevice *DeviceManager::mapGamepadInput( Input::InputType type,
|
||||
{
|
||||
*player = NULL;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
*player = gPad->getPlayer();
|
||||
}
|
||||
@ -370,9 +370,9 @@ bool DeviceManager::translateInput( Input::InputType type,
|
||||
{
|
||||
GUIEngine::getCurrentScreen()->filterInput(type, deviceID, btnID, axisDir, value);
|
||||
}
|
||||
|
||||
|
||||
InputDevice *device = NULL;
|
||||
|
||||
|
||||
// If the input event matches a bind on an input device, get a pointer to the device
|
||||
switch (type)
|
||||
{
|
||||
@ -390,11 +390,11 @@ bool DeviceManager::translateInput( Input::InputType type,
|
||||
break;
|
||||
case Input::IT_STICKBUTTON:
|
||||
case Input::IT_STICKMOTION:
|
||||
device = mapGamepadInput(type, deviceID, btnID, axisDir, value,
|
||||
device = mapGamepadInput(type, deviceID, btnID, axisDir, value,
|
||||
mode, player, action);
|
||||
if(!device && m_map_fire_to_select)
|
||||
{
|
||||
device = mapGamepadInput(type, deviceID, btnID, axisDir, value,
|
||||
device = mapGamepadInput(type, deviceID, btnID, axisDir, value,
|
||||
InputManager::INGAME, player, action);
|
||||
if(device && *action == PA_FIRE)
|
||||
*action = PA_MENU_SELECT;
|
||||
@ -404,7 +404,7 @@ bool DeviceManager::translateInput( Input::InputType type,
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Return true if input was successfully translated to an action and player
|
||||
if (device != NULL && abs(value) > Input::MAX_VALUE/2)
|
||||
{
|
||||
@ -418,13 +418,13 @@ bool DeviceManager::translateInput( Input::InputType type,
|
||||
InputDevice* DeviceManager::getLatestUsedDevice()
|
||||
{
|
||||
// If none, probably the user clicked or used enter; give keyboard by default
|
||||
|
||||
|
||||
if (m_latest_used_device == NULL)
|
||||
{
|
||||
{
|
||||
//std::cout<< "========== No latest device, returning keyboard ==========\n";
|
||||
return m_keyboards.get(0); // FIXME: is this right?
|
||||
}
|
||||
|
||||
|
||||
return m_latest_used_device;
|
||||
} // getLatestUsedDevice
|
||||
|
||||
@ -438,7 +438,7 @@ void DeviceManager::clearLatestUsedDevice()
|
||||
bool DeviceManager::deserialize()
|
||||
{
|
||||
static std::string filepath = file_manager->getConfigDir() + "/" + INPUT_FILE_NAME;
|
||||
|
||||
|
||||
if(UserConfigParams::logMisc())
|
||||
printf("Deserializing input.xml...\n");
|
||||
|
||||
@ -450,17 +450,17 @@ bool DeviceManager::deserialize()
|
||||
else
|
||||
{
|
||||
irr::io::IrrXMLReader* xml = irr::io::createIrrXMLReader( filepath.c_str() );
|
||||
|
||||
|
||||
const int GAMEPAD = 1;
|
||||
const int KEYBOARD = 2;
|
||||
const int NOTHING = 3;
|
||||
|
||||
|
||||
int reading_now = NOTHING;
|
||||
|
||||
|
||||
KeyboardConfig* keyboard_config = NULL;
|
||||
GamepadConfig* gamepad_config = NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
// parse XML file
|
||||
while(xml && xml->read())
|
||||
{
|
||||
@ -468,7 +468,7 @@ bool DeviceManager::deserialize()
|
||||
{
|
||||
case irr::io::EXN_TEXT:
|
||||
break;
|
||||
|
||||
|
||||
case irr::io::EXN_ELEMENT:
|
||||
{
|
||||
if (strcmp("input", xml->getNodeName()) == 0)
|
||||
@ -478,7 +478,7 @@ bool DeviceManager::deserialize()
|
||||
{
|
||||
//I18N: shown when config file is too old
|
||||
GUIEngine::showMessage( _("Please re-configure your key bindings.") );
|
||||
|
||||
|
||||
GUIEngine::showMessage( _("Your input config file is not compatible with this version of STK.") );
|
||||
return false;
|
||||
}
|
||||
@ -495,13 +495,13 @@ bool DeviceManager::deserialize()
|
||||
}
|
||||
else if (strcmp("action", xml->getNodeName()) == 0)
|
||||
{
|
||||
if(reading_now == KEYBOARD)
|
||||
if(reading_now == KEYBOARD)
|
||||
{
|
||||
if(keyboard_config != NULL)
|
||||
if(!keyboard_config->deserializeAction(xml))
|
||||
std::cerr << "Ignoring an ill-formed keyboard action in input config.\n";
|
||||
}
|
||||
else if(reading_now == GAMEPAD)
|
||||
else if(reading_now == GAMEPAD)
|
||||
{
|
||||
if(gamepad_config != NULL)
|
||||
if(!gamepad_config->deserializeAction(xml))
|
||||
@ -526,18 +526,18 @@ bool DeviceManager::deserialize()
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default: break;
|
||||
|
||||
|
||||
} // end switch
|
||||
} // end while
|
||||
|
||||
|
||||
if(UserConfigParams::logMisc())
|
||||
{
|
||||
printf("Found %d keyboard and %d gamepad configurations.\n",
|
||||
printf("Found %d keyboard and %d gamepad configurations.\n",
|
||||
m_keyboard_configs.size(), m_gamepad_configs.size());
|
||||
}
|
||||
|
||||
|
||||
// For Debugging....
|
||||
/*
|
||||
for (int n = 0; n < m_keyboard_configs.size(); n++)
|
||||
@ -546,7 +546,7 @@ bool DeviceManager::deserialize()
|
||||
for (int n = 0; n < m_gamepad_configs.size(); n++)
|
||||
printf("%s", m_gamepad_configs[n].toString().c_str());
|
||||
*/
|
||||
|
||||
|
||||
delete xml;
|
||||
}
|
||||
|
||||
@ -556,24 +556,24 @@ bool DeviceManager::deserialize()
|
||||
// -----------------------------------------------------------------------------
|
||||
void DeviceManager::serialize()
|
||||
{
|
||||
static std::string filepath = file_manager->getConfigDir() + "/"
|
||||
static std::string filepath = file_manager->getConfigDir() + "/"
|
||||
+ INPUT_FILE_NAME;
|
||||
if(UserConfigParams::logMisc()) printf("Serializing input.xml...\n");
|
||||
|
||||
|
||||
|
||||
std::ofstream configfile;
|
||||
configfile.open (filepath.c_str());
|
||||
|
||||
|
||||
if(!configfile.is_open())
|
||||
{
|
||||
std::cerr << "Failed to open " << filepath.c_str()
|
||||
std::cerr << "Failed to open " << filepath.c_str()
|
||||
<< " for writing, controls won't be saved\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
configfile << "<input version=\"" << INPUT_FILE_VERSION << "\">\n\n";
|
||||
|
||||
|
||||
for(int n=0; n<m_keyboard_configs.size(); n++)
|
||||
{
|
||||
m_keyboard_configs[n].serialize(configfile);
|
||||
@ -582,12 +582,12 @@ void DeviceManager::serialize()
|
||||
{
|
||||
m_gamepad_configs[n].serialize(configfile);
|
||||
}
|
||||
|
||||
|
||||
configfile << "</input>\n";
|
||||
configfile.close();
|
||||
configfile.close();
|
||||
if(UserConfigParams::logMisc()) printf("Serialization complete.\n\n");
|
||||
} // serialize
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
KeyboardDevice* DeviceManager::getKeyboardFromBtnID(const int btnID)
|
||||
@ -595,10 +595,10 @@ KeyboardDevice* DeviceManager::getKeyboardFromBtnID(const int btnID)
|
||||
const int keyboard_amount = m_keyboards.size();
|
||||
for (int n=0; n<keyboard_amount; n++)
|
||||
{
|
||||
if (m_keyboards[n].getConfiguration()->hasBindingFor(btnID))
|
||||
if (m_keyboards[n].getConfiguration()->hasBindingFor(btnID))
|
||||
return m_keyboards.get(n);
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
} // getKeyboardFromBtnID
|
||||
|
||||
|
@ -48,20 +48,20 @@ KeyboardDevice::KeyboardDevice()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool KeyboardDevice::processAndMapInput(const int id,
|
||||
bool KeyboardDevice::processAndMapInput(const int id,
|
||||
InputManager::InputDriverMode mode,
|
||||
PlayerAction* action /* out */)
|
||||
{
|
||||
if (mode == InputManager::INGAME)
|
||||
{
|
||||
return m_configuration->getGameAction(Input::IT_KEYBOARD, id, 0,
|
||||
return m_configuration->getGameAction(Input::IT_KEYBOARD, id, 0,
|
||||
action);
|
||||
}
|
||||
else
|
||||
{
|
||||
// bindings can only be accessed in game and menu modes
|
||||
assert(mode == InputManager::MENU);
|
||||
return m_configuration->getMenuAction(Input::IT_KEYBOARD, id, 0,
|
||||
return m_configuration->getMenuAction(Input::IT_KEYBOARD, id, 0,
|
||||
action);
|
||||
}
|
||||
} // processAndMapInput
|
||||
@ -74,8 +74,8 @@ bool KeyboardDevice::processAndMapInput(const int id,
|
||||
#endif
|
||||
|
||||
|
||||
GamePadDevice::GamePadDevice(const int irrIndex, const std::string name,
|
||||
const int axis_count, const int button_count,
|
||||
GamePadDevice::GamePadDevice(const int irrIndex, const std::string name,
|
||||
const int axis_count, const int button_count,
|
||||
GamepadConfig *configuration)
|
||||
{
|
||||
m_type = DT_GAMEPAD;
|
||||
@ -89,7 +89,7 @@ GamePadDevice::GamePadDevice(const int irrIndex, const std::string name,
|
||||
m_button_count = button_count;
|
||||
m_index = irrIndex;
|
||||
m_name = name;
|
||||
|
||||
|
||||
for (int i = 0; i < axis_count; i++)
|
||||
{
|
||||
m_prevAxisDirections[i] = Input::AD_NEUTRAL;
|
||||
@ -129,8 +129,8 @@ void GamePadDevice::setButtonPressed(const int i, bool isButtonPressed)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void GamePadDevice::resetAxisDirection(const int axis,
|
||||
Input::AxisDirection direction,
|
||||
void GamePadDevice::resetAxisDirection(const int axis,
|
||||
Input::AxisDirection direction,
|
||||
StateManager::ActivePlayer* player)
|
||||
{
|
||||
// ignore this while in menus
|
||||
@ -142,7 +142,7 @@ void GamePadDevice::resetAxisDirection(const int axis,
|
||||
fprintf(stderr, "Error, trying to reset axis for an unknown player\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for(int n=0; n<PA_COUNT; n++)
|
||||
{
|
||||
Binding& bind = m_configuration->getBinding(n);
|
||||
@ -161,22 +161,22 @@ void GamePadDevice::resetAxisDirection(const int axis,
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
|
||||
bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
|
||||
const int value,
|
||||
InputManager::InputDriverMode mode,
|
||||
StateManager::ActivePlayer* player,
|
||||
PlayerAction* action /* out */)
|
||||
{
|
||||
if (!m_configuration->isEnabled()) return false;
|
||||
|
||||
|
||||
bool success = false;
|
||||
if(m_prevAxisDirections == NULL) return false; // device not open
|
||||
|
||||
|
||||
if (type == Input::IT_STICKMOTION)
|
||||
{
|
||||
// this gamepad doesn't even have that many axes
|
||||
if (id >= m_axis_count) return false;
|
||||
|
||||
|
||||
if (player != NULL)
|
||||
{
|
||||
// going to negative from positive
|
||||
@ -186,14 +186,14 @@ bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
|
||||
resetAxisDirection(id, Input::AD_POSITIVE, player);
|
||||
}
|
||||
// going to positive from negative
|
||||
else if (value > 0 &&
|
||||
else if (value > 0 &&
|
||||
m_prevAxisDirections[id] == Input::AD_NEGATIVE)
|
||||
{
|
||||
// set negative id to 0
|
||||
resetAxisDirection(id, Input::AD_NEGATIVE, player);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (value > 0) m_prevAxisDirections[id] = Input::AD_POSITIVE;
|
||||
else if(value < 0) m_prevAxisDirections[id] = Input::AD_NEGATIVE;
|
||||
|
||||
@ -210,7 +210,7 @@ bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
|
||||
m_axis_ok[id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check if within deadzone
|
||||
if(value > -m_deadzone && value < m_deadzone && player != NULL)
|
||||
{
|
||||
@ -236,11 +236,11 @@ bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// If axis did not send proper values yet, ignore it.
|
||||
if (!m_axis_ok[id]) return false;
|
||||
}
|
||||
|
||||
|
||||
if (m_configuration != NULL)
|
||||
{
|
||||
if (mode == InputManager::INGAME)
|
||||
|
@ -103,7 +103,7 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
switch (key)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Special debug options for profile mode: switch the
|
||||
// Special debug options for profile mode: switch the
|
||||
// camera to show a different kart.
|
||||
case KEY_KEY_1:
|
||||
case KEY_KEY_2:
|
||||
@ -134,20 +134,20 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
case KEY_KEY_I:
|
||||
{
|
||||
if (!world || !UserConfigParams::m_artist_debug_mode) break;
|
||||
|
||||
|
||||
AbstractKart* kart = world->getLocalPlayerKart(0);
|
||||
if (kart == NULL) break;
|
||||
|
||||
|
||||
kart->flyUp();
|
||||
break;
|
||||
}
|
||||
case KEY_KEY_K:
|
||||
{
|
||||
if (!world || !UserConfigParams::m_artist_debug_mode) break;
|
||||
|
||||
|
||||
AbstractKart* kart = world->getLocalPlayerKart(0);
|
||||
if (kart == NULL) break;
|
||||
|
||||
|
||||
kart->flyDown();
|
||||
break;
|
||||
}
|
||||
@ -155,10 +155,10 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
case KEY_PRINT:
|
||||
// on windows we don't get a press event, only release. So
|
||||
// save on release only (to avoid saving twice on other platforms)
|
||||
if (value ==0 )
|
||||
if (value ==0 )
|
||||
irr_driver->requestScreenshot();
|
||||
break;
|
||||
|
||||
|
||||
case KEY_F1:
|
||||
if (UserConfigParams::m_artist_debug_mode && world)
|
||||
{
|
||||
@ -213,7 +213,7 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
kart->setPowerup(PowerupManager::POWERUP_ZIPPER, 10000);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case KEY_F8:
|
||||
if (UserConfigParams::m_artist_debug_mode && value && world)
|
||||
{
|
||||
@ -221,7 +221,7 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
{
|
||||
RaceGUIBase* gui = world->getRaceGUI();
|
||||
if (gui != NULL) gui->m_enabled = !gui->m_enabled;
|
||||
|
||||
|
||||
const int count = World::getWorld()->getNumKarts();
|
||||
for (int n=0; n<count; n++)
|
||||
{
|
||||
@ -237,7 +237,7 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case KEY_F9:
|
||||
if (UserConfigParams::m_artist_debug_mode && world)
|
||||
{
|
||||
@ -250,7 +250,7 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
kart->setPowerup(PowerupManager::POWERUP_SWATTER, 10000);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case KEY_F10:
|
||||
if(world && value)
|
||||
{
|
||||
@ -260,9 +260,9 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
history->Save();
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case KEY_F11:
|
||||
if (UserConfigParams::m_artist_debug_mode && value &&
|
||||
if (UserConfigParams::m_artist_debug_mode && value &&
|
||||
control_is_pressed && world)
|
||||
{
|
||||
world->getPhysics()->nextDebugMode();
|
||||
@ -271,14 +271,14 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
|
||||
case KEY_F12:
|
||||
if(value)
|
||||
UserConfigParams::m_display_fps =
|
||||
UserConfigParams::m_display_fps =
|
||||
!UserConfigParams::m_display_fps;
|
||||
break;
|
||||
|
||||
|
||||
case KEY_KEY_P:
|
||||
if (UserConfigParams::m_artist_debug_mode && value &&
|
||||
if (UserConfigParams::m_artist_debug_mode && value &&
|
||||
control_is_pressed)
|
||||
UserConfigParams::m_profiler_enabled =
|
||||
UserConfigParams::m_profiler_enabled =
|
||||
!UserConfigParams::m_profiler_enabled;
|
||||
break;
|
||||
default:
|
||||
@ -291,30 +291,30 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
/**
|
||||
* Handles input when an input sensing mode (when configuring input)
|
||||
*/
|
||||
void InputManager::inputSensing(Input::InputType type, int deviceID,
|
||||
void InputManager::inputSensing(Input::InputType type, int deviceID,
|
||||
int button, Input::AxisDirection axisDirection,
|
||||
int value)
|
||||
{
|
||||
#if INPUT_MODE_DEBUG
|
||||
std::cout << "INPUT SENSING... ";
|
||||
#endif
|
||||
|
||||
// don't store if we're trying to do something like bindings keyboard
|
||||
|
||||
// don't store if we're trying to do something like bindings keyboard
|
||||
// keys on a gamepad
|
||||
if (m_mode == INPUT_SENSE_KEYBOARD && type != Input::IT_KEYBOARD)
|
||||
return;
|
||||
if (m_mode == INPUT_SENSE_GAMEPAD && type != Input::IT_STICKMOTION &&
|
||||
if (m_mode == INPUT_SENSE_GAMEPAD && type != Input::IT_STICKMOTION &&
|
||||
type != Input::IT_STICKBUTTON)
|
||||
return;
|
||||
|
||||
#if INPUT_MODE_DEBUG
|
||||
std::cout << (store_new ? "storing it" : "ignoring it") << "\n";
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case Input::IT_KEYBOARD:
|
||||
case Input::IT_KEYBOARD:
|
||||
if (value > Input::MAX_VALUE/2)
|
||||
{
|
||||
m_sensed_input_high_kbd.insert(button);
|
||||
@ -349,7 +349,7 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
|
||||
case Input::IT_STICKMOTION:
|
||||
{
|
||||
std::cout << "%% storing new axis binding, value=" << value <<
|
||||
" deviceID=" << deviceID << " button=" << button <<
|
||||
" deviceID=" << deviceID << " button=" << button <<
|
||||
" axisDirection=" <<
|
||||
(axisDirection == Input::AD_NEGATIVE ? "-" : "+") << "\n";
|
||||
// We have to save the direction in which the axis was moved.
|
||||
@ -357,18 +357,18 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
|
||||
// be zero, we add one before changing the sign).
|
||||
int input_id = value>=0 ? 1+button : -(1+button);
|
||||
|
||||
bool id_was_high = m_sensed_input_high_gamepad.find(input_id)
|
||||
bool id_was_high = m_sensed_input_high_gamepad.find(input_id)
|
||||
!= m_sensed_input_high_gamepad.end();
|
||||
bool inverse_id_was_high = m_sensed_input_high_gamepad.find(-input_id)
|
||||
!= m_sensed_input_high_gamepad.end();
|
||||
|
||||
// A stick was pushed far enough (for the first time) to count as
|
||||
// 'triggered' - save the axis (coded with direction in the button
|
||||
// value) for later, so that it can be registered when the stick is
|
||||
// value) for later, so that it can be registered when the stick is
|
||||
// released again.
|
||||
// This is mostly legacy behaviour, it is probably good enough
|
||||
// to register this as soon as the value is high enough.
|
||||
if (!id_was_high && abs(value) > Input::MAX_VALUE*6.0f/7.0f)
|
||||
if (!id_was_high && abs(value) > Input::MAX_VALUE*6.0f/7.0f)
|
||||
{
|
||||
m_sensed_input_high_gamepad.insert(input_id);
|
||||
}
|
||||
@ -378,7 +378,7 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
|
||||
sensed_input.m_type = type;
|
||||
sensed_input.m_device_id = deviceID;
|
||||
sensed_input.m_button_id = button;
|
||||
sensed_input.m_axis_direction = value>=0 ? Input::AD_POSITIVE
|
||||
sensed_input.m_axis_direction = value>=0 ? Input::AD_POSITIVE
|
||||
: Input::AD_NEGATIVE;
|
||||
sensed_input.m_character = deviceID;
|
||||
OptionsScreenInput2::getInstance()->gotSensedInput(sensed_input);
|
||||
@ -411,11 +411,11 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
|
||||
//-----------------------------------------------------------------------------
|
||||
int InputManager::getPlayerKeyboardID() const
|
||||
{
|
||||
// In no-assign mode, just return the GUI player ID (devices not
|
||||
// In no-assign mode, just return the GUI player ID (devices not
|
||||
// assigned yet)
|
||||
if (m_device_manager->getAssignMode() == NO_ASSIGN)
|
||||
if (m_device_manager->getAssignMode() == NO_ASSIGN)
|
||||
return PLAYER_ID_GAME_MASTER;
|
||||
|
||||
|
||||
// Otherwise, after devices are assigned, we can check in more depth
|
||||
// Return the first keyboard that is actually being used
|
||||
const int amount = m_device_manager->getKeyboardAmount();
|
||||
@ -427,7 +427,7 @@ int InputManager::getPlayerKeyboardID() const
|
||||
return m_device_manager->getKeyboard(k)->getPlayer()->getID();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -443,8 +443,8 @@ int InputManager::getPlayerKeyboardID() const
|
||||
* Note: It is the obligation of the called menu to switch of the sense mode.
|
||||
*
|
||||
*/
|
||||
void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
int button,
|
||||
void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
int button,
|
||||
Input::AxisDirection axisDirection, int value)
|
||||
{
|
||||
// Act different in input sensing mode.
|
||||
@ -454,7 +454,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
inputSensing(type, deviceID, button, axisDirection, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Abort demo mode if a key is pressed during the race in demo mode
|
||||
if(dynamic_cast<DemoWorld*>(World::getWorld()))
|
||||
{
|
||||
@ -465,16 +465,16 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
|
||||
StateManager::ActivePlayer* player = NULL;
|
||||
PlayerAction action;
|
||||
bool action_found = m_device_manager->translateInput(type, deviceID,
|
||||
bool action_found = m_device_manager->translateInput(type, deviceID,
|
||||
button, axisDirection,
|
||||
value, m_mode,
|
||||
value, m_mode,
|
||||
&player, &action);
|
||||
|
||||
// in menus, some keyboard keys are standard (before each player selected
|
||||
// his device). So if a key could not be mapped to any known binding,
|
||||
// in menus, some keyboard keys are standard (before each player selected
|
||||
// his device). So if a key could not be mapped to any known binding,
|
||||
// fall back to check the defaults.
|
||||
if (!action_found &&
|
||||
StateManager::get()->getGameState() != GUIEngine::GAME &&
|
||||
if (!action_found &&
|
||||
StateManager::get()->getGameState() != GUIEngine::GAME &&
|
||||
type == Input::IT_KEYBOARD &&
|
||||
m_mode == MENU && m_device_manager->getAssignMode() == NO_ASSIGN)
|
||||
{
|
||||
@ -491,23 +491,23 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
{
|
||||
GUIEngine::ModalDialog::onEnterPressed();
|
||||
}
|
||||
|
||||
|
||||
if (action != PA_BEFORE_FIRST)
|
||||
{
|
||||
action_found = true;
|
||||
player = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// do something with the key if it matches a binding
|
||||
if (action_found)
|
||||
{
|
||||
// If we're in the kart menu awaiting new players, do special things
|
||||
// when a device presses fire or rescue
|
||||
if (m_device_manager->getAssignMode() == DETECT_NEW)
|
||||
{
|
||||
{
|
||||
// Player is unjoining
|
||||
if ((player != NULL) && (action == PA_RESCUE ||
|
||||
if ((player != NULL) && (action == PA_RESCUE ||
|
||||
action == PA_MENU_CANCEL ) )
|
||||
{
|
||||
// returns true if the event was handled
|
||||
@ -534,11 +534,11 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
InputDevice *device = NULL;
|
||||
if (type == Input::IT_KEYBOARD)
|
||||
{
|
||||
//std::cout << "==== New Player Joining with Key " <<
|
||||
//std::cout << "==== New Player Joining with Key " <<
|
||||
// button << " ====" << std::endl;
|
||||
device = m_device_manager->getKeyboardFromBtnID(button);
|
||||
}
|
||||
else if (type == Input::IT_STICKBUTTON ||
|
||||
else if (type == Input::IT_STICKBUTTON ||
|
||||
type == Input::IT_STICKMOTION )
|
||||
{
|
||||
device = m_device_manager->getGamePadFromIrrID(deviceID);
|
||||
@ -546,17 +546,17 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
|
||||
if (device != NULL)
|
||||
{
|
||||
KartSelectionScreen::getInstance()->playerJoin(device,
|
||||
KartSelectionScreen::getInstance()->playerJoin(device,
|
||||
false );
|
||||
}
|
||||
}
|
||||
return; // we're done here, ignore devices that aren't
|
||||
return; // we're done here, ignore devices that aren't
|
||||
// associated with players
|
||||
}
|
||||
}
|
||||
|
||||
// ... when in-game
|
||||
if (StateManager::get()->getGameState() == GUIEngine::GAME &&
|
||||
if (StateManager::get()->getGameState() == GUIEngine::GAME &&
|
||||
!GUIEngine::ModalDialog::isADialogActive() )
|
||||
{
|
||||
if (player == NULL)
|
||||
@ -574,7 +574,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
"Error, trying to process action for an unknown player\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Controller* controller = pk->getController();
|
||||
if (controller != NULL) controller->action(action, abs(value));
|
||||
}
|
||||
@ -589,15 +589,15 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
m_timer = 0;
|
||||
}
|
||||
|
||||
// When in master-only mode, we can safely assume that players
|
||||
// are set up, contrarly to early menus where we accept every
|
||||
// When in master-only mode, we can safely assume that players
|
||||
// are set up, contrarly to early menus where we accept every
|
||||
// input because players are not set-up yet
|
||||
if (m_master_player_only && player == NULL)
|
||||
{
|
||||
if (type == Input::IT_STICKMOTION ||
|
||||
if (type == Input::IT_STICKMOTION ||
|
||||
type == Input::IT_STICKBUTTON)
|
||||
{
|
||||
GamePadDevice* gp =
|
||||
GamePadDevice* gp =
|
||||
getDeviceList()->getGamePadFromIrrID(deviceID);
|
||||
|
||||
if (gp != NULL &&
|
||||
@ -612,7 +612,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// menu input
|
||||
if (!m_timer_in_use)
|
||||
{
|
||||
@ -621,36 +621,36 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
m_timer_in_use = true;
|
||||
m_timer = 0.25;
|
||||
}
|
||||
|
||||
// player may be NULL in early menus, before player setup has
|
||||
|
||||
// player may be NULL in early menus, before player setup has
|
||||
// been performed
|
||||
int playerID = (player == NULL ? 0 : player->getID());
|
||||
|
||||
// If only the master player can act, and this player is not
|
||||
|
||||
// If only the master player can act, and this player is not
|
||||
// the master, ignore his input
|
||||
if (m_device_manager->getAssignMode() == ASSIGN &&
|
||||
if (m_device_manager->getAssignMode() == ASSIGN &&
|
||||
m_master_player_only &&
|
||||
playerID != PLAYER_ID_GAME_MASTER)
|
||||
{
|
||||
//I18N: message shown when a player that isn't game master
|
||||
//I18N: tries to modify options that only the game master
|
||||
//I18N: tries to modify options that only the game master
|
||||
//I18N: is allowed to
|
||||
GUIEngine::showMessage(
|
||||
_("Only the Game Master may act at this point!"));
|
||||
return;
|
||||
}
|
||||
|
||||
// all is good, pass the translated input event on to the
|
||||
|
||||
// all is good, pass the translated input event on to the
|
||||
// event handler
|
||||
GUIEngine::EventHandler::get()
|
||||
->processGUIAction(action, deviceID, abs(value), type,
|
||||
->processGUIAction(action, deviceID, abs(value), type,
|
||||
playerID);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == Input::IT_KEYBOARD)
|
||||
{
|
||||
// keyboard press not handled by device manager / bindings.
|
||||
// keyboard press not handled by device manager / bindings.
|
||||
// Check static bindings...
|
||||
handleStaticAction( button, value );
|
||||
}
|
||||
@ -661,7 +661,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
void InputManager::setMasterPlayerOnly(bool enabled)
|
||||
{
|
||||
#if INPUT_MODE_DEBUG
|
||||
std::cout <<
|
||||
std::cout <<
|
||||
"====== InputManager::setMasterPlayerOnly(" << enabled << ") ======\n";
|
||||
#endif
|
||||
m_master_player_only = enabled;
|
||||
@ -693,24 +693,24 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
{
|
||||
if (event.EventType == EET_JOYSTICK_INPUT_EVENT)
|
||||
{
|
||||
// Axes - FIXME, instead of checking all of them, ask the bindings
|
||||
// Axes - FIXME, instead of checking all of them, ask the bindings
|
||||
// which ones to poll
|
||||
for (int axis_id=0; axis_id<SEvent::SJoystickEvent::NUMBER_OF_AXES ;
|
||||
for (int axis_id=0; axis_id<SEvent::SJoystickEvent::NUMBER_OF_AXES ;
|
||||
axis_id++)
|
||||
{
|
||||
int value = event.JoystickEvent.Axis[axis_id];
|
||||
|
||||
if (UserConfigParams::m_gamepad_debug)
|
||||
{
|
||||
Log::info("InputManager",
|
||||
Log::info("InputManager",
|
||||
"axis motion: gamepad_id=%d axis=%d value=%d",
|
||||
event.JoystickEvent.Joystick, axis_id, value);
|
||||
}
|
||||
|
||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||
axis_id, Input::AD_NEUTRAL, value);
|
||||
}
|
||||
|
||||
|
||||
if (event.JoystickEvent.POV == 65535)
|
||||
{
|
||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||
@ -721,7 +721,7 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
else
|
||||
{
|
||||
// *0.017453925f is to convert degrees to radians
|
||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||
Input::HAT_H_ID, Input::AD_NEUTRAL,
|
||||
(int)(cos(event.JoystickEvent.POV*0.017453925f/100.0f)
|
||||
*Input::MAX_VALUE));
|
||||
@ -730,8 +730,8 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
(int)(sin(event.JoystickEvent.POV*0.017453925f/100.0f)
|
||||
*Input::MAX_VALUE));
|
||||
}
|
||||
|
||||
GamePadDevice* gp =
|
||||
|
||||
GamePadDevice* gp =
|
||||
getDeviceList()->getGamePadFromIrrID(event.JoystickEvent.Joystick);
|
||||
|
||||
if (gp == NULL)
|
||||
@ -743,9 +743,9 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
for(int i=0; i<gp->m_button_count; i++)
|
||||
{
|
||||
const bool isButtonPressed = event.JoystickEvent.IsButtonPressed(i);
|
||||
|
||||
|
||||
// Only report button events when the state of the button changes
|
||||
if ((!gp->isButtonPressed(i) && isButtonPressed) ||
|
||||
if ((!gp->isButtonPressed(i) && isButtonPressed) ||
|
||||
(gp->isButtonPressed(i) && !isButtonPressed) )
|
||||
{
|
||||
if (UserConfigParams::m_gamepad_debug)
|
||||
@ -753,9 +753,9 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
Log::info("InputManager", "button %i, status=%i",
|
||||
i, isButtonPressed);
|
||||
}
|
||||
|
||||
dispatchInput(Input::IT_STICKBUTTON,
|
||||
event.JoystickEvent.Joystick, i,
|
||||
|
||||
dispatchInput(Input::IT_STICKBUTTON,
|
||||
event.JoystickEvent.Joystick, i,
|
||||
Input::AD_POSITIVE,
|
||||
isButtonPressed ? Input::MAX_VALUE : 0);
|
||||
}
|
||||
@ -765,7 +765,7 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
}
|
||||
else if (event.EventType == EET_KEY_INPUT_EVENT)
|
||||
{
|
||||
// On some systems (linux esp.) certain keys (e.g. [] ) have a 0
|
||||
// On some systems (linux esp.) certain keys (e.g. [] ) have a 0
|
||||
// Key value, but do have a value defined in the Char field.
|
||||
// So to distinguish them (otherwise [] would both be mapped to
|
||||
// the same value 0, which means we can't distinguish which key
|
||||
@ -784,7 +784,7 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
// 'backspace' in a text control must never be mapped, since user
|
||||
// can be in a text area trying to erase text (and if it's mapped
|
||||
// can be in a text area trying to erase text (and if it's mapped
|
||||
// to rescue that would dismiss the dialog instead of erasing a
|
||||
// single letter). Same for spacebar. Same for letters.
|
||||
if (GUIEngine::isWithinATextBox())
|
||||
@ -798,12 +798,12 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
return EVENT_LET;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const bool wasInTextBox = GUIEngine::isWithinATextBox();
|
||||
|
||||
|
||||
dispatchInput(Input::IT_KEYBOARD, event.KeyInput.Char, key,
|
||||
Input::AD_POSITIVE, Input::MAX_VALUE);
|
||||
|
||||
|
||||
// if this action took us into a text box, don't let event continue
|
||||
// (FIXME not the cleanest solution)
|
||||
if (!wasInTextBox && GUIEngine::isWithinATextBox())
|
||||
@ -815,8 +815,8 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
else
|
||||
{
|
||||
// 'backspace' in a text control must never be mapped, since user
|
||||
// can be in a text area trying to erase text (and if it's mapped
|
||||
// to rescue that would dismiss the dialog instead of erasing a
|
||||
// can be in a text area trying to erase text (and if it's mapped
|
||||
// to rescue that would dismiss the dialog instead of erasing a
|
||||
// single letter). Same for spacebar. Same for letters.
|
||||
if (GUIEngine::isWithinATextBox())
|
||||
{
|
||||
@ -829,8 +829,8 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
return EVENT_LET;
|
||||
}
|
||||
}
|
||||
|
||||
dispatchInput(Input::IT_KEYBOARD, event.KeyInput.Char, key,
|
||||
|
||||
dispatchInput(Input::IT_KEYBOARD, event.KeyInput.Char, key,
|
||||
Input::AD_POSITIVE, 0);
|
||||
return EVENT_BLOCK; // Don't propagate key up events
|
||||
}
|
||||
@ -855,20 +855,20 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
EMIE_RMOUSE_LEFT_UP Right mouse button was left up.
|
||||
EMIE_MMOUSE_LEFT_UP Middle mouse button was left up.
|
||||
EMIE_MOUSE_MOVED The mouse cursor changed its position.
|
||||
EMIE_MOUSE_WHEEL The mouse wheel was moved. Use Wheel value in
|
||||
event data to find out in what direction and
|
||||
EMIE_MOUSE_WHEEL The mouse wheel was moved. Use Wheel value in
|
||||
event data to find out in what direction and
|
||||
how fast.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
// block events in all modes but initial menus (except in text boxes to
|
||||
|
||||
// block events in all modes but initial menus (except in text boxes to
|
||||
// allow typing, and except in modal dialogs in-game)
|
||||
// FIXME: 1) that's awful logic 2) that's not what the code below does,
|
||||
// FIXME: 1) that's awful logic 2) that's not what the code below does,
|
||||
// events are never blocked in menus
|
||||
if (getDeviceList()->getAssignMode() != NO_ASSIGN &&
|
||||
if (getDeviceList()->getAssignMode() != NO_ASSIGN &&
|
||||
!GUIEngine::isWithinATextBox() &&
|
||||
(!GUIEngine::ModalDialog::isADialogActive() &&
|
||||
(!GUIEngine::ModalDialog::isADialogActive() &&
|
||||
StateManager::get()->getGameState() == GUIEngine::GAME))
|
||||
{
|
||||
return EVENT_BLOCK;
|
||||
@ -911,7 +911,7 @@ bool InputManager::isInMode(InputDriverMode expMode)
|
||||
void InputManager::setMode(InputDriverMode new_mode)
|
||||
{
|
||||
if (new_mode == m_mode) return; // no change
|
||||
|
||||
|
||||
switch (new_mode)
|
||||
{
|
||||
case MENU:
|
||||
@ -933,7 +933,7 @@ void InputManager::setMode(InputDriverMode new_mode)
|
||||
//irr_driver->showPointer();
|
||||
m_mode = MENU;
|
||||
break;
|
||||
|
||||
|
||||
case BOOTSTRAP:
|
||||
// Leaving boot strap mode.
|
||||
|
||||
@ -952,13 +952,13 @@ void InputManager::setMode(InputDriverMode new_mode)
|
||||
m_sensed_input_high_gamepad.clear();
|
||||
m_sensed_input_high_kbd.clear();
|
||||
|
||||
// The order is deliberate just in case someone starts
|
||||
// to make STK multithreaded: m_sensed_input must not be
|
||||
// The order is deliberate just in case someone starts
|
||||
// to make STK multithreaded: m_sensed_input must not be
|
||||
// 0 when mode == INPUT_SENSE_PREFER_{AXIS,BUTTON}.
|
||||
m_mode = MENU;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
case LOWLEVEL:
|
||||
// Leaving lowlevel mode.
|
||||
@ -973,7 +973,7 @@ void InputManager::setMode(InputDriverMode new_mode)
|
||||
// Something is broken.
|
||||
//assert (false);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case INGAME:
|
||||
#if INPUT_MODE_DEBUG
|
||||
@ -1001,7 +1001,7 @@ void InputManager::setMode(InputDriverMode new_mode)
|
||||
// We must be in menu mode now in order to switch.
|
||||
assert (m_mode == MENU);
|
||||
|
||||
// Reset the helper values for the relative mouse movement
|
||||
// Reset the helper values for the relative mouse movement
|
||||
// supresses to the notification of them as an input.
|
||||
m_mouse_val_x = m_mouse_val_y = 0;
|
||||
m_mode = new_mode;
|
||||
|
@ -27,17 +27,17 @@
|
||||
|
||||
|
||||
|
||||
Wiimote::Wiimote(wiimote_t* wiimote_handle, int wiimote_id,
|
||||
Wiimote::Wiimote(wiimote_t* wiimote_handle, int wiimote_id,
|
||||
GamepadConfig* gamepad_config)
|
||||
{
|
||||
m_wiimote_handle = wiimote_handle;
|
||||
m_wiimote_id = wiimote_id;
|
||||
resetIrrEvent();
|
||||
|
||||
|
||||
m_connected = true;
|
||||
|
||||
// Create the corresponding gamepad device
|
||||
irr::core::stringc gamepad_name = irr::core::stringc("Wiimote ") +
|
||||
|
||||
// Create the corresponding gamepad device
|
||||
irr::core::stringc gamepad_name = irr::core::stringc("Wiimote ") +
|
||||
StringUtils::toString(wiimote_id).c_str();
|
||||
|
||||
gamepad_config->setPlugged();
|
||||
@ -72,7 +72,7 @@ void Wiimote::resetIrrEvent()
|
||||
} // resetIrrEvent
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Called from the update thread: takes the wiimote state and
|
||||
/** Called from the update thread: takes the wiimote state and
|
||||
*/
|
||||
void Wiimote::update()
|
||||
{
|
||||
@ -80,8 +80,8 @@ void Wiimote::update()
|
||||
if(UserConfigParams::m_wiimote_debug)
|
||||
{
|
||||
Log::verbose("wiimote", "pitch: %f yaw %f roll %f",
|
||||
m_wiimote_handle->orient.pitch,
|
||||
m_wiimote_handle->orient.yaw,
|
||||
m_wiimote_handle->orient.pitch,
|
||||
m_wiimote_handle->orient.yaw,
|
||||
m_wiimote_handle->orient.roll);
|
||||
}
|
||||
#endif
|
||||
@ -92,7 +92,7 @@ void Wiimote::update()
|
||||
else if(normalized_angle>1.0f)
|
||||
normalized_angle = 1.0f;
|
||||
|
||||
// Shape the curve that determines steering depending on wiimote angle.
|
||||
// Shape the curve that determines steering depending on wiimote angle.
|
||||
// The wiimote value is already normalized to be in [-1,1]. Now use a
|
||||
// weighted linear combination to compute the steering value used in game.
|
||||
float w1 = UserConfigParams::m_wiimote_weight_linear;
|
||||
@ -114,8 +114,8 @@ void Wiimote::update()
|
||||
|
||||
irr::SEvent::SJoystickEvent &ev = m_irr_event.getData().JoystickEvent;
|
||||
ev.Axis[SEvent::SJoystickEvent::AXIS_X] =
|
||||
(irr::s16)(irr::core::clamp(angle, -JOYSTICK_ABS_MAX_ANGLE,
|
||||
+JOYSTICK_ABS_MAX_ANGLE));
|
||||
(irr::s16)(irr::core::clamp(angle, -JOYSTICK_ABS_MAX_ANGLE,
|
||||
+JOYSTICK_ABS_MAX_ANGLE));
|
||||
// --------------------- Wiimote buttons --------------------
|
||||
// Copy the wiimote button structure, but mask out the non-button
|
||||
// bits (4 bits of the button structure are actually bits for the
|
||||
@ -163,14 +163,14 @@ void Wiimote::printDebugInfo() const
|
||||
if(IS_PRESSED(m_wiimote_handle, wiimote_actions[i].wiimote_action_id))
|
||||
{
|
||||
Log::verbose("wiimote", "%d: pressed button %s -> button id: %d",
|
||||
m_wiimote_id, wiimote_actions[i].wiimote_action_name,
|
||||
m_wiimote_id, wiimote_actions[i].wiimote_action_name,
|
||||
i);
|
||||
}
|
||||
} // for i < count
|
||||
} // printDebugInfo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Thread-safe reading of the last updated event
|
||||
/** Thread-safe reading of the last updated event
|
||||
*/
|
||||
irr::SEvent Wiimote::getIrrEvent()
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ WiimoteManager::~WiimoteManager()
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/**
|
||||
* Launch wiimote detection and add the corresponding gamepad devices to the
|
||||
* Launch wiimote detection and add the corresponding gamepad devices to the
|
||||
* device manager.
|
||||
* TODO: this should be done in a separate thread, to not block the UI...
|
||||
*/
|
||||
@ -62,44 +62,44 @@ void WiimoteManager::launchDetection(int timeout)
|
||||
{
|
||||
// Stop WiiUse, remove wiimotes, gamepads, gamepad configs.
|
||||
cleanup();
|
||||
|
||||
|
||||
m_all_wiimote_handles = wiiuse_init(MAX_WIIMOTES);
|
||||
|
||||
|
||||
// Detect wiimotes
|
||||
int nb_found_wiimotes = wiiuse_find(m_all_wiimote_handles, MAX_WIIMOTES, timeout);
|
||||
|
||||
|
||||
// Couldn't find any wiimote?
|
||||
if(nb_found_wiimotes == 0)
|
||||
return;
|
||||
|
||||
|
||||
// Try to connect to all found wiimotes
|
||||
int nb_wiimotes = wiiuse_connect(m_all_wiimote_handles, nb_found_wiimotes);
|
||||
|
||||
|
||||
// Couldn't connect to any wiimote?
|
||||
if(nb_wiimotes == 0)
|
||||
return;
|
||||
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Create or find a GamepadConfig for all wiimotes
|
||||
DeviceManager* device_manager = input_manager->getDeviceList();
|
||||
GamepadConfig* gamepad_config = NULL;
|
||||
|
||||
device_manager->getConfigForGamepad(WIIMOTE_START_IRR_ID, "Wiimote",
|
||||
|
||||
device_manager->getConfigForGamepad(WIIMOTE_START_IRR_ID, "Wiimote",
|
||||
&gamepad_config);
|
||||
int num_buttons = (int)( log((float)WIIMOTE_BUTTON_ALL) / log(2.0f))+1;
|
||||
gamepad_config->setNumberOfButtons(num_buttons);
|
||||
gamepad_config->setNumberOfAxis(1);
|
||||
|
||||
setWiimoteBindings(gamepad_config);
|
||||
|
||||
// Initialize all Wiimotes, which in turn create their
|
||||
|
||||
// Initialize all Wiimotes, which in turn create their
|
||||
// associated GamePadDevices
|
||||
for(int i=0 ; i < nb_wiimotes ; i++)
|
||||
{
|
||||
m_wiimotes.push_back(new Wiimote(m_all_wiimote_handles[i], i,
|
||||
m_wiimotes.push_back(new Wiimote(m_all_wiimote_handles[i], i,
|
||||
gamepad_config ));
|
||||
} // end for
|
||||
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Set the LEDs and rumble for 0.2s
|
||||
int leds[] = {WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, WIIMOTE_LED_4};
|
||||
@ -109,7 +109,7 @@ void WiimoteManager::launchDetection(int timeout)
|
||||
wiiuse_set_leds(wiimote_handle, leds[i]);
|
||||
wiiuse_rumble(wiimote_handle, 1);
|
||||
}
|
||||
|
||||
|
||||
irr_driver->getDevice()->sleep(200);
|
||||
|
||||
for(unsigned int i=0 ; i < m_wiimotes.size(); i++)
|
||||
@ -117,7 +117,7 @@ void WiimoteManager::launchDetection(int timeout)
|
||||
wiimote_t* wiimote_handle = m_wiimotes[i]->getWiimoteHandle();
|
||||
wiiuse_rumble(wiimote_handle, 0);
|
||||
}
|
||||
|
||||
|
||||
// TODO: only enable accelerometer during race
|
||||
enableAccelerometer(true);
|
||||
|
||||
@ -169,19 +169,19 @@ void WiimoteManager::cleanup()
|
||||
if(m_wiimotes.size() > 0)
|
||||
{
|
||||
DeviceManager* device_manager = input_manager->getDeviceList();
|
||||
|
||||
GamePadDevice* first_gamepad_device =
|
||||
|
||||
GamePadDevice* first_gamepad_device =
|
||||
device_manager->getGamePadFromIrrID(WIIMOTE_START_IRR_ID);
|
||||
assert(first_gamepad_device);
|
||||
|
||||
DeviceConfig* gamepad_config =
|
||||
|
||||
DeviceConfig* gamepad_config =
|
||||
first_gamepad_device->getConfiguration();
|
||||
assert(gamepad_config);
|
||||
|
||||
// Remove the wiimote configuration -> automatically removes all
|
||||
|
||||
// Remove the wiimote configuration -> automatically removes all
|
||||
// linked gamepad devices;
|
||||
device_manager->deleteConfig(gamepad_config);
|
||||
|
||||
|
||||
// Shut the update thread
|
||||
#ifdef WIIMOTE_THREADING
|
||||
m_shut = true;
|
||||
@ -190,7 +190,7 @@ void WiimoteManager::cleanup()
|
||||
// Cleanup WiiUse
|
||||
wiiuse_cleanup(m_all_wiimote_handles, MAX_WIIMOTES);
|
||||
}
|
||||
|
||||
|
||||
for(unsigned int i=0; i<m_wiimotes.size(); i++)
|
||||
delete m_wiimotes[i];
|
||||
m_wiimotes.clear();
|
||||
@ -228,11 +228,11 @@ void WiimoteManager::enableAccelerometer(bool state)
|
||||
} // enableAccelerometer
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Thread update method - wiimotes state is updated in another thread to
|
||||
/** Thread update method - wiimotes state is updated in another thread to
|
||||
* avoid latency problems */
|
||||
void WiimoteManager::threadFunc()
|
||||
{
|
||||
#ifdef WIIMOTE_THREADING
|
||||
#ifdef WIIMOTE_THREADING
|
||||
while(!m_shut)
|
||||
#endif
|
||||
{
|
||||
@ -283,7 +283,7 @@ void WiimoteManager::threadFunc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
irr_driver->getDevice()->sleep(1); // 'cause come on, the whole CPU is not ours :)
|
||||
} // end while
|
||||
} // threadFunc
|
||||
@ -304,17 +304,17 @@ void* WiimoteManager::threadFuncWrapper(void *data)
|
||||
*/
|
||||
int WiimoteManager::askUserToConnectWiimotes()
|
||||
{
|
||||
new MessageDialog(
|
||||
new MessageDialog(
|
||||
_("Press the buttons 1+2 simultaneously on your wiimote to put "
|
||||
"it in discovery mode, then click on OK."),
|
||||
MessageDialog::MESSAGE_DIALOG_CONFIRM,
|
||||
MessageDialog::MESSAGE_DIALOG_CONFIRM,
|
||||
new WiimoteDialogListener(), true);
|
||||
|
||||
return getNumberOfWiimotes();
|
||||
} // askUserToConnectWiimotes
|
||||
|
||||
// ============================================================================
|
||||
/** Calles when the user clicks on OK, i.e. all wiimotes are in discovery
|
||||
/** Calles when the user clicks on OK, i.e. all wiimotes are in discovery
|
||||
* mode.
|
||||
*/
|
||||
void WiimoteManager::WiimoteDialogListener::onConfirm()
|
||||
|
@ -73,14 +73,14 @@
|
||||
bool macSetBundlePathIfRelevant(std::string& data_dir)
|
||||
{
|
||||
Log::debug("FileManager", "Checking whether we are using an app bundle... ");
|
||||
// the following code will enable STK to find its data when placed in an
|
||||
// the following code will enable STK to find its data when placed in an
|
||||
// app bundle on mac OS X.
|
||||
// returns true if path is set, returns false if path was not set
|
||||
char path[1024];
|
||||
CFBundleRef main_bundle = CFBundleGetMainBundle(); assert(main_bundle);
|
||||
CFURLRef main_bundle_URL = CFBundleCopyBundleURL(main_bundle);
|
||||
CFURLRef main_bundle_URL = CFBundleCopyBundleURL(main_bundle);
|
||||
assert(main_bundle_URL);
|
||||
CFStringRef cf_string_ref = CFURLCopyFileSystemPath(main_bundle_URL,
|
||||
CFStringRef cf_string_ref = CFURLCopyFileSystemPath(main_bundle_URL,
|
||||
kCFURLPOSIXPathStyle);
|
||||
assert(cf_string_ref);
|
||||
CFStringGetCString(cf_string_ref, path, 1024, kCFStringEncodingASCII);
|
||||
@ -118,7 +118,7 @@ FileManager::FileManager(char *argv[])
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// irrLicht's createDevice method has a nasty habit of messing the CWD.
|
||||
// since the code above may rely on it, save it to be able to restore
|
||||
// since the code above may rely on it, save it to be able to restore
|
||||
// it after.
|
||||
char buffer[256];
|
||||
getcwd(buffer, 256);
|
||||
@ -229,7 +229,7 @@ FileManager::~FileManager()
|
||||
std::set<std::string> allfiles;
|
||||
std::string tmp=getAddonsFile("tmp");
|
||||
listFiles(allfiles, tmp, /*fullpath*/true);
|
||||
for(std::set<std::string>::iterator i=allfiles.begin();
|
||||
for(std::set<std::string>::iterator i=allfiles.begin();
|
||||
i!=allfiles.end(); i++)
|
||||
{
|
||||
if((*i)=="." || (*i)=="..") continue;
|
||||
@ -238,7 +238,7 @@ FileManager::~FileManager()
|
||||
// other files.
|
||||
std::string full_path=tmp+"/"+*i;
|
||||
if(StringUtils::getExtension(*i)!="zip" &&
|
||||
StringUtils::getExtension(*i)!="part" )
|
||||
StringUtils::getExtension(*i)!="part" )
|
||||
{
|
||||
Log::warn("FileManager", "Unexpected tmp file '%s' found.",
|
||||
full_path.c_str());
|
||||
@ -328,7 +328,7 @@ void FileManager::pushModelSearchPath(const std::string& path)
|
||||
/*ignorePaths*/false,
|
||||
io::EFAT_FOLDER);
|
||||
// A later added file archive should be searched first (so that
|
||||
// track specific models are found before models in data/models).
|
||||
// track specific models are found before models in data/models).
|
||||
// This is not necessary if this is the first member, or if the
|
||||
// addFileArchive call did not add this file systems (this can
|
||||
// happen if the file archive has been added prevously, which
|
||||
@ -356,7 +356,7 @@ void FileManager::pushTextureSearchPath(const std::string& path)
|
||||
io::EFAT_FOLDER);
|
||||
// A later added file archive should be searched first (so that
|
||||
// e.g. track specific textures are found before textures in
|
||||
// data/textures).
|
||||
// data/textures).
|
||||
// This is not necessary if this is the first member, or if the
|
||||
// addFileArchive call did not add this file systems (this can
|
||||
// happen if the file archive has been added previously, which
|
||||
@ -402,7 +402,7 @@ bool FileManager::findFile(std::string& full_path,
|
||||
const std::string& file_name,
|
||||
const std::vector<std::string>& search_path) const
|
||||
{
|
||||
for(std::vector<std::string>::const_reverse_iterator
|
||||
for(std::vector<std::string>::const_reverse_iterator
|
||||
i = search_path.rbegin();
|
||||
i != search_path.rend(); ++i)
|
||||
{
|
||||
@ -414,7 +414,7 @@ bool FileManager::findFile(std::string& full_path,
|
||||
} // findFile
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the full path of a texture file name by searching for this
|
||||
/** Returns the full path of a texture file name by searching for this
|
||||
* file in all texture search paths.
|
||||
* \param file_name Name of the texture file to search.
|
||||
* \return The full path for the texture, or "" if the texture was not found.
|
||||
@ -427,7 +427,7 @@ std::string FileManager::getTextureFile(const std::string& file_name) const
|
||||
} // getTextureFile
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the full path of a model file name by searching for this
|
||||
/** Returns the full path of a model file name by searching for this
|
||||
* file in all model search paths.
|
||||
* \param file_name Name of the model file to search.
|
||||
* \return The full path for the model, or "" if the model was not found.
|
||||
@ -517,7 +517,7 @@ std::string FileManager::getGfxFile(const std::string& file_name) const
|
||||
* function does not support recursive operations, so if a directory "a/b"
|
||||
* is tested, and "a" does not exist, this function will fail.
|
||||
* \params path Directory to test.
|
||||
* \return True if the directory exists or could be created,
|
||||
* \return True if the directory exists or could be created,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool FileManager::checkAndCreateDirectory(const std::string &path)
|
||||
@ -528,7 +528,7 @@ bool FileManager::checkAndCreateDirectory(const std::string &path)
|
||||
return true;
|
||||
|
||||
Log::info("FileManager", "Creating directory '%s'.", path.c_str());
|
||||
|
||||
|
||||
// Otherwise try to create the directory:
|
||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||
bool error = _mkdir(path.c_str()) != 0;
|
||||
@ -539,7 +539,7 @@ bool FileManager::checkAndCreateDirectory(const std::string &path)
|
||||
} // checkAndCreateDirectory
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** If the directory specified in path does not exist, it is created
|
||||
/** If the directory specified in path does not exist, it is created
|
||||
* recursively (mkdir -p style).
|
||||
* \params path Directory to test.
|
||||
* \return True if the directory exists or could be created, false otherwise.
|
||||
@ -550,9 +550,9 @@ bool FileManager::checkAndCreateDirectoryP(const std::string &path)
|
||||
// (using access/_access internally):
|
||||
if(m_file_system->existFile(io::path(path.c_str())))
|
||||
return true;
|
||||
|
||||
|
||||
std::cout << "[FileManager] Creating directory(ies) '" << path << "'.\n";
|
||||
|
||||
|
||||
std::vector<std::string> split = StringUtils::split(path,'/');
|
||||
std::string current_path = "";
|
||||
for (unsigned int i=0; i<split.size(); i++)
|
||||
@ -576,13 +576,13 @@ bool FileManager::checkAndCreateDirectoryP(const std::string &path)
|
||||
} // checkAndCreateDirectory
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Checks if the config directory exists, and it not, tries to create it.
|
||||
/** Checks if the config directory exists, and it not, tries to create it.
|
||||
* It will set m_config_dir to the path to which user-specific config files
|
||||
* are stored.
|
||||
*/
|
||||
void FileManager::checkAndCreateConfigDir()
|
||||
{
|
||||
if(getenv("SUPERTUXKART_SAVEDIR") &&
|
||||
if(getenv("SUPERTUXKART_SAVEDIR") &&
|
||||
checkAndCreateDirectory(getenv("SUPERTUXKART_SAVEDIR")) )
|
||||
{
|
||||
m_config_dir = getenv("SUPERTUXKART_SAVEDIR");
|
||||
@ -617,9 +617,9 @@ void FileManager::checkAndCreateConfigDir()
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr <<
|
||||
std::cerr <<
|
||||
"[FileManager] No home directory, this should NOT happen!\n";
|
||||
// Fall back to system-wide app data (rather than
|
||||
// Fall back to system-wide app data (rather than
|
||||
// user-specific data), but should not happen anyway.
|
||||
m_config_dir = "";
|
||||
}
|
||||
@ -636,7 +636,7 @@ void FileManager::checkAndCreateConfigDir()
|
||||
}
|
||||
else if (!getenv("HOME"))
|
||||
{
|
||||
std::cerr
|
||||
std::cerr
|
||||
<< "[FileManager] No home directory, this should NOT happen "
|
||||
<< "- trying '.' for config files!\n";
|
||||
m_config_dir = ".";
|
||||
@ -648,8 +648,8 @@ void FileManager::checkAndCreateConfigDir()
|
||||
if(!checkAndCreateDirectory(m_config_dir))
|
||||
{
|
||||
// If $HOME/.config can not be created:
|
||||
std::cerr << "[FileManager] Cannot create directory '"
|
||||
<< m_config_dir <<"', falling back to use '"
|
||||
std::cerr << "[FileManager] Cannot create directory '"
|
||||
<< m_config_dir <<"', falling back to use '"
|
||||
<< getenv("HOME")<< "'.\n";
|
||||
m_config_dir = getenv("HOME");
|
||||
}
|
||||
@ -673,7 +673,7 @@ void FileManager::checkAndCreateConfigDir()
|
||||
} // checkAndCreateConfigDir
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Creates the directories for the addons data. This will set m_addons_dir
|
||||
/** Creates the directories for the addons data. This will set m_addons_dir
|
||||
* with the appropriate path, and also create the subdirectories in this
|
||||
* directory.
|
||||
*/
|
||||
@ -685,9 +685,9 @@ void FileManager::checkAndCreateAddonsDir()
|
||||
m_addons_dir = getenv("HOME");
|
||||
m_addons_dir += "/Library/Application Support/SuperTuxKart/Addons/";
|
||||
#else
|
||||
m_addons_dir = checkAndCreateLinuxDir("XDG_DATA_HOME", "supertuxkart",
|
||||
m_addons_dir = checkAndCreateLinuxDir("XDG_DATA_HOME", "supertuxkart",
|
||||
".local/share", ".stkaddons");
|
||||
m_addons_dir += "addons/";
|
||||
m_addons_dir += "addons/";
|
||||
#endif
|
||||
|
||||
if(!checkAndCreateDirectory(m_addons_dir))
|
||||
@ -711,7 +711,7 @@ void FileManager::checkAndCreateAddonsDir()
|
||||
} // checkAndCreateAddonsDir
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Creates the directories for screenshots. This will set m_screenshot_dir
|
||||
/** Creates the directories for screenshots. This will set m_screenshot_dir
|
||||
* with the appropriate path.
|
||||
*/
|
||||
void FileManager::checkAndCreateScreenshotDir()
|
||||
@ -739,7 +739,7 @@ void FileManager::checkAndCreateScreenshotDir()
|
||||
#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__APPLE__)
|
||||
|
||||
/** Find a directory to use for remaining unix variants. Use the new standards
|
||||
* for config directory based on XDG_* environment variables, or a
|
||||
* for config directory based on XDG_* environment variables, or a
|
||||
* subdirectory under $HOME, trying two different fallbacks. It will also
|
||||
* check if the directory 'dirname' can be created (to avoid problems that
|
||||
* e.g. $env_name is '/', which exists, but can not be written to.
|
||||
@ -766,12 +766,12 @@ std::string FileManager::checkAndCreateLinuxDir(const char *env_name,
|
||||
Log::warn("FileManager", "Cannot create $%s.", env_name);
|
||||
|
||||
if(dir[dir.size()-1]!='/') dir += "/";
|
||||
// Do an additional test here, e.g. in case that XDG_DATA_HOME is '/'
|
||||
// Do an additional test here, e.g. in case that XDG_DATA_HOME is '/'
|
||||
// and since dir_ok is set, it would not test any of the other options
|
||||
// like $HOME/.local/share
|
||||
dir_ok = checkAndCreateDirectory(dir+dir_name);
|
||||
if(!dir_ok)
|
||||
Log::warn("FileManager", "Cannot create $%s/%s.", dir.c_str(),
|
||||
Log::warn("FileManager", "Cannot create $%s/%s.", dir.c_str(),
|
||||
dir_name);
|
||||
}
|
||||
|
||||
@ -781,11 +781,11 @@ std::string FileManager::checkAndCreateLinuxDir(const char *env_name,
|
||||
dir = getenv("HOME");
|
||||
if(dir.size()>0 && dir[dir.size()-1]!='/') dir += "/";
|
||||
dir += fallback1;
|
||||
// This will create each individual subdirectory if
|
||||
// This will create each individual subdirectory if
|
||||
// dir_name contains "/".
|
||||
dir_ok = checkAndCreateDirectoryP(dir);
|
||||
if(!dir_ok)
|
||||
Log::warn("FileManager", "Cannot create $HOME/%s.",
|
||||
Log::warn("FileManager", "Cannot create $HOME/%s.",
|
||||
fallback1);
|
||||
}
|
||||
if(!dir_ok && fallback2 && getenv("HOME"))
|
||||
@ -795,7 +795,7 @@ std::string FileManager::checkAndCreateLinuxDir(const char *env_name,
|
||||
dir += fallback2;
|
||||
dir_ok = checkAndCreateDirectory(dir);
|
||||
if(!dir_ok)
|
||||
Log::warn("FileManager", "Cannot create $HOME/%s.",
|
||||
Log::warn("FileManager", "Cannot create $HOME/%s.",
|
||||
fallback2);
|
||||
}
|
||||
|
||||
@ -926,7 +926,7 @@ std::string FileManager::getChallengeFile(const std::string &file_name) const
|
||||
} // getChallengeFile
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the full path of the tutorial file.
|
||||
/** Returns the full path of the tutorial file.
|
||||
* \param file_name Name of the tutorial file to return.
|
||||
*/
|
||||
std::string FileManager::getTutorialFile(const std::string &file_name) const
|
||||
@ -959,8 +959,8 @@ bool FileManager::isDirectory(const std::string &path) const
|
||||
* otherwise m_root_dir is used.
|
||||
* \param make_full_path If set to true, all listed files will be full paths.
|
||||
*/
|
||||
void FileManager::listFiles(std::set<std::string>& result,
|
||||
const std::string& dir, bool is_full_path,
|
||||
void FileManager::listFiles(std::set<std::string>& result,
|
||||
const std::string& dir, bool is_full_path,
|
||||
bool make_full_path) const
|
||||
{
|
||||
result.clear();
|
||||
@ -1036,7 +1036,7 @@ bool FileManager::removeDirectory(const std::string &name) const
|
||||
{
|
||||
if((*i)=="." || (*i)=="..") continue;
|
||||
if(UserConfigParams::logMisc())
|
||||
Log::verbose("FileManager", "Deleting directory '%s'.",
|
||||
Log::verbose("FileManager", "Deleting directory '%s'.",
|
||||
(*i).c_str());
|
||||
std::string full_path=name+"/"+*i;
|
||||
if(isDirectory(full_path))
|
||||
|
@ -27,7 +27,7 @@
|
||||
XMLNode::XMLNode(io::IXMLReader *xml)
|
||||
{
|
||||
m_file_name = "[unknown]";
|
||||
|
||||
|
||||
while(xml->getNodeType()!=io::EXN_ELEMENT && xml->read());
|
||||
readXML(xml);
|
||||
} // XMLNode
|
||||
@ -39,24 +39,24 @@ XMLNode::XMLNode(io::IXMLReader *xml)
|
||||
XMLNode::XMLNode(const std::string &filename)
|
||||
{
|
||||
m_file_name = filename;
|
||||
|
||||
|
||||
io::IXMLReader *xml = file_manager->createXMLReader(filename);
|
||||
|
||||
|
||||
if (xml == NULL)
|
||||
{
|
||||
throw std::runtime_error("Cannot find file "+filename);
|
||||
}
|
||||
|
||||
|
||||
bool is_first_element = true;
|
||||
while(xml->read())
|
||||
{
|
||||
switch (xml->getNodeType())
|
||||
switch (xml->getNodeType())
|
||||
{
|
||||
case io::EXN_ELEMENT:
|
||||
{
|
||||
if(!is_first_element)
|
||||
{
|
||||
fprintf(stderr,
|
||||
fprintf(stderr,
|
||||
"More than one root element in '%s' - ignored.\n",
|
||||
filename.c_str());
|
||||
}
|
||||
@ -101,13 +101,13 @@ void XMLNode::readXML(io::IXMLReader *xml)
|
||||
} // for i
|
||||
|
||||
// If no children, we are done
|
||||
if(xml->isEmptyElement())
|
||||
if(xml->isEmptyElement())
|
||||
return;
|
||||
|
||||
/** Read all children elements. */
|
||||
while(xml->read())
|
||||
{
|
||||
switch (xml->getNodeType())
|
||||
switch (xml->getNodeType())
|
||||
{
|
||||
case io::EXN_ELEMENT:
|
||||
{
|
||||
@ -227,9 +227,9 @@ int XMLNode::get(const std::string &attribute, Vec3 *value) const
|
||||
s.c_str(), m_file_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
float x, y, z;
|
||||
|
||||
|
||||
if (StringUtils::parseString<float>(v[0], &x) &&
|
||||
StringUtils::parseString<float>(v[1], &y) &&
|
||||
StringUtils::parseString<float>(v[2], &z) )
|
||||
@ -244,7 +244,7 @@ int XMLNode::get(const std::string &attribute, Vec3 *value) const
|
||||
s.c_str(), m_file_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
} // get(Vec3)
|
||||
|
||||
@ -298,7 +298,7 @@ int XMLNode::get(const std::string &attribute, int32_t *value) const
|
||||
s.c_str(), attribute.c_str(), m_name.c_str(), m_file_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
} // get(int32_t)
|
||||
|
||||
@ -314,7 +314,7 @@ int XMLNode::get(const std::string &attribute, int64_t *value) const
|
||||
s.c_str(), attribute.c_str(), m_name.c_str(), m_file_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
} // get(int64_t)
|
||||
|
||||
@ -324,14 +324,14 @@ int XMLNode::get(const std::string &attribute, uint32_t *value) const
|
||||
{
|
||||
std::string s;
|
||||
if(!get(attribute, &s)) return 0;
|
||||
|
||||
|
||||
if (!StringUtils::parseString<unsigned int>(s, value))
|
||||
{
|
||||
fprintf(stderr, "[XMLNode] WARNING: Expected uint but found '%s' for attribute '%s' of node '%s' in file %s\n",
|
||||
s.c_str(), attribute.c_str(), m_name.c_str(), m_file_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
} // get(uint32_t)
|
||||
|
||||
@ -340,14 +340,14 @@ int XMLNode::get(const std::string &attribute, float *value) const
|
||||
{
|
||||
std::string s;
|
||||
if(!get(attribute, &s)) return 0;
|
||||
|
||||
|
||||
if (!StringUtils::parseString<float>(s, value))
|
||||
{
|
||||
fprintf(stderr, "[XMLNode] WARNING: Expected float but found '%s' for attribute '%s' of node '%s' in file %s\n",
|
||||
s.c_str(), attribute.c_str(), m_name.c_str(), m_file_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
} // get(int)
|
||||
|
||||
@ -355,7 +355,7 @@ int XMLNode::get(const std::string &attribute, float *value) const
|
||||
int XMLNode::get(const std::string &attribute, bool *value) const
|
||||
{
|
||||
std::string s;
|
||||
|
||||
|
||||
// FIXME: for some reason, missing attributes don't trigger that if???
|
||||
if(!get(attribute, &s)) return 0;
|
||||
*value = s[0]=='T' || s[0]=='t' || s[0]=='Y' || s[0]=='y' ||
|
||||
@ -370,7 +370,7 @@ int XMLNode::get(const std::string &attribute, bool *value) const
|
||||
* \param attribute Name of the attribute.
|
||||
* \param value Value of the attribute.
|
||||
*/
|
||||
int XMLNode::get(const std::string &attribute,
|
||||
int XMLNode::get(const std::string &attribute,
|
||||
std::vector<std::string> *value) const
|
||||
{
|
||||
std::string s;
|
||||
@ -387,7 +387,7 @@ int XMLNode::get(const std::string &attribute,
|
||||
* \param attribute Name of the attribute.
|
||||
* \param value Value of the attribute.
|
||||
*/
|
||||
int XMLNode::get(const std::string &attribute,
|
||||
int XMLNode::get(const std::string &attribute,
|
||||
std::vector<float> *value) const
|
||||
{
|
||||
std::string s;
|
||||
@ -395,7 +395,7 @@ int XMLNode::get(const std::string &attribute,
|
||||
|
||||
std::vector<std::string> v = StringUtils::split(s,' ');
|
||||
value->clear();
|
||||
|
||||
|
||||
const unsigned int count = v.size();
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
{
|
||||
@ -406,7 +406,7 @@ int XMLNode::get(const std::string &attribute,
|
||||
v[i].c_str(), attribute.c_str(), m_name.c_str(), m_file_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
value->push_back(curr);
|
||||
}
|
||||
return value->size();
|
||||
@ -426,7 +426,7 @@ int XMLNode::get(const std::string &attribute, std::vector<int> *value) const
|
||||
|
||||
std::vector<std::string> v = StringUtils::split(s,' ');
|
||||
value->clear();
|
||||
|
||||
|
||||
const unsigned int count = v.size();
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
{
|
||||
@ -437,7 +437,7 @@ int XMLNode::get(const std::string &attribute, std::vector<int> *value) const
|
||||
v[i].c_str(), attribute.c_str(), m_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
value->push_back(val);
|
||||
}
|
||||
return value->size();
|
||||
@ -471,7 +471,7 @@ int XMLNode::get(const std::string &attribute, InterpolationArray *value) const
|
||||
float x;
|
||||
if(!StringUtils::fromString(pair[0], x))
|
||||
{
|
||||
printf("Incorrect x in pair '%s' of '%s'.\n",
|
||||
printf("Incorrect x in pair '%s' of '%s'.\n",
|
||||
pairs[i].c_str(), attribute.c_str());
|
||||
exit(-1);
|
||||
}
|
||||
@ -494,7 +494,7 @@ int XMLNode::get(const std::string &attribute, InterpolationArray *value) const
|
||||
/** Interprets the attributes 'x', 'y', 'z' or 'h', 'p', 'r' as a 3d vector
|
||||
* and set the corresponding elements of value. Not all values need to be
|
||||
* defined as attributes (and the correspnding elements of the vector will
|
||||
* not be changed). It returns a bit field for each defined value, i.e. if x
|
||||
* not be changed). It returns a bit field for each defined value, i.e. if x
|
||||
* and y are defined, 3 is returned.
|
||||
* \param value Vector to return the values in.
|
||||
*/
|
||||
@ -513,10 +513,10 @@ int XMLNode::get(core::vector3df *value) const
|
||||
} // core::vector3df
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Interprets the attributes 'x', 'y', 'z' as a 3d vector and set the
|
||||
* corresponding elements of value. Not all values need to be defined as
|
||||
* attributes (and the correspnding elements of the vector will not be
|
||||
* changed). It returns a bit field for each defined value, i.e. if x
|
||||
/** Interprets the attributes 'x', 'y', 'z' as a 3d vector and set the
|
||||
* corresponding elements of value. Not all values need to be defined as
|
||||
* attributes (and the correspnding elements of the vector will not be
|
||||
* changed). It returns a bit field for each defined value, i.e. if x
|
||||
* and y are defined, 3 is returned.
|
||||
* \param value Vector to return the values in.
|
||||
*/
|
||||
@ -532,10 +532,10 @@ int XMLNode::getXYZ(core::vector3df *value) const
|
||||
} // getXYZ vector3df
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Interprets the attributes 'x', 'y', 'z' as a 3d vector and set the
|
||||
* corresponding elements of value. Not all values need to be defined as
|
||||
* attributes (and the correspnding elements of the vector will not be
|
||||
* changed). It returns a bit field for each defined value, i.e. if x
|
||||
/** Interprets the attributes 'x', 'y', 'z' as a 3d vector and set the
|
||||
* corresponding elements of value. Not all values need to be defined as
|
||||
* attributes (and the correspnding elements of the vector will not be
|
||||
* changed). It returns a bit field for each defined value, i.e. if x
|
||||
* and y are defined, 3 is returned.
|
||||
* \param value Vector to return the values in.
|
||||
*/
|
||||
@ -551,10 +551,10 @@ int XMLNode::getXYZ(Vec3 *value) const
|
||||
} // getXYZ Vec3
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Interprets the attributes 'h', 'p', 'r' as a 3d vector and set the
|
||||
* corresponding elements of value. Not all values need to be defined as
|
||||
* attributes (and the correspnding elements of the vector will not be
|
||||
* changed). It returns a bit field for each defined value, i.e. if x and y
|
||||
/** Interprets the attributes 'h', 'p', 'r' as a 3d vector and set the
|
||||
* corresponding elements of value. Not all values need to be defined as
|
||||
* attributes (and the correspnding elements of the vector will not be
|
||||
* changed). It returns a bit field for each defined value, i.e. if x and y
|
||||
* are defined, 3 is returned.
|
||||
* \param value Vector to return the values in.
|
||||
*/
|
||||
@ -570,10 +570,10 @@ int XMLNode::getHPR(core::vector3df *value) const
|
||||
} // getHPR vector3df
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Interprets the attributes 'h', 'p', 'r' as a 3d vector and set the
|
||||
* corresponding elements of value. Not all values need to be defined as
|
||||
* attributes (and the correspnding elements of the vector will not be
|
||||
* changed). It returns a bit field for each defined value, i.e. if x and y
|
||||
/** Interprets the attributes 'h', 'p', 'r' as a 3d vector and set the
|
||||
* corresponding elements of value. Not all values need to be defined as
|
||||
* attributes (and the correspnding elements of the vector will not be
|
||||
* changed). It returns a bit field for each defined value, i.e. if x and y
|
||||
* are defined, 3 is returned.
|
||||
* \param value Vector to return the values in.
|
||||
*/
|
||||
|
@ -32,10 +32,10 @@ XMLWriter::XMLWriter(const char* dest) : m_base(dest, std::ios::out | std::ios::
|
||||
{
|
||||
throw std::runtime_error("Failed to open file for writing : " + std::string(dest));
|
||||
}
|
||||
|
||||
|
||||
// FIXME: make sure to properly handle endianness
|
||||
wchar_t BOM = 0xFEFF; // UTF-16 BOM is 0xFEFF; UTF-32 BOM is 0x0000FEFF. So this works in either case
|
||||
|
||||
|
||||
m_base.write((char *) &BOM, sizeof(wchar_t));
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ Attachment::~Attachment()
|
||||
{
|
||||
if(m_node)
|
||||
irr_driver->removeNode(m_node);
|
||||
|
||||
|
||||
if (m_bomb_sound)
|
||||
{
|
||||
sfx_manager->deleteSFX(m_bomb_sound);
|
||||
@ -77,7 +77,7 @@ Attachment::~Attachment()
|
||||
} // ~Attachment
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the attachment a kart has. This will also handle animation to be
|
||||
/** Sets the attachment a kart has. This will also handle animation to be
|
||||
* played, e.g. when a swatter replaces a bomb.
|
||||
* \param type The type of the new attachment.
|
||||
* \param time How long this attachment should stay with the kart.
|
||||
@ -86,17 +86,17 @@ Attachment::~Attachment()
|
||||
* can be passed back to the previous owner). NULL if a no
|
||||
* previous owner exists.
|
||||
*/
|
||||
void Attachment::set(AttachmentType type, float time,
|
||||
void Attachment::set(AttachmentType type, float time,
|
||||
AbstractKart *current_kart)
|
||||
{
|
||||
bool was_bomb = (m_type == ATTACH_BOMB);
|
||||
scene::ISceneNode* bomb_scene_node = NULL;
|
||||
if (was_bomb && type == ATTACH_SWATTER)
|
||||
{
|
||||
// let's keep the bomb node, and create a new one for
|
||||
// let's keep the bomb node, and create a new one for
|
||||
// the new attachment
|
||||
bomb_scene_node = m_node;
|
||||
|
||||
|
||||
m_node = irr_driver->addAnimatedMesh(
|
||||
attachment_manager->getMesh(Attachment::ATTACH_BOMB));
|
||||
#ifdef DEBUG
|
||||
@ -107,10 +107,10 @@ void Attachment::set(AttachmentType type, float time,
|
||||
m_node->setParent(m_kart->getNode());
|
||||
m_node->setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
clear();
|
||||
|
||||
// If necessary create the appropriate plugin which encapsulates
|
||||
|
||||
// If necessary create the appropriate plugin which encapsulates
|
||||
// the associated behavior
|
||||
switch(type)
|
||||
{
|
||||
@ -139,12 +139,12 @@ void Attachment::set(AttachmentType type, float time,
|
||||
m_node->setAnimationSpeed(0);
|
||||
m_node->setCurrentFrame(0);
|
||||
}
|
||||
|
||||
|
||||
m_type = type;
|
||||
m_time_left = time;
|
||||
m_previous_owner = current_kart;
|
||||
m_node->setRotation(core::vector3df(0, 0, 0));
|
||||
|
||||
|
||||
// A parachute can be attached as result of the usage of an item. In this
|
||||
// case we have to save the current kart speed so that it can be detached
|
||||
// by slowing down.
|
||||
@ -152,8 +152,8 @@ void Attachment::set(AttachmentType type, float time,
|
||||
{
|
||||
m_initial_speed = m_kart->getSpeed();
|
||||
// if going very slowly or backwards, braking won't remove parachute
|
||||
if(m_initial_speed <= 1.5) m_initial_speed = 1.5;
|
||||
|
||||
if(m_initial_speed <= 1.5) m_initial_speed = 1.5;
|
||||
|
||||
if (UserConfigParams::m_graphical_effects)
|
||||
{
|
||||
// .blend was created @25 (<10 real, slow computer), make it faster
|
||||
@ -182,15 +182,15 @@ void Attachment::clear()
|
||||
sfx_manager->deleteSFX(m_bomb_sound);
|
||||
m_bomb_sound = NULL;
|
||||
}
|
||||
|
||||
m_type=ATTACH_NOTHING;
|
||||
|
||||
|
||||
m_type=ATTACH_NOTHING;
|
||||
|
||||
m_time_left=0.0;
|
||||
m_node->setVisible(false);
|
||||
m_node->setPosition(core::vector3df());
|
||||
m_node->setRotation(core::vector3df());
|
||||
|
||||
// Resets the weight of the kart if the previous attachment affected it
|
||||
// Resets the weight of the kart if the previous attachment affected it
|
||||
// (e.g. anvil). This must be done *after* setting m_type to
|
||||
// ATTACH_NOTHING in order to reset the physics parameters.
|
||||
m_kart->updateWeight();
|
||||
@ -206,16 +206,16 @@ void Attachment::clear()
|
||||
void Attachment::hitBanana(Item *item, int new_attachment)
|
||||
{
|
||||
float leftover_time = 0.0f;
|
||||
|
||||
|
||||
bool add_a_new_item = true;
|
||||
|
||||
|
||||
if (dynamic_cast<ThreeStrikesBattle*>(World::getWorld()) != NULL)
|
||||
{
|
||||
World::getWorld()->kartHit(m_kart->getWorldKartId());
|
||||
ExplosionAnimation::create(m_kart);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch(getType()) // If there already is an attachment, make it worse :)
|
||||
{
|
||||
case ATTACH_BOMB:
|
||||
@ -227,20 +227,20 @@ void Attachment::hitBanana(Item *item, int new_attachment)
|
||||
projectile_manager->addHitEffect(he);
|
||||
ExplosionAnimation::create(m_kart);
|
||||
clear();
|
||||
if(new_attachment==-1)
|
||||
if(new_attachment==-1)
|
||||
new_attachment = m_random.get(3);
|
||||
// Disable the banana on which the kart just is for more than the
|
||||
// default time. This is necessary to avoid that a kart lands on the
|
||||
// same banana again once the explosion animation is finished, giving
|
||||
// Disable the banana on which the kart just is for more than the
|
||||
// default time. This is necessary to avoid that a kart lands on the
|
||||
// same banana again once the explosion animation is finished, giving
|
||||
// the kart the same penalty twice.
|
||||
float f = std::max(item->getDisableTime(),
|
||||
float f = std::max(item->getDisableTime(),
|
||||
m_kart->getKartProperties()->getExplosionTime()+2.0f);
|
||||
item->setDisableTime(f);
|
||||
break;
|
||||
}
|
||||
case ATTACH_ANVIL:
|
||||
// if the kart already has an anvil, attach a new anvil,
|
||||
// and increase the overall time
|
||||
// if the kart already has an anvil, attach a new anvil,
|
||||
// and increase the overall time
|
||||
new_attachment = 2;
|
||||
leftover_time = m_time_left;
|
||||
break;
|
||||
@ -256,7 +256,7 @@ void Attachment::hitBanana(Item *item, int new_attachment)
|
||||
if(new_attachment==-1)
|
||||
new_attachment = m_random.get(3);
|
||||
} // switch
|
||||
|
||||
|
||||
// Save the information about the attachment in the race state
|
||||
// so that the clients can be updated.
|
||||
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||
@ -270,17 +270,17 @@ void Attachment::hitBanana(Item *item, int new_attachment)
|
||||
{
|
||||
switch (new_attachment)
|
||||
{
|
||||
case 0:
|
||||
case 0:
|
||||
set( ATTACH_PARACHUTE,stk_config->m_parachute_time+leftover_time);
|
||||
m_initial_speed = m_kart->getSpeed();
|
||||
|
||||
// if going very slowly or backwards,
|
||||
// if going very slowly or backwards,
|
||||
// braking won't remove parachute
|
||||
if(m_initial_speed <= 1.5) m_initial_speed = 1.5;
|
||||
break ;
|
||||
case 1:
|
||||
set( ATTACH_BOMB, stk_config->m_bomb_time+leftover_time);
|
||||
|
||||
|
||||
// if ( m_kart == m_kart[0] )
|
||||
// sound -> playSfx ( SOUND_SHOOMF ) ;
|
||||
break ;
|
||||
@ -367,7 +367,7 @@ void Attachment::update(float dt)
|
||||
// Partly handled in Kart::updatePhysics
|
||||
// Otherwise: disable if a certain percantage of
|
||||
// initial speed was lost
|
||||
if(m_kart->getSpeed() <=
|
||||
if(m_kart->getSpeed() <=
|
||||
m_initial_speed*stk_config->m_parachute_done_fraction)
|
||||
{
|
||||
m_time_left = -1;
|
||||
@ -382,7 +382,7 @@ void Attachment::update(float dt)
|
||||
// Everything is done in the plugin.
|
||||
break;
|
||||
case ATTACH_BOMB:
|
||||
|
||||
|
||||
if (m_bomb_sound) m_bomb_sound->position(m_kart->getXYZ());
|
||||
|
||||
// Mesh animation frames are 1 to 61 frames (60 steps)
|
||||
@ -390,7 +390,7 @@ void Attachment::update(float dt)
|
||||
// If longer times needed, it should be a surprise "oh! bomb activated!"
|
||||
if(m_time_left <= (m_node->getEndFrame() - m_node->getStartFrame()-1))
|
||||
{
|
||||
m_node->setCurrentFrame(m_node->getEndFrame()
|
||||
m_node->setCurrentFrame(m_node->getEndFrame()
|
||||
- m_node->getStartFrame()-1-m_time_left);
|
||||
}
|
||||
if(m_time_left<=0.0)
|
||||
@ -400,7 +400,7 @@ void Attachment::update(float dt)
|
||||
he->setPlayerKartHit();
|
||||
projectile_manager->addHitEffect(he);
|
||||
ExplosionAnimation::create(m_kart);
|
||||
|
||||
|
||||
if (m_bomb_sound)
|
||||
{
|
||||
m_bomb_sound->stop();
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
AttachmentManager *attachment_manager = 0;
|
||||
|
||||
struct initAttachmentType {Attachment::AttachmentType attachment;
|
||||
struct initAttachmentType {Attachment::AttachmentType attachment;
|
||||
const char *file;
|
||||
const char *icon_file;};
|
||||
|
||||
@ -34,14 +34,14 @@ struct initAttachmentType {Attachment::AttachmentType attachment;
|
||||
friction only becomes important at higher speeds.
|
||||
Anvil: It increases the weight of the kart.But this will NOT have any
|
||||
effect on karts already driving at highest speed: the accelerating
|
||||
force is independent of the mass, so it is 0 at highest speed
|
||||
force is independent of the mass, so it is 0 at highest speed
|
||||
(engine force = air- plus system-force) and only this value gets
|
||||
divided by the mass later --> at highest speed there would be no
|
||||
effect when the mass is changed, only at lower speeds the acting
|
||||
divided by the mass later --> at highest speed there would be no
|
||||
effect when the mass is changed, only at lower speeds the acting
|
||||
acceleration will be lower.Reducing the power slows the kart down,
|
||||
but doesn't give the feeling of a sudden weight increase.
|
||||
but doesn't give the feeling of a sudden weight increase.
|
||||
Therefore the anvil will reduce by a certain factor (see physics
|
||||
parameters) once when it is attached. Together with the mass
|
||||
parameters) once when it is attached. Together with the mass
|
||||
increase (lower acceleration) it's sufficient negative.
|
||||
*/
|
||||
|
||||
@ -97,7 +97,7 @@ void AttachmentManager::loadModels()
|
||||
m_all_icons[iat[i].attachment] =
|
||||
material_manager->getMaterial(full_icon_path,
|
||||
/* full_path */ true,
|
||||
/*make_permanent */ true);
|
||||
/*make_permanent */ true);
|
||||
}
|
||||
|
||||
} // for
|
||||
|
@ -29,14 +29,14 @@ float Bowling::m_st_max_distance_squared;
|
||||
float Bowling::m_st_force_to_target;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
Bowling::Bowling(AbstractKart *kart)
|
||||
Bowling::Bowling(AbstractKart *kart)
|
||||
: Flyable(kart, PowerupManager::POWERUP_BOWLING, 50.0f /* mass */)
|
||||
{
|
||||
m_has_hit_kart = false;
|
||||
float y_offset = 0.5f*kart->getKartLength() + m_extend.getZ()*0.5f;
|
||||
|
||||
|
||||
// if the kart is looking backwards, release from the back
|
||||
if( kart->getControls().m_look_back )
|
||||
if( kart->getControls().m_look_back )
|
||||
{
|
||||
y_offset = -y_offset;
|
||||
m_speed = -m_speed*2;
|
||||
@ -52,9 +52,9 @@ Bowling::Bowling(AbstractKart *kart)
|
||||
}
|
||||
|
||||
createPhysics(y_offset, btVector3(0.0f, 0.0f, m_speed*2),
|
||||
new btSphereShape(0.5f*m_extend.getY()),
|
||||
new btSphereShape(0.5f*m_extend.getY()),
|
||||
1.0f /*restitution*/,
|
||||
-70.0f /*gravity*/,
|
||||
-70.0f /*gravity*/,
|
||||
true /*rotates*/);
|
||||
// Even if the ball is fired backwards, m_speed must be positive,
|
||||
// otherwise the ball can start to vibrate when energy is added.
|
||||
@ -63,15 +63,15 @@ Bowling::Bowling(AbstractKart *kart)
|
||||
// this would disable gravity.
|
||||
setAdjustUpVelocity(false);
|
||||
|
||||
// unset no_contact_response flags, so that the ball
|
||||
// unset no_contact_response flags, so that the ball
|
||||
// will bounce off the track
|
||||
int flag = getBody()->getCollisionFlags();
|
||||
flag = flag & (~ btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
||||
getBody()->setCollisionFlags(flag);
|
||||
|
||||
|
||||
// should not live forever, auto-destruct after 20 seconds
|
||||
m_max_lifespan = 20;
|
||||
|
||||
|
||||
} // Bowling
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -85,15 +85,15 @@ void Bowling::init(const XMLNode &node, scene::IMesh *bowling)
|
||||
m_st_max_distance = 20.0f;
|
||||
m_st_max_distance_squared = 20.0f * 20.0f;
|
||||
m_st_force_to_target = 10.0f;
|
||||
|
||||
|
||||
node.get("max-distance", &m_st_max_distance );
|
||||
m_st_max_distance_squared = m_st_max_distance*m_st_max_distance;
|
||||
|
||||
|
||||
node.get("force-to-target", &m_st_force_to_target);
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Picks a random message to be displayed when a kart is hit by a bowling
|
||||
/** Picks a random message to be displayed when a kart is hit by a bowling
|
||||
* ball. This function picks a different message if a kart hit itself.
|
||||
* \param kart The kart that was hit.
|
||||
* \returns The string to display.
|
||||
@ -163,7 +163,7 @@ bool Bowling::updateAndDelete(float dt)
|
||||
m_body->applyCentralForce(direction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Bowling balls lose energy (e.g. when hitting the track), so increase
|
||||
// the speed if the ball is too slow, but only if it's not too high (if
|
||||
// the ball is too high, it is 'pushed down', which can reduce the
|
||||
@ -191,8 +191,8 @@ bool Bowling::updateAndDelete(float dt)
|
||||
}
|
||||
// m_body->setLinearVelocity(v*(m_speed/sqrt(vlen)));
|
||||
} // vlen < 0.8*m_speed*m_speed
|
||||
} // hat< m_max_height
|
||||
|
||||
} // hat< m_max_height
|
||||
|
||||
if(vlen<0.1)
|
||||
{
|
||||
hit(NULL);
|
||||
@ -201,11 +201,11 @@ bool Bowling::updateAndDelete(float dt)
|
||||
return false;
|
||||
} // updateAndDelete
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Callback from the physics in case that a kart or physical object is hit.
|
||||
/** Callback from the physics in case that a kart or physical object is hit.
|
||||
* The bowling ball triggers an explosion when hit.
|
||||
* \param kart The kart hit (NULL if no kart was hit).
|
||||
* \param object The object that was hit (NULL if none).
|
||||
* \returns True if there was actually a hit (i.e. not owner, and target is
|
||||
* \returns True if there was actually a hit (i.e. not owner, and target is
|
||||
* not immune), false otherwise.
|
||||
*/
|
||||
bool Bowling::hit(AbstractKart* kart, PhysicalObject* obj)
|
||||
|
@ -47,7 +47,7 @@ Cake::Cake (AbstractKart *kart) : Flyable(kart, PowerupManager::POWERUP_CAKE)
|
||||
m_speed *= kart->getSpeed() / 23.0f;
|
||||
|
||||
//when going backwards, decrease speed of cake by less
|
||||
if (kart->getSpeed() < 0) m_speed /= 3.6f;
|
||||
if (kart->getSpeed() < 0) m_speed /= 3.6f;
|
||||
|
||||
m_speed += 16.0f;
|
||||
|
||||
@ -63,7 +63,7 @@ Cake::Cake (AbstractKart *kart) : Flyable(kart, PowerupManager::POWERUP_CAKE)
|
||||
const AbstractKart *closest_kart=NULL;
|
||||
Vec3 direction;
|
||||
float kart_dist_squared;
|
||||
getClosestKart(&closest_kart, &kart_dist_squared, &direction,
|
||||
getClosestKart(&closest_kart, &kart_dist_squared, &direction,
|
||||
kart /* search in front of this kart */, backwards);
|
||||
|
||||
// aim at this kart if 1) it's not too far, 2) if the aimed kart's speed
|
||||
@ -84,11 +84,11 @@ Cake::Cake (AbstractKart *kart) : Flyable(kart, PowerupManager::POWERUP_CAKE)
|
||||
|
||||
// apply transformation to the bullet object (without pitch)
|
||||
trans.setRotation(btQuaternion(btVector3(0,1,0), fire_angle));
|
||||
|
||||
|
||||
m_initial_velocity = Vec3(0.0f, up_velocity, m_speed);
|
||||
|
||||
createPhysics(forward_offset, m_initial_velocity,
|
||||
new btCylinderShape(0.5f*m_extend),
|
||||
new btCylinderShape(0.5f*m_extend),
|
||||
0.5f /* restitution */, -m_gravity,
|
||||
true /* rotation */, false /* backwards */, &trans);
|
||||
}
|
||||
@ -98,11 +98,11 @@ Cake::Cake (AbstractKart *kart) : Flyable(kart, PowerupManager::POWERUP_CAKE)
|
||||
// kart is too far to be hit. so throw the projectile in a generic way,
|
||||
// straight ahead, without trying to hit anything in particular
|
||||
trans = kart->getAlignedTransform(pitch);
|
||||
|
||||
|
||||
m_initial_velocity = Vec3(0.0f, up_velocity, m_speed);
|
||||
|
||||
createPhysics(forward_offset, m_initial_velocity,
|
||||
new btCylinderShape(0.5f*m_extend),
|
||||
new btCylinderShape(0.5f*m_extend),
|
||||
0.5f /* restitution */, -m_gravity,
|
||||
true /* rotation */, backwards, &trans);
|
||||
}
|
||||
@ -157,11 +157,11 @@ const core::stringw Cake::getHitString(const AbstractKart *kart) const
|
||||
}
|
||||
} // getHitString
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Callback from the physics in case that a kart or physical object is hit.
|
||||
/** Callback from the physics in case that a kart or physical object is hit.
|
||||
* The cake triggers an explosion when hit.
|
||||
* \param kart The kart hit (NULL if no kart was hit).
|
||||
* \param object The object that was hit (NULL if none).
|
||||
* \returns True if there was actually a hit (i.e. not owner, and target is
|
||||
* \returns True if there was actually a hit (i.e. not owner, and target is
|
||||
* not immune), false otherwise.
|
||||
*/
|
||||
bool Cake::hit(AbstractKart* kart, PhysicalObject* obj)
|
||||
|
@ -53,8 +53,8 @@ float Flyable::m_st_force_updown[PowerupManager::POWERUP_MAX];
|
||||
Vec3 Flyable::m_st_extend [PowerupManager::POWERUP_MAX];
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Flyable::Flyable(AbstractKart *kart, PowerupManager::PowerupType type,
|
||||
float mass)
|
||||
Flyable::Flyable(AbstractKart *kart, PowerupManager::PowerupType type,
|
||||
float mass)
|
||||
: Moveable(), TerrainInfo()
|
||||
{
|
||||
// get the appropriate data from the static fields
|
||||
@ -88,7 +88,7 @@ Flyable::Flyable(AbstractKart *kart, PowerupManager::PowerupType type,
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Creates a bullet physics body for the flyable item.
|
||||
* \param forw_offset How far ahead of the kart the flyable should be
|
||||
* \param forw_offset How far ahead of the kart the flyable should be
|
||||
* positioned. Necessary to avoid exploding a rocket inside of the
|
||||
* firing kart.
|
||||
* \param velocity Initial velocity of the flyable.
|
||||
@ -97,11 +97,11 @@ Flyable::Flyable(AbstractKart *kart, PowerupManager::PowerupType type,
|
||||
* \param rotates True if the item should rotate, otherwise the angular factor
|
||||
* is set to 0 preventing rotations from happening.
|
||||
* \param turn_around True if the item is fired backwards.
|
||||
* \param custom_direction If defined the initial heading for this item,
|
||||
* \param custom_direction If defined the initial heading for this item,
|
||||
* otherwise the kart's heading will be used.
|
||||
*/
|
||||
void Flyable::createPhysics(float forw_offset, const Vec3 &velocity,
|
||||
btCollisionShape *shape,
|
||||
btCollisionShape *shape,
|
||||
float restitution, const float gravity,
|
||||
const bool rotates, const bool turn_around,
|
||||
const btTransform* custom_direction)
|
||||
@ -156,17 +156,17 @@ void Flyable::createPhysics(float forw_offset, const Vec3 &velocity,
|
||||
m_body->setLinearVelocity(v);
|
||||
if(!rotates) m_body->setAngularFactor(0.0f); // prevent rotations
|
||||
}
|
||||
m_body->setCollisionFlags(m_body->getCollisionFlags() |
|
||||
m_body->setCollisionFlags(m_body->getCollisionFlags() |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
||||
|
||||
} // createPhysics
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Initialises the static members of this class for a certain type with
|
||||
/** Initialises the static members of this class for a certain type with
|
||||
* default values and with settings from powerup.xml.
|
||||
* \param The xml node containing settings.
|
||||
* \param model The mesh to use.
|
||||
* \param type The type of flyable.
|
||||
* \param type The type of flyable.
|
||||
*/
|
||||
void Flyable::init(const XMLNode &node, scene::IMesh *model,
|
||||
PowerupManager::PowerupType type)
|
||||
@ -182,11 +182,11 @@ void Flyable::init(const XMLNode &node, scene::IMesh *model,
|
||||
core::vector3df scale(1.0f, 1.0f, 1.0f);
|
||||
if(node.get("scale", &scale))
|
||||
{
|
||||
irr::scene::IMeshManipulator *mani =
|
||||
irr::scene::IMeshManipulator *mani =
|
||||
irr_driver->getVideoDriver()->getMeshManipulator();
|
||||
mani->scale(model, scale);
|
||||
}
|
||||
|
||||
|
||||
// Store the size of the model
|
||||
Vec3 min, max;
|
||||
MeshTools::minMax3D(model, &min, &max);
|
||||
@ -203,14 +203,14 @@ Flyable::~Flyable()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns information on what is the closest kart and at what distance it is.
|
||||
* All 3 parameters first are of type 'out'. 'inFrontOf' can be set if you
|
||||
* wish to know the closest kart in front of some karts (will ignore those
|
||||
* All 3 parameters first are of type 'out'. 'inFrontOf' can be set if you
|
||||
* wish to know the closest kart in front of some karts (will ignore those
|
||||
* behind). Useful e.g. for throwing projectiles in front only.
|
||||
*/
|
||||
|
||||
void Flyable::getClosestKart(const AbstractKart **minKart,
|
||||
float *minDistSquared, Vec3 *minDelta,
|
||||
const AbstractKart* inFrontOf,
|
||||
void Flyable::getClosestKart(const AbstractKart **minKart,
|
||||
float *minDistSquared, Vec3 *minDelta,
|
||||
const AbstractKart* inFrontOf,
|
||||
const bool backwards) const
|
||||
{
|
||||
btTransform trans_projectile = (inFrontOf != NULL ? inFrontOf->getTrans()
|
||||
@ -225,7 +225,7 @@ void Flyable::getClosestKart(const AbstractKart **minKart,
|
||||
AbstractKart *kart = world->getKart(i);
|
||||
// If a kart has star effect shown, the kart is immune, so
|
||||
// it is not considered a target anymore.
|
||||
if(kart->isEliminated() || kart == m_owner ||
|
||||
if(kart->isEliminated() || kart == m_owner ||
|
||||
kart->isInvulnerable() ||
|
||||
kart->getKartAnimation() ) continue;
|
||||
btTransform t=kart->getTrans();
|
||||
@ -233,7 +233,7 @@ void Flyable::getClosestKart(const AbstractKart **minKart,
|
||||
Vec3 delta = t.getOrigin()-trans_projectile.getOrigin();
|
||||
// the Y distance is added again because karts above or below should//
|
||||
// not be prioritized when aiming
|
||||
float distance2 = delta.length2() + abs(t.getOrigin().getY()
|
||||
float distance2 = delta.length2() + abs(t.getOrigin().getY()
|
||||
- trans_projectile.getOrigin().getY())*2;
|
||||
|
||||
if(inFrontOf != NULL)
|
||||
@ -254,7 +254,7 @@ void Flyable::getClosestKart(const AbstractKart **minKart,
|
||||
float s = sqrt(v.length2() * to_target.length2());
|
||||
float c = to_target.dot(v)/s;
|
||||
// Original test was: fabsf(acos(c))>1, which is the same as
|
||||
// c<cos(1) (acos returns values in [0, pi] anyway)
|
||||
// c<cos(1) (acos returns values in [0, pi] anyway)
|
||||
if(c<0.54) continue;
|
||||
}
|
||||
|
||||
@ -269,7 +269,7 @@ void Flyable::getClosestKart(const AbstractKart **minKart,
|
||||
} // getClosestKart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns information on the parameters needed to hit a target kart moving
|
||||
/** Returns information on the parameters needed to hit a target kart moving
|
||||
* at constant velocity and direction for a given speed in the XZ-plane.
|
||||
* \param origin Location of the kart shooting the item.
|
||||
* \param target_kart Which kart to target.
|
||||
@ -280,11 +280,11 @@ void Flyable::getClosestKart(const AbstractKart **minKart,
|
||||
* \param fire_angle Returns the angle to fire the item at.
|
||||
* \param up_velocity Returns the upwards velocity to use for the item.
|
||||
*/
|
||||
void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
|
||||
void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
|
||||
const AbstractKart *target_kart,
|
||||
float item_XZ_speed,
|
||||
float item_XZ_speed,
|
||||
float gravity, float forw_offset,
|
||||
float *fire_angle,
|
||||
float *fire_angle,
|
||||
float *up_velocity)
|
||||
{
|
||||
Vec3 relative_target_kart_loc = target_kart->getXYZ() - origin;
|
||||
@ -299,12 +299,12 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
|
||||
float gy = target_direction.getY();
|
||||
|
||||
//Projected onto X-Z plane
|
||||
float target_kart_speed = target_direction.length_2d()
|
||||
float target_kart_speed = target_direction.length_2d()
|
||||
* target_kart->getSpeed();
|
||||
|
||||
float target_kart_heading = target_kart->getHeading();
|
||||
|
||||
float dist = -(target_kart_speed / item_XZ_speed)
|
||||
float dist = -(target_kart_speed / item_XZ_speed)
|
||||
* (dx * cosf(target_kart_heading) -
|
||||
dz * sinf(target_kart_heading) );
|
||||
|
||||
@ -314,9 +314,9 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
|
||||
: acosf(fire_th));
|
||||
|
||||
float time = 0.0f;
|
||||
float a = item_XZ_speed * sinf (fire_th)
|
||||
float a = item_XZ_speed * sinf (fire_th)
|
||||
+ target_kart_speed * sinf (target_kart_heading);
|
||||
float b = item_XZ_speed * cosf (fire_th)
|
||||
float b = item_XZ_speed * cosf (fire_th)
|
||||
+ target_kart_speed * cosf (target_kart_heading);
|
||||
|
||||
if (fabsf(a) > fabsf(b)) time = fabsf (dx / a);
|
||||
@ -331,7 +331,7 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
|
||||
time -= forw_offset / sqrt(a*a+b*b);
|
||||
|
||||
*fire_angle = fire_th;
|
||||
*up_velocity = (0.5f * time * gravity) + (dy / time)
|
||||
*up_velocity = (0.5f * time * gravity) + (dy / time)
|
||||
+ (gy * target_kart->getSpeed());
|
||||
} // getLinearKartItemIntersection
|
||||
|
||||
@ -344,7 +344,7 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
|
||||
bool Flyable::updateAndDelete(float dt)
|
||||
{
|
||||
m_time_since_thrown += dt;
|
||||
if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan)
|
||||
if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan)
|
||||
hit(NULL);
|
||||
|
||||
if(m_has_hit_something) return true;
|
||||
@ -355,7 +355,7 @@ bool Flyable::updateAndDelete(float dt)
|
||||
const Vec3 *min, *max;
|
||||
World::getWorld()->getTrack()->getAABB(&min, &max);
|
||||
|
||||
// I have seen that the bullet AABB can be slightly different from the
|
||||
// I have seen that the bullet AABB can be slightly different from the
|
||||
// one computed here - I assume due to minor floating point errors
|
||||
// (e.g. 308.25842 instead of 308.25845). To avoid a crash with a bullet
|
||||
// assertion (see bug 3058932) I add an epsilon here - but admittedly
|
||||
@ -374,7 +374,7 @@ bool Flyable::updateAndDelete(float dt)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add the position offset so that the flyable can adjust its position
|
||||
// Add the position offset so that the flyable can adjust its position
|
||||
// (usually to do the raycast from a slightly higher position to avoid
|
||||
// problems finding the terrain in steep uphill sections).
|
||||
if(m_do_terrain_info)
|
||||
@ -436,10 +436,10 @@ bool Flyable::isOwnerImmunity(const AbstractKart* kart_hit) const
|
||||
} // isOwnerImmunity
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Callback from the physics in case that a kart or physical object is hit.
|
||||
/** Callback from the physics in case that a kart or physical object is hit.
|
||||
* \param kart The kart hit (NULL if no kart was hit).
|
||||
* \param object The object that was hit (NULL if none).
|
||||
* \return True if there was actually a hit (i.e. not owner, and target is
|
||||
* \return True if there was actually a hit (i.e. not owner, and target is
|
||||
* not immune), false otherwise.
|
||||
*/
|
||||
bool Flyable::hit(AbstractKart *kart_hit, PhysicalObject* object)
|
||||
@ -461,7 +461,7 @@ bool Flyable::hit(AbstractKart *kart_hit, PhysicalObject* object)
|
||||
}
|
||||
|
||||
m_has_hit_something=true;
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
} // hit
|
||||
|
@ -35,7 +35,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
scene::IMesh* mesh, scene::IMesh* lowres_mesh)
|
||||
{
|
||||
assert(type != ITEM_TRIGGER); // use other constructor for that
|
||||
|
||||
|
||||
m_distance_2 = 0.8f;
|
||||
initItem(type, xyz);
|
||||
// Sets heading to 0, and sets pitch and roll depending on the normal. */
|
||||
@ -43,12 +43,12 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
m_original_mesh = mesh;
|
||||
m_original_lowmesh = lowres_mesh;
|
||||
m_listener = NULL;
|
||||
|
||||
|
||||
LODNode* lodnode = new LODNode("item",
|
||||
irr_driver->getSceneManager()->getRootSceneNode(),
|
||||
irr_driver->getSceneManager());
|
||||
scene::IMeshSceneNode* meshnode = irr_driver->addMesh(mesh);
|
||||
|
||||
|
||||
if (lowres_mesh != NULL)
|
||||
{
|
||||
lodnode->add(35, meshnode, true);
|
||||
@ -56,12 +56,12 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
lodnode->add(100, meshnode, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
lodnode->add(100, meshnode, true);
|
||||
}
|
||||
|
||||
|
||||
m_node = lodnode;
|
||||
|
||||
|
||||
//m_node = irr_driver->addMesh(mesh);
|
||||
#ifdef DEBUG
|
||||
std::string debug_name("item: ");
|
||||
@ -114,14 +114,14 @@ void Item::initItem(ItemType type, const Vec3 &xyz)
|
||||
(type!=ITEM_EASTER_EGG);
|
||||
switch(m_type)
|
||||
{
|
||||
case ITEM_BUBBLEGUM:
|
||||
case ITEM_BUBBLEGUM:
|
||||
m_disappear_counter = stk_config->m_bubble_gum_counter; break;
|
||||
case ITEM_EASTER_EGG:
|
||||
m_disappear_counter = -1; break;
|
||||
default:
|
||||
m_disappear_counter = -1;
|
||||
}
|
||||
// Now determine in which quad this item is, and its distance
|
||||
// Now determine in which quad this item is, and its distance
|
||||
// from the center within this quad.
|
||||
m_graph_node = QuadGraph::UNKNOWN_SECTOR;
|
||||
QuadGraph* currentQuadGraph = QuadGraph::get();
|
||||
@ -176,10 +176,10 @@ void Item::switchTo(ItemType type, scene::IMesh *mesh, scene::IMesh *lowmesh)
|
||||
{
|
||||
// triggers and easter eggs should not be switched
|
||||
if (m_type == ITEM_TRIGGER || m_type == ITEM_EASTER_EGG) return;
|
||||
|
||||
|
||||
m_original_type = m_type;
|
||||
setType(type);
|
||||
|
||||
|
||||
scene::ISceneNode* node = m_node->getAllNodes()[0];
|
||||
((scene::IMeshSceneNode*)node)->setMesh(mesh);
|
||||
if (lowmesh != NULL)
|
||||
@ -187,7 +187,7 @@ void Item::switchTo(ItemType type, scene::IMesh *mesh, scene::IMesh *lowmesh)
|
||||
node = m_node->getAllNodes()[1];
|
||||
((scene::IMeshSceneNode*)node)->setMesh(lowmesh);
|
||||
}
|
||||
|
||||
|
||||
World::getWorld()->getTrack()->adjustForFog(m_node);
|
||||
} // switchTo
|
||||
|
||||
@ -198,16 +198,16 @@ void Item::switchBack()
|
||||
{
|
||||
// triggers should not be switched
|
||||
if (m_type == ITEM_TRIGGER) return;
|
||||
|
||||
|
||||
// If the item is not switched, do nothing. This can happen if a bubble
|
||||
// gum is dropped while items are switched - when switching back, this
|
||||
// bubble gum has no original type.
|
||||
if(m_original_type==ITEM_NONE)
|
||||
return;
|
||||
|
||||
|
||||
setType(m_original_type);
|
||||
m_original_type = ITEM_NONE;
|
||||
|
||||
|
||||
scene::ISceneNode* node = m_node->getAllNodes()[0];
|
||||
((scene::IMeshSceneNode*)node)->setMesh(m_original_mesh);
|
||||
if (m_original_lowmesh != NULL)
|
||||
@ -215,7 +215,7 @@ void Item::switchBack()
|
||||
node = m_node->getAllNodes()[1];
|
||||
((scene::IMeshSceneNode*)node)->setMesh(m_original_lowmesh);
|
||||
}
|
||||
|
||||
|
||||
World::getWorld()->getTrack()->adjustForFog(m_node);
|
||||
m_node->setRotation(m_original_hpr.toIrrHPR());
|
||||
} // switchBack
|
||||
@ -246,7 +246,7 @@ void Item::reset()
|
||||
m_deactive_time = 0.0f;
|
||||
switch(m_type)
|
||||
{
|
||||
case ITEM_BUBBLEGUM:
|
||||
case ITEM_BUBBLEGUM:
|
||||
m_disappear_counter = stk_config->m_bubble_gum_counter; break;
|
||||
case ITEM_EASTER_EGG:
|
||||
m_disappear_counter = -1; break;
|
||||
@ -258,7 +258,7 @@ void Item::reset()
|
||||
setType(m_original_type);
|
||||
m_original_type = ITEM_NONE;
|
||||
}
|
||||
|
||||
|
||||
if (m_node != NULL)
|
||||
{
|
||||
m_node->setScale(core::vector3df(1,1,1));
|
||||
@ -286,14 +286,14 @@ void Item::setParent(AbstractKart* parent)
|
||||
void Item::update(float dt)
|
||||
{
|
||||
if(m_deactive_time > 0) m_deactive_time -= dt;
|
||||
|
||||
|
||||
if(m_collected)
|
||||
{
|
||||
m_time_till_return -= dt;
|
||||
if(m_time_till_return<0)
|
||||
{
|
||||
m_collected=false;
|
||||
|
||||
|
||||
if (m_node != NULL)
|
||||
{
|
||||
m_node->setScale(core::vector3df(1,1,1));
|
||||
@ -311,14 +311,14 @@ void Item::update(float dt)
|
||||
} // if collected
|
||||
else
|
||||
{ // not m_collected
|
||||
|
||||
|
||||
if(!m_rotate || m_node == NULL) return;
|
||||
// have it rotate
|
||||
Vec3 rotation(0, dt*M_PI, 0);
|
||||
core::vector3df r = m_node->getRotation();
|
||||
r.Y += dt*180.0f;
|
||||
if(r.Y>360.0f) r.Y -= 360.0f;
|
||||
|
||||
|
||||
m_node->setRotation(r);
|
||||
return;
|
||||
} // not m_collected
|
||||
@ -326,7 +326,7 @@ void Item::update(float dt)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Is called when the item is hit by a kart. It sets the flag that the item
|
||||
* has been collected, and the time to return to the parameter.
|
||||
* has been collected, and the time to return to the parameter.
|
||||
* \param t Time till the object reappears (defaults to 2 seconds).
|
||||
*/
|
||||
void Item::collected(const AbstractKart *kart, float t)
|
||||
@ -351,7 +351,7 @@ void Item::collected(const AbstractKart *kart, float t)
|
||||
// prevent bubble gum from hitting a kart over and over again (in each
|
||||
// frame) by giving it time to drive away.
|
||||
m_deactive_time = 0.5f;
|
||||
// Set the time till reappear to -1 seconds --> the item will
|
||||
// Set the time till reappear to -1 seconds --> the item will
|
||||
// reappear immediately.
|
||||
m_time_till_return = -1;
|
||||
}
|
||||
@ -365,12 +365,12 @@ void Item::collected(const AbstractKart *kart, float t)
|
||||
m_node->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_listener != NULL)
|
||||
{
|
||||
m_listener->onTriggerItemApproached(this);
|
||||
}
|
||||
|
||||
|
||||
if (dynamic_cast<ThreeStrikesBattle*>(World::getWorld()) != NULL)
|
||||
{
|
||||
m_time_till_return *= 3;
|
||||
|
@ -79,7 +79,7 @@ void ItemManager::loadDefaultItemMeshes()
|
||||
item_names[Item::ITEM_TRIGGER ] = "trigger";
|
||||
item_names[Item::ITEM_BUBBLEGUM_NOLOK] = "bubblegum-nolok";
|
||||
item_names[Item::ITEM_EASTER_EGG ] = "easter-egg";
|
||||
|
||||
|
||||
const std::string file_name = file_manager->getDataFile("items.xml");
|
||||
const XMLNode *root = file_manager->createXMLTree(file_name);
|
||||
for(unsigned int i=Item::ITEM_FIRST; i<=Item::ITEM_LAST; i++)
|
||||
@ -90,15 +90,15 @@ void ItemManager::loadDefaultItemMeshes()
|
||||
|
||||
std::string model_filename;
|
||||
node->get("model", &model_filename);
|
||||
|
||||
scene::IMesh *mesh = irr_driver->getAnimatedMesh(model_filename);
|
||||
|
||||
scene::IMesh *mesh = irr_driver->getAnimatedMesh(model_filename);
|
||||
if(!node || model_filename.size()==0 || !mesh)
|
||||
{
|
||||
fprintf(stderr, "Item model '%s' in items.xml could not be loaded "
|
||||
"- aborting", name.c_str());
|
||||
exit(-1);
|
||||
}
|
||||
mesh->grab();
|
||||
mesh->grab();
|
||||
m_item_mesh[i] = mesh;
|
||||
|
||||
std::string lowres_model_filename;
|
||||
@ -180,7 +180,7 @@ void ItemManager::setSwitchItems(const std::vector<int> &switch_items)
|
||||
/** Destructor. Cleans up all items and meshes stored.
|
||||
*/
|
||||
ItemManager::~ItemManager()
|
||||
{
|
||||
{
|
||||
if(m_items_in_quads)
|
||||
delete m_items_in_quads;
|
||||
for(AllItemTypes::iterator i =m_all_items.begin();
|
||||
@ -195,7 +195,7 @@ ItemManager::~ItemManager()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Inserts the new item into the items management data structures, if possible
|
||||
* reusing an existing, unused entry (e.g. due to a removed bubble gum). Then
|
||||
* reusing an existing, unused entry (e.g. due to a removed bubble gum). Then
|
||||
* the item is also added to the quad-wise list of items.
|
||||
*/
|
||||
void ItemManager::insertItem(Item *item)
|
||||
@ -204,7 +204,7 @@ void ItemManager::insertItem(Item *item)
|
||||
// previously deleted entry, otherwise at the end.
|
||||
int index = -1;
|
||||
for(index=m_all_items.size()-1; index>=0 && m_all_items[index]; index--) {}
|
||||
|
||||
|
||||
if(index==-1) index = m_all_items.size();
|
||||
|
||||
if(index<(int)m_all_items.size())
|
||||
@ -237,7 +237,7 @@ void ItemManager::insertItem(Item *item)
|
||||
* \param parent In case of a dropped item used to avoid that a kart
|
||||
* is affected by its own items.
|
||||
*/
|
||||
Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz,
|
||||
Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz,
|
||||
const Vec3 &normal, AbstractKart *parent)
|
||||
{
|
||||
Item::ItemType mesh_type = type;
|
||||
@ -245,8 +245,8 @@ Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz,
|
||||
{
|
||||
mesh_type = Item::ITEM_BUBBLEGUM_NOLOK;
|
||||
}
|
||||
|
||||
Item* item = new Item(type, xyz, normal, m_item_mesh[mesh_type],
|
||||
|
||||
Item* item = new Item(type, xyz, normal, m_item_mesh[mesh_type],
|
||||
m_item_lowres_mesh[mesh_type]);
|
||||
|
||||
insertItem(item);
|
||||
@ -254,7 +254,7 @@ Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz,
|
||||
if(m_switch_time>=0)
|
||||
{
|
||||
Item::ItemType new_type = m_switch_to[item->getType()];
|
||||
item->switchTo(new_type, m_item_mesh[(int)new_type],
|
||||
item->switchTo(new_type, m_item_mesh[(int)new_type],
|
||||
m_item_lowres_mesh[(int)new_type]);
|
||||
}
|
||||
return item;
|
||||
@ -264,7 +264,7 @@ Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz,
|
||||
/** Creates a new trigger item.
|
||||
* \param xyz Position of the item.
|
||||
*/
|
||||
Item* ItemManager::newItem(const Vec3& xyz, float distance,
|
||||
Item* ItemManager::newItem(const Vec3& xyz, float distance,
|
||||
TriggerItemListener* listener)
|
||||
{
|
||||
Item* item;
|
||||
@ -276,7 +276,7 @@ Item* ItemManager::newItem(const Vec3& xyz, float distance,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Set an item as collected.
|
||||
* This function is called on the server when an item is collected, or on
|
||||
* This function is called on the server when an item is collected, or on
|
||||
* the client upon receiving information about collected items. */
|
||||
void ItemManager::collectedItem(Item *item, AbstractKart *kart, int add_info)
|
||||
{
|
||||
@ -288,19 +288,19 @@ void ItemManager::collectedItem(Item *item, AbstractKart *kart, int add_info)
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Checks if any item was collected by the given kart. This function calls
|
||||
* collectedItem if an item was collected.
|
||||
* \param kart Pointer to the kart.
|
||||
* \param kart Pointer to the kart.
|
||||
*/
|
||||
void ItemManager::checkItemHit(AbstractKart* kart)
|
||||
{
|
||||
// Only do this on the server
|
||||
if(network_manager->getMode()==NetworkManager::NW_CLIENT) return;
|
||||
|
||||
|
||||
// We could use m_items_in_quads to to check for item hits: take the quad
|
||||
// of the graph node of the kart, and only check items in that quad. But
|
||||
// then we also need to check for any adjacent quads (since an item just
|
||||
// on the order of one quad might get hit from an adjacent quad). Then
|
||||
// it is possible that a quad is that short that we need to test adjacent
|
||||
// of adjacent quads. And check for items outside of the track.
|
||||
// of adjacent quads. And check for items outside of the track.
|
||||
// Since at this stace item detection is by far not a bottle neck,
|
||||
// the original, simple and stable algorithm is left in place.
|
||||
|
||||
@ -326,7 +326,7 @@ void ItemManager::reset()
|
||||
// If items are switched, switch them back first.
|
||||
if(m_switch_time>=0)
|
||||
{
|
||||
for(AllItemTypes::iterator i =m_all_items.begin();
|
||||
for(AllItemTypes::iterator i =m_all_items.begin();
|
||||
i!=m_all_items.end(); i++)
|
||||
{
|
||||
if(*i) (*i)->switchBack();
|
||||
@ -341,7 +341,7 @@ void ItemManager::reset()
|
||||
AllItemTypes::iterator i=m_all_items.begin();
|
||||
while(i!=m_all_items.end())
|
||||
{
|
||||
if(!*i)
|
||||
if(!*i)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
@ -376,7 +376,7 @@ void ItemManager::update(float dt)
|
||||
{
|
||||
for(AllItemTypes::iterator i =m_all_items.begin();
|
||||
i!=m_all_items.end(); i++)
|
||||
{
|
||||
{
|
||||
if(*i) (*i)->switchBack();
|
||||
} // for m_all_items
|
||||
} // m_switch_time < 0
|
||||
@ -433,7 +433,7 @@ void ItemManager::switchItems()
|
||||
i!=m_all_items.end(); i++)
|
||||
{
|
||||
if(!*i) continue;
|
||||
|
||||
|
||||
if ((*i)->getType() == Item::ITEM_BUBBLEGUM || (*i)->getType() == Item::ITEM_BUBBLEGUM_NOLOK)
|
||||
{
|
||||
if (race_manager->getAISuperPower() == RaceManager::SUPERPOWER_NOLOK_BOSS)
|
||||
@ -441,7 +441,7 @@ void ItemManager::switchItems()
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item::ItemType new_type = m_switch_to[(*i)->getType()];
|
||||
|
||||
if(m_switch_time<0)
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
Plunger::Plunger(AbstractKart *kart)
|
||||
Plunger::Plunger(AbstractKart *kart)
|
||||
: Flyable(kart, PowerupManager::POWERUP_PLUNGER)
|
||||
{
|
||||
const float gravity = 0.0f;
|
||||
@ -51,7 +51,7 @@ Plunger::Plunger(AbstractKart *kart)
|
||||
m_reverse_mode = kart->getControls().m_look_back;
|
||||
|
||||
// find closest kart in front of the current one
|
||||
const AbstractKart *closest_kart=0;
|
||||
const AbstractKart *closest_kart=0;
|
||||
Vec3 direction;
|
||||
float kart_dist_2;
|
||||
getClosestKart(&closest_kart, &kart_dist_2, &direction,
|
||||
@ -74,21 +74,21 @@ Plunger::Plunger(AbstractKart *kart)
|
||||
&fire_angle, &up_velocity);
|
||||
|
||||
btTransform trans = kart->getTrans();
|
||||
|
||||
|
||||
trans.setRotation(btQuaternion(btVector3(0, 1, 0), fire_angle));
|
||||
|
||||
m_initial_velocity = btVector3(0.0f, up_velocity, plunger_speed);
|
||||
|
||||
createPhysics(forward_offset, m_initial_velocity,
|
||||
new btCylinderShape(0.5f*m_extend),
|
||||
0.5f /* restitution */ , gravity,
|
||||
new btCylinderShape(0.5f*m_extend),
|
||||
0.5f /* restitution */ , gravity,
|
||||
/* rotates */false , /*turn around*/false, &trans);
|
||||
}
|
||||
else
|
||||
{
|
||||
createPhysics(forward_offset, btVector3(pitch, 0.0f, plunger_speed),
|
||||
new btCylinderShape(0.5f*m_extend),
|
||||
0.5f /* restitution */, gravity,
|
||||
new btCylinderShape(0.5f*m_extend),
|
||||
0.5f /* restitution */, gravity,
|
||||
false /* rotates */, m_reverse_mode, &kart_transform);
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ bool Plunger::updateAndDelete(float dt)
|
||||
* till the rubber band expires.
|
||||
* \param kart Pointer to the kart hit (NULL if not a kart).
|
||||
* \param obj Pointer to PhysicalObject object if hit (NULL otherwise).
|
||||
* \returns True if there was actually a hit (i.e. not owner, and target is
|
||||
* \returns True if there was actually a hit (i.e. not owner, and target is
|
||||
* not immune), false otherwise.
|
||||
*/
|
||||
bool Plunger::hit(AbstractKart *kart, PhysicalObject *obj)
|
||||
@ -237,7 +237,7 @@ bool Plunger::hit(AbstractKart *kart, PhysicalObject *obj)
|
||||
}
|
||||
}
|
||||
|
||||
// Rubber band attached.
|
||||
// Rubber band attached.
|
||||
return false;
|
||||
} // hit
|
||||
|
||||
|
@ -89,8 +89,8 @@ const wchar_t* getSwapperString()
|
||||
} // getSwapperString
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Constructor, stores the kart to which this powerup belongs.
|
||||
* \param kart The kart to which this powerup belongs.
|
||||
/** Constructor, stores the kart to which this powerup belongs.
|
||||
* \param kart The kart to which this powerup belongs.
|
||||
*/
|
||||
Powerup::Powerup(AbstractKart* kart)
|
||||
{
|
||||
@ -114,7 +114,7 @@ void Powerup::reset()
|
||||
{
|
||||
m_type = PowerupManager::POWERUP_NOTHING;
|
||||
m_number = 0;
|
||||
|
||||
|
||||
int type, number;
|
||||
World::getWorld()->getDefaultCollectibles( &type, &number );
|
||||
set( (PowerupManager::PowerupType)type, number );
|
||||
@ -136,13 +136,13 @@ void Powerup::set(PowerupManager::PowerupType type, int n)
|
||||
}
|
||||
m_type=type;
|
||||
m_number=n;
|
||||
|
||||
|
||||
if(m_sound_use != NULL)
|
||||
{
|
||||
sfx_manager->deleteSFX(m_sound_use);
|
||||
m_sound_use = NULL;
|
||||
}
|
||||
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
// No sound effect when arming the glove
|
||||
@ -151,27 +151,27 @@ void Powerup::set(PowerupManager::PowerupType type, int n)
|
||||
|
||||
case PowerupManager::POWERUP_ZIPPER:
|
||||
break ;
|
||||
|
||||
|
||||
case PowerupManager::POWERUP_BOWLING:
|
||||
m_sound_use = sfx_manager->createSoundSource("bowling_roll");
|
||||
break ;
|
||||
|
||||
|
||||
case PowerupManager::POWERUP_ANVIL:
|
||||
m_sound_use = sfx_manager->createSoundSource("anvil");
|
||||
break;
|
||||
|
||||
|
||||
case PowerupManager::POWERUP_PARACHUTE:
|
||||
m_sound_use = sfx_manager->createSoundSource("parachute");
|
||||
break;
|
||||
|
||||
|
||||
case PowerupManager::POWERUP_BUBBLEGUM:
|
||||
m_sound_use = sfx_manager->createSoundSource("goo");
|
||||
break ;
|
||||
|
||||
|
||||
case PowerupManager::POWERUP_SWITCH:
|
||||
m_sound_use = sfx_manager->createSoundSource("swap");
|
||||
break;
|
||||
|
||||
|
||||
case PowerupManager::POWERUP_NOTHING:
|
||||
case PowerupManager::POWERUP_CAKE:
|
||||
case PowerupManager::POWERUP_PLUNGER:
|
||||
@ -179,7 +179,7 @@ void Powerup::set(PowerupManager::PowerupType type, int n)
|
||||
m_sound_use = sfx_manager->createSoundSource("shoot");
|
||||
break ;
|
||||
}
|
||||
|
||||
|
||||
} // set
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -199,25 +199,25 @@ Material *Powerup::getIcon() const
|
||||
void Powerup::use()
|
||||
{
|
||||
// Play custom kart sound when collectible is used
|
||||
if (m_type != PowerupManager::POWERUP_NOTHING &&
|
||||
if (m_type != PowerupManager::POWERUP_NOTHING &&
|
||||
m_type != PowerupManager::POWERUP_SWATTER &&
|
||||
m_type != PowerupManager::POWERUP_ZIPPER)
|
||||
m_type != PowerupManager::POWERUP_ZIPPER)
|
||||
m_owner->playCustomSFX(SFXManager::CUSTOM_SHOOT);
|
||||
|
||||
// FIXME - for some collectibles, set() is never called
|
||||
if(m_sound_use == NULL)
|
||||
{
|
||||
//if (m_type == POWERUP_SWITCH) m_sound_use = sfx_manager->newSFX(SFXManager::SOUND_SWAP);
|
||||
//else
|
||||
//else
|
||||
m_sound_use = sfx_manager->createSoundSource("shoot");
|
||||
}
|
||||
|
||||
|
||||
m_number--;
|
||||
World *world = World::getWorld();
|
||||
RaceGUIBase* gui = world->getRaceGUI();
|
||||
switch (m_type)
|
||||
{
|
||||
case PowerupManager::POWERUP_ZIPPER:
|
||||
case PowerupManager::POWERUP_ZIPPER:
|
||||
m_owner->handleZipper(NULL, true);
|
||||
break ;
|
||||
case PowerupManager::POWERUP_SWITCH:
|
||||
@ -234,15 +234,15 @@ void Powerup::use()
|
||||
case PowerupManager::POWERUP_RUBBERBALL:
|
||||
case PowerupManager::POWERUP_BOWLING:
|
||||
case PowerupManager::POWERUP_PLUNGER:
|
||||
|
||||
|
||||
m_sound_use->position(m_owner->getXYZ());
|
||||
|
||||
|
||||
// in multiplayer mode, sounds are NOT positional (because we have multiple listeners)
|
||||
// so the sounds of all AIs are constantly heard. So reduce volume of sounds.
|
||||
if (race_manager->getNumLocalPlayers() > 1)
|
||||
{
|
||||
// player karts played at full volume; AI karts much dimmer
|
||||
|
||||
|
||||
if (m_owner->getController()->isPlayerController())
|
||||
{
|
||||
m_sound_use->volume( 1.0f );
|
||||
@ -252,7 +252,7 @@ void Powerup::use()
|
||||
m_sound_use->volume( std::min(0.5f, 1.0f / race_manager->getNumberOfKarts()) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_sound_use->play();
|
||||
projectile_manager->newProjectile(m_owner, world->getTrack(), m_type);
|
||||
break ;
|
||||
@ -276,16 +276,16 @@ void Powerup::use()
|
||||
if(!material_hit)
|
||||
return;
|
||||
normal.normalize();
|
||||
|
||||
|
||||
// in multiplayer mode, sounds are NOT positional (because we have multiple listeners)
|
||||
// so the sounds of all AIs are constantly heard. So reduce volume of sounds.
|
||||
if (race_manager->getNumLocalPlayers() > 1)
|
||||
{
|
||||
const int np = race_manager->getNumLocalPlayers();
|
||||
const int nai = race_manager->getNumberOfKarts() - np;
|
||||
|
||||
|
||||
// player karts played at full volume; AI karts much dimmer
|
||||
|
||||
|
||||
if (m_owner->getController()->isPlayerController())
|
||||
{
|
||||
m_sound_use->volume( 1.0f );
|
||||
@ -295,18 +295,18 @@ void Powerup::use()
|
||||
m_sound_use->volume( 1.0f / nai );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_sound_use->position(m_owner->getXYZ());
|
||||
m_sound_use->play();
|
||||
|
||||
|
||||
pos.setY(hit_point.getY()-0.05f);
|
||||
|
||||
|
||||
ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_owner);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case PowerupManager::POWERUP_ANVIL:
|
||||
|
||||
|
||||
//Attach an anvil(twice as good as the one given
|
||||
//by the bananas) to the kart in the 1st position.
|
||||
for(unsigned int i = 0 ; i < world->getNumKarts(); ++i)
|
||||
@ -316,11 +316,11 @@ void Powerup::use()
|
||||
if(kart == m_owner) continue;
|
||||
if(kart->getPosition() == 1)
|
||||
{
|
||||
kart->getAttachment()->set(Attachment::ATTACH_ANVIL,
|
||||
kart->getAttachment()->set(Attachment::ATTACH_ANVIL,
|
||||
stk_config->m_anvil_time);
|
||||
kart->updateWeight();
|
||||
kart->adjustSpeed(stk_config->m_anvil_speed_factor*0.5f);
|
||||
|
||||
|
||||
// should we position the sound at the kart that is hit,
|
||||
// or the kart "throwing" the anvil? Ideally it should be both.
|
||||
// Meanwhile, don't play it near AI karts since they obviously
|
||||
@ -329,7 +329,7 @@ void Powerup::use()
|
||||
m_sound_use->position(kart->getXYZ());
|
||||
else
|
||||
m_sound_use->position(m_owner->getXYZ());
|
||||
|
||||
|
||||
m_sound_use->play();
|
||||
|
||||
irr::core::stringw anchor_message;
|
||||
@ -355,7 +355,7 @@ void Powerup::use()
|
||||
if(m_owner->getPosition() > kart->getPosition())
|
||||
{
|
||||
kart->getAttachment()
|
||||
->set(Attachment::ATTACH_PARACHUTE,
|
||||
->set(Attachment::ATTACH_PARACHUTE,
|
||||
stk_config->m_parachute_time_other);
|
||||
|
||||
if(kart->getController()->isPlayerController())
|
||||
@ -404,37 +404,37 @@ void Powerup::use()
|
||||
* for servers so that the clients can be informed which item
|
||||
* was collected.
|
||||
* \param add_info Additional information. This is used for network games
|
||||
* so that the server can overwrite which item is collectted
|
||||
* so that the server can overwrite which item is collectted
|
||||
* (otherwise a random choice is done).
|
||||
*/
|
||||
void Powerup::hitBonusBox(const Item &item, int add_info)
|
||||
{
|
||||
// Position can be -1 in case of a battle mode (which doesn't have
|
||||
// Position can be -1 in case of a battle mode (which doesn't have
|
||||
// positions), but this case is properly handled in getRandomPowerup.
|
||||
int position = m_owner->getPosition();
|
||||
|
||||
|
||||
unsigned int n=1;
|
||||
PowerupManager::PowerupType new_powerup;
|
||||
|
||||
// Check if rubber ball is the current power up held by the kart. If so,
|
||||
|
||||
// Check if rubber ball is the current power up held by the kart. If so,
|
||||
// reset the bBallCollectTime to 0 before giving new powerup.
|
||||
if(m_type == PowerupManager::POWERUP_RUBBERBALL)
|
||||
if(m_type == PowerupManager::POWERUP_RUBBERBALL)
|
||||
powerup_manager->setBallCollectTime(0);
|
||||
|
||||
|
||||
// Check if two bouncing balls are collected less than getRubberBallTimer()
|
||||
//seconds apart. If yes, then call getRandomPowerup again. If no, then break.
|
||||
for(int i=0; i<20; i++)
|
||||
{
|
||||
new_powerup = powerup_manager->getRandomPowerup(position, &n);
|
||||
if(new_powerup != PowerupManager::POWERUP_RUBBERBALL ||
|
||||
if(new_powerup != PowerupManager::POWERUP_RUBBERBALL ||
|
||||
( World::getWorld()->getTime() - powerup_manager->getBallCollectTime()) >
|
||||
RubberBall::getTimeBetweenRubberBalls() )
|
||||
RubberBall::getTimeBetweenRubberBalls() )
|
||||
break;
|
||||
}
|
||||
|
||||
if(new_powerup == PowerupManager::POWERUP_RUBBERBALL)
|
||||
powerup_manager->setBallCollectTime(World::getWorld()->getTime());
|
||||
|
||||
powerup_manager->setBallCollectTime(World::getWorld()->getTime());
|
||||
|
||||
// Always add a new powerup in ITEM_MODE_NEW (or if the kart
|
||||
// doesn't have a powerup atm).
|
||||
if(m_type == PowerupManager::POWERUP_NOTHING ||
|
||||
@ -450,7 +450,7 @@ void Powerup::hitBonusBox(const Item &item, int add_info)
|
||||
new_powerup==m_type)
|
||||
{
|
||||
m_number+=n;
|
||||
if(m_number > MAX_POWERUPS)
|
||||
if(m_number > MAX_POWERUPS)
|
||||
m_number = MAX_POWERUPS;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "items/bowling.hpp"
|
||||
#include "items/bowling.hpp"
|
||||
#include "items/cake.hpp"
|
||||
#include "items/plunger.hpp"
|
||||
#include "items/rubber_ball.hpp"
|
||||
@ -78,7 +78,7 @@ void PowerupManager::unloadPowerups()
|
||||
{
|
||||
if(m_all_meshes[(PowerupType)i])
|
||||
m_all_meshes[(PowerupType)i]->drop();
|
||||
|
||||
|
||||
//FIXME: I'm not sure if this is OK or if I need to ->drop(), or delete them, or...
|
||||
m_all_icons[i] = (Material*)NULL;
|
||||
}
|
||||
@ -89,13 +89,13 @@ void PowerupManager::unloadPowerups()
|
||||
* \param name Name of the powerup to look up.
|
||||
* \return The type, or POWERUP_NOTHING if the name is not found
|
||||
*/
|
||||
PowerupManager::PowerupType
|
||||
PowerupManager::PowerupType
|
||||
PowerupManager::getPowerupType(const std::string &name) const
|
||||
{
|
||||
// Must match the order of PowerupType in powerup_manager.hpp!!
|
||||
static std::string powerup_names[] = {
|
||||
"", /* Nothing */
|
||||
"bubblegum", "cake", "bowling", "zipper", "plunger", "switch",
|
||||
"", /* Nothing */
|
||||
"bubblegum", "cake", "bowling", "zipper", "plunger", "switch",
|
||||
"swatter", "rubber-ball", "parachute", "anchor"
|
||||
};
|
||||
|
||||
@ -137,23 +137,23 @@ void PowerupManager::loadAllPowerups()
|
||||
loadWeights(*root, "last" , POSITION_LAST );
|
||||
loadWeights(*root, "battle" , POSITION_BATTLE_MODE);
|
||||
loadWeights(*root, "tuto", POSITION_TUTORIAL_MODE);
|
||||
|
||||
|
||||
delete root;
|
||||
|
||||
|
||||
} // loadAllPowerups
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Loads the data for one particular powerup. For bowling ball, plunger, and
|
||||
* cake static members in the appropriate classes are called to store
|
||||
* cake static members in the appropriate classes are called to store
|
||||
* additional information for those objects.
|
||||
* \param type The type of the powerup.
|
||||
* \param node The XML node with the data for this powerup.
|
||||
*/
|
||||
void PowerupManager::LoadPowerup(PowerupType type, const XMLNode &node)
|
||||
{
|
||||
std::string icon_file("");
|
||||
std::string icon_file("");
|
||||
node.get("icon", &icon_file);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
if (icon_file.size() == 0)
|
||||
{
|
||||
@ -161,16 +161,16 @@ void PowerupManager::LoadPowerup(PowerupType type, const XMLNode &node)
|
||||
assert(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
m_all_icons[type] = material_manager->getMaterial(icon_file,
|
||||
/* full_path */ false,
|
||||
/*make_permanent */ true);
|
||||
/*make_permanent */ true);
|
||||
|
||||
|
||||
assert(m_all_icons[type] != NULL);
|
||||
assert(m_all_icons[type]->getTexture() != NULL);
|
||||
|
||||
std::string model("");
|
||||
|
||||
std::string model("");
|
||||
node.get("model", &model);
|
||||
if(model.size()>0)
|
||||
{
|
||||
@ -191,11 +191,11 @@ void PowerupManager::LoadPowerup(PowerupType type, const XMLNode &node)
|
||||
}
|
||||
// Load special attributes for certain powerups
|
||||
switch (type) {
|
||||
case POWERUP_BOWLING:
|
||||
case POWERUP_BOWLING:
|
||||
Bowling::init(node, m_all_meshes[type]); break;
|
||||
case POWERUP_PLUNGER:
|
||||
case POWERUP_PLUNGER:
|
||||
Plunger::init(node, m_all_meshes[type]); break;
|
||||
case POWERUP_CAKE:
|
||||
case POWERUP_CAKE:
|
||||
Cake::init(node, m_all_meshes[type]); break;
|
||||
case POWERUP_RUBBERBALL:
|
||||
RubberBall::init(node, m_all_meshes[type]); break;
|
||||
@ -206,7 +206,7 @@ void PowerupManager::LoadPowerup(PowerupType type, const XMLNode &node)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads a weight list specified in powerup.xml. The different position
|
||||
* classes must be loaded in the right order
|
||||
* \param root The root node of powerup.xml
|
||||
* \param root The root node of powerup.xml
|
||||
* \param class_name The name of the position class to load.
|
||||
* \param position_class The class for which the weights are read.
|
||||
*/
|
||||
@ -245,7 +245,7 @@ void PowerupManager::loadWeights(const XMLNode &root,
|
||||
|
||||
if(weight_list.size()!=2*(int)POWERUP_LAST)
|
||||
{
|
||||
printf("Incorrect number of weights found in class '%s':\n",
|
||||
printf("Incorrect number of weights found in class '%s':\n",
|
||||
class_name.c_str());
|
||||
printf("%d instead of %d - probabilities will be incorrect.\n",
|
||||
(int)weight_list.size(), (int)POWERUP_LAST);
|
||||
@ -286,8 +286,8 @@ void PowerupManager::updateWeightsForRace(unsigned int num_karts)
|
||||
m_powerups_for_position[pos_class].clear();
|
||||
for(unsigned int i= POWERUP_FIRST; i<=2*POWERUP_LAST; i++)
|
||||
{
|
||||
PowerupType type =
|
||||
(PowerupType) ((i<=POWERUP_LAST) ? i
|
||||
PowerupType type =
|
||||
(PowerupType) ((i<=POWERUP_LAST) ? i
|
||||
: i+POWERUP_FIRST);
|
||||
unsigned int w =m_weights[pos_class][i-POWERUP_FIRST];
|
||||
// The 'global' powerups (i.e. powerups that affect
|
||||
@ -309,15 +309,15 @@ void PowerupManager::updateWeightsForRace(unsigned int num_karts)
|
||||
} // updateWeightsForRace
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determines the position class for a given position. If the race is a
|
||||
/** Determines the position class for a given position. If the race is a
|
||||
* battle mode (in which case we don't have a position), always return
|
||||
* 'POSITION_BATTLE_MODE' (and in this case only position 1 will be used
|
||||
* for all karts).
|
||||
* \param num_karts Number of karts in the race.
|
||||
* \param position The position for which to determine the position class.
|
||||
*/
|
||||
PowerupManager::PositionClass
|
||||
PowerupManager::convertPositionToClass(unsigned int num_karts,
|
||||
PowerupManager::PositionClass
|
||||
PowerupManager::convertPositionToClass(unsigned int num_karts,
|
||||
unsigned int position)
|
||||
{
|
||||
if(race_manager->isBattleMode()) return POSITION_BATTLE_MODE;
|
||||
@ -326,7 +326,7 @@ PowerupManager::PositionClass
|
||||
if(position==num_karts) return POSITION_LAST;
|
||||
|
||||
// Now num_karts must be >2, since position <=num_players
|
||||
|
||||
|
||||
unsigned int third = (unsigned int)floor((float)(num_karts-1)/3.0f);
|
||||
// 1 < Position <= 1+third is top33
|
||||
if(position <= 1 + third) return POSITION_TOP33;
|
||||
@ -351,7 +351,7 @@ PowerupManager::PowerupType PowerupManager::getRandomPowerup(unsigned int pos,
|
||||
unsigned int *n)
|
||||
{
|
||||
// Positions start with 1, while the index starts with 0 - so subtract 1
|
||||
PositionClass pos_class =
|
||||
PositionClass pos_class =
|
||||
(race_manager->isBattleMode() ? POSITION_BATTLE_MODE :
|
||||
(race_manager->isTutorialMode() ? POSITION_TUTORIAL_MODE :
|
||||
m_position_to_class[pos-1]));
|
||||
|
@ -51,7 +51,7 @@ void ProjectileManager::cleanup()
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
|
||||
|
||||
m_active_projectiles.clear();
|
||||
for(HitEffects::iterator i = m_active_hit_effects.begin();
|
||||
i != m_active_hit_effects.end(); ++i)
|
||||
@ -113,7 +113,7 @@ void ProjectileManager::updateServer(float dt)
|
||||
if(network_manager->getMode()!=NetworkManager::NW_NONE)
|
||||
{
|
||||
race_state->setFlyableInfo(p-m_active_projectiles.begin(),
|
||||
FlyableInfo((*p)->getXYZ(),
|
||||
FlyableInfo((*p)->getXYZ(),
|
||||
(*p)->getRotation(),
|
||||
can_be_deleted) );
|
||||
}
|
||||
@ -149,7 +149,7 @@ void ProjectileManager::updateClient(float dt)
|
||||
{
|
||||
const FlyableInfo &f = race_state->getFlyable(indx);
|
||||
(*i)->updateFromServer(f, dt);
|
||||
if(f.m_exploded)
|
||||
if(f.m_exploded)
|
||||
{
|
||||
(*i)->hit(NULL);
|
||||
}
|
||||
@ -161,12 +161,12 @@ Flyable *ProjectileManager::newProjectile(AbstractKart *kart, Track* track,
|
||||
PowerupManager::PowerupType type)
|
||||
{
|
||||
Flyable *f;
|
||||
switch(type)
|
||||
switch(type)
|
||||
{
|
||||
case PowerupManager::POWERUP_BOWLING: f = new Bowling(kart); break;
|
||||
case PowerupManager::POWERUP_PLUNGER: f = new Plunger(kart); break;
|
||||
case PowerupManager::POWERUP_CAKE: f = new Cake(kart); break;
|
||||
case PowerupManager::POWERUP_RUBBERBALL: f = new RubberBall(kart);
|
||||
case PowerupManager::POWERUP_RUBBERBALL: f = new RubberBall(kart);
|
||||
break;
|
||||
default: return NULL;
|
||||
}
|
||||
|
@ -48,10 +48,10 @@ float RubberBall::m_time_between_balls;
|
||||
RubberBall::RubberBall(AbstractKart *kart)
|
||||
: Flyable(kart, PowerupManager::POWERUP_RUBBERBALL, 0.0f /* mass */),
|
||||
TrackSector()
|
||||
{
|
||||
// For debugging purpose: pre-fix each debugging line with the id of
|
||||
{
|
||||
// For debugging purpose: pre-fix each debugging line with the id of
|
||||
// the ball so that it's easy to collect all debug output for one
|
||||
// particular ball only.
|
||||
// particular ball only.
|
||||
m_next_id++;
|
||||
m_id = m_next_id;
|
||||
|
||||
@ -59,13 +59,13 @@ RubberBall::RubberBall(AbstractKart *kart)
|
||||
// has to do it earlier than that.
|
||||
setDoTerrainInfo(false);
|
||||
float forw_offset = 0.5f*kart->getKartLength() + m_extend.getZ()*0.5f+5.0f;
|
||||
|
||||
|
||||
createPhysics(forw_offset, btVector3(0.0f, 0.0f, m_speed*2),
|
||||
new btSphereShape(0.5f*m_extend.getY()),
|
||||
-70.0f /*gravity*/,
|
||||
new btSphereShape(0.5f*m_extend.getY()),
|
||||
-70.0f /*gravity*/,
|
||||
true /*rotates*/);
|
||||
|
||||
// Do not adjust the up velocity
|
||||
// Do not adjust the up velocity
|
||||
setAdjustUpVelocity(false);
|
||||
m_max_lifespan = 9999;
|
||||
m_target = NULL;
|
||||
@ -79,7 +79,7 @@ RubberBall::RubberBall(AbstractKart *kart)
|
||||
m_ping_sfx = sfx_manager->createSoundSource("ball_bounce");
|
||||
// Just init the previoux coordinates with some value that's not getXYZ()
|
||||
m_previous_xyz = m_owner->getXYZ();
|
||||
m_previous_height = 2.0f; //
|
||||
m_previous_height = 2.0f; //
|
||||
// A negative value indicates that the timer is not active
|
||||
m_delete_timer = -1.0f;
|
||||
m_tunnel_count = 0;
|
||||
@ -105,9 +105,9 @@ RubberBall::~RubberBall()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sets up the control points for the interpolation. The parameter contains
|
||||
* the coordinates of the first control points (i.e. a control point that
|
||||
* influences the direction the ball is flying only, not the actual
|
||||
* coordinates - see details about Catmull-Rom splines). This function will
|
||||
* the coordinates of the first control points (i.e. a control point that
|
||||
* influences the direction the ball is flying only, not the actual
|
||||
* coordinates - see details about Catmull-Rom splines). This function will
|
||||
* then set the 2nd control point to be the current coordinates of the ball,
|
||||
* and find two more appropriate control points for a smooth movement.
|
||||
* \param xyz Coordinates of the first control points.
|
||||
@ -117,12 +117,12 @@ void RubberBall::initializeControlPoints(const Vec3 &xyz)
|
||||
m_control_points[0] = xyz;
|
||||
m_control_points[1] = getXYZ();
|
||||
m_last_aimed_graph_node = getSuccessorToHitTarget(getCurrentGraphNode());
|
||||
// This call defined m_control_points[3], but also sets a new
|
||||
// This call defined m_control_points[3], but also sets a new
|
||||
// m_last_aimed_graph_node, which is further away from the current point,
|
||||
// which avoids the problem that the ball might go too quickly to the
|
||||
// which avoids the problem that the ball might go too quickly to the
|
||||
// left or right when firing the ball off track.
|
||||
getNextControlPoint();
|
||||
m_control_points[2] =
|
||||
m_control_points[2] =
|
||||
QuadGraph::get()->getQuadOfNode(m_last_aimed_graph_node).getCenter();
|
||||
|
||||
// This updates m_last_aimed_graph_node, and sets m_control_points[3]
|
||||
@ -141,18 +141,18 @@ void RubberBall::computeTarget()
|
||||
// FIXME: what does the rubber ball do in case of battle mode??
|
||||
if(!world) return;
|
||||
|
||||
for(unsigned int p = race_manager->getFinishedKarts()+1;
|
||||
for(unsigned int p = race_manager->getFinishedKarts()+1;
|
||||
p < world->getNumKarts()+1; p++)
|
||||
{
|
||||
m_target = world->getKartAtPosition(p);
|
||||
if(!m_target->isEliminated() && !m_target->hasFinishedRace())
|
||||
{
|
||||
// If the firing kart itself is the first kart (that is
|
||||
// If the firing kart itself is the first kart (that is
|
||||
// still driving), prepare to remove the rubber ball
|
||||
if(m_target==m_owner && m_delete_timer < 0)
|
||||
{
|
||||
#ifdef PRINT_BALL_REMOVE_INFO
|
||||
Log::debug("RubberBall",
|
||||
Log::debug("RubberBall",
|
||||
"ball %d removed because owner is target.", m_id);
|
||||
#endif
|
||||
m_delete_timer = m_st_delete_time;
|
||||
@ -190,7 +190,7 @@ unsigned int RubberBall::getSuccessorToHitTarget(unsigned int node_index,
|
||||
// FIXME: what does the rubber ball do in case of battle mode??
|
||||
if(lin_world)
|
||||
{
|
||||
unsigned int sect =
|
||||
unsigned int sect =
|
||||
lin_world->getSectorForKart(m_target);
|
||||
succ = QuadGraph::get()->getNode(node_index).getSuccessorToReach(sect);
|
||||
}
|
||||
@ -203,7 +203,7 @@ unsigned int RubberBall::getSuccessorToHitTarget(unsigned int node_index,
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determines the next control points to aim at. The control points must not
|
||||
* be too close to each other (since otherwise the interpolation is still
|
||||
* not smooth enough), so keep on picking graph nodes till the distance
|
||||
* not smooth enough), so keep on picking graph nodes till the distance
|
||||
* between the currently aimed at graph node and the next one is above a
|
||||
* certain threshold. It uses getSuccessorToHitTarget to determine which
|
||||
* graph node to select.
|
||||
@ -227,14 +227,14 @@ void RubberBall::getNextControlPoint()
|
||||
|
||||
m_last_aimed_graph_node = next;
|
||||
m_length_cp_2_3 = dist;
|
||||
const Quad &quad =
|
||||
const Quad &quad =
|
||||
QuadGraph::get()->getQuadOfNode(m_last_aimed_graph_node);
|
||||
m_control_points[3] = quad.getCenter();
|
||||
} // getNextControlPoint
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialises this object with data from the power.xml file (this is a static
|
||||
* function).
|
||||
* function).
|
||||
* \param node XML Node
|
||||
* \param rubberball The rubber ball mesh
|
||||
*/
|
||||
@ -259,7 +259,7 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *rubberball)
|
||||
"No squash-duration specified for rubber ball.");
|
||||
if(!node.get("squash-slowdown", &m_st_squash_slowdown))
|
||||
Log::warn("powerup", "No squash-slowdown specified for rubber ball.");
|
||||
if(!node.get("min-interpolation-distance",
|
||||
if(!node.get("min-interpolation-distance",
|
||||
&m_st_min_interpolation_distance))
|
||||
Log::warn("powerup", "No min-interpolation-distance specified "
|
||||
"for rubber ball.");
|
||||
@ -272,7 +272,7 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *rubberball)
|
||||
Log::warn("powerup", "No target-max-angle specified for rubber ball.");
|
||||
m_st_target_max_angle *= DEGREE_TO_RAD;
|
||||
if(!node.get("max-height-difference", &m_st_max_height_difference))
|
||||
Log::warn("powerup",
|
||||
Log::warn("powerup",
|
||||
"No max-height-difference specified for rubber ball.");
|
||||
if(!node.get("fast-ping-distance", &m_st_fast_ping_distance))
|
||||
Log::warn("powerup",
|
||||
@ -282,16 +282,16 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *rubberball)
|
||||
"Ping-distance is smaller than target distance.\n"
|
||||
"That should not happen, but is ignored for now.");
|
||||
if(!node.get("early-target-factor", &m_st_early_target_factor))
|
||||
Log::warn("powerup",
|
||||
Log::warn("powerup",
|
||||
"No early-target-factor specified for rubber ball.");
|
||||
if(!node.get("time-between-balls", &m_time_between_balls))
|
||||
Log::warn("powerup",
|
||||
Log::warn("powerup",
|
||||
"No time-between-balls specified for rubber ball.");
|
||||
Flyable::init(node, rubberball, PowerupManager::POWERUP_RUBBERBALL);
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Picks a random message to be displayed when a kart is hit by the
|
||||
/** Picks a random message to be displayed when a kart is hit by the
|
||||
* rubber ball.
|
||||
* \param The kart that was hit (ignored here).
|
||||
* \returns The string to display.
|
||||
@ -302,10 +302,10 @@ const core::stringw RubberBall::getHitString(const AbstractKart *kart) const
|
||||
RandomGenerator r;
|
||||
switch (r.get(COUNT))
|
||||
{
|
||||
//I18N: shown when a player is hit by a rubber ball. %1 is the
|
||||
//I18N: shown when a player is hit by a rubber ball. %1 is the
|
||||
// attacker, %0 is the victim.
|
||||
case 0: return _LTR("%s is being bounced around.");
|
||||
//I18N: shown when a player is hit by a rubber ball. %1 is the
|
||||
//I18N: shown when a player is hit by a rubber ball. %1 is the
|
||||
// attacker, %0 is the victim.
|
||||
case 1: return _LTR("Fetch the ball, %0!");
|
||||
default:assert(false); return L""; // avoid compiler warning
|
||||
@ -313,7 +313,7 @@ const core::stringw RubberBall::getHitString(const AbstractKart *kart) const
|
||||
} // getHitString
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updates the rubber ball.
|
||||
/** Updates the rubber ball.
|
||||
* \param dt Time step size.
|
||||
* \returns True if the rubber ball should be removed.
|
||||
*/
|
||||
@ -337,7 +337,7 @@ bool RubberBall::updateAndDelete(float dt)
|
||||
computeTarget();
|
||||
updateDistanceToTarget();
|
||||
|
||||
// Determine the new position. This new position is only temporary,
|
||||
// Determine the new position. This new position is only temporary,
|
||||
// since it still needs to be adjusted for the height of the terrain.
|
||||
Vec3 next_xyz;
|
||||
if(m_aiming_at_target)
|
||||
@ -357,10 +357,10 @@ bool RubberBall::updateAndDelete(float dt)
|
||||
float vertical_offset = close_to_ground ? 4.0f : 2.0f;
|
||||
// Note that at this stage getHoT still reports the height at
|
||||
// the previous location (since TerrainInfo wasn't updated). On
|
||||
// the other hand, we can't update TerrainInfo without having
|
||||
// the other hand, we can't update TerrainInfo without having
|
||||
// at least a good estimation of the height.
|
||||
next_xyz.setY(getHoT() + vertical_offset);
|
||||
// Update height of terrain (which isn't done as part of
|
||||
// Update height of terrain (which isn't done as part of
|
||||
// Flyable::update for rubber balls.
|
||||
TerrainInfo::update(next_xyz);
|
||||
|
||||
@ -373,7 +373,7 @@ bool RubberBall::updateAndDelete(float dt)
|
||||
m_id, next_xyz.getX(), next_xyz.getY(), next_xyz.getZ(), height, new_y, getHoT());
|
||||
|
||||
// No need to check for terrain height if the ball is low to the ground
|
||||
if(height > 0.5f)
|
||||
if(height > 0.5f)
|
||||
{
|
||||
float terrain_height = getMaxTerrainHeight(vertical_offset)
|
||||
- m_extend.getY();
|
||||
@ -437,7 +437,7 @@ void RubberBall::moveTowardsTarget(Vec3 *next_xyz, float dt)
|
||||
core::vector2df old_2d(old_vec.getX(), old_vec.getZ());
|
||||
if(old_2d.getLengthSQ()==0.0f) old_2d.Y = 1.0f;
|
||||
old_2d.normalize();
|
||||
old_2d.rotateBy( RAD_TO_DEGREE * dt
|
||||
old_2d.rotateBy( RAD_TO_DEGREE * dt
|
||||
* (angle > 0 ? m_st_target_max_angle
|
||||
: -m_st_target_max_angle));
|
||||
next_xyz->setX(getXYZ().getX() + old_2d.X*dt*m_speed);
|
||||
@ -449,7 +449,7 @@ void RubberBall::moveTowardsTarget(Vec3 *next_xyz, float dt)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Uses Hermite splines (Catmull-Rom) to interpolate the position of the
|
||||
* ball between the control points. If the next point would be outside of
|
||||
* the spline between control_points[1] and [2], a new control point is
|
||||
* the spline between control_points[1] and [2], a new control point is
|
||||
* added.
|
||||
* \param next_xyz Returns the new position.
|
||||
* \param The time step size.
|
||||
@ -472,10 +472,10 @@ void RubberBall::interpolate(Vec3 *next_xyz, float dt)
|
||||
m_t -= 1.0f;
|
||||
}
|
||||
|
||||
*next_xyz = 0.5f * ((- m_control_points[0] + 3*m_control_points[1]
|
||||
*next_xyz = 0.5f * ((- m_control_points[0] + 3*m_control_points[1]
|
||||
-3*m_control_points[2] + m_control_points[3] )
|
||||
*m_t*m_t*m_t
|
||||
+ ( 2*m_control_points[0] -5*m_control_points[1]
|
||||
+ ( 2*m_control_points[0] -5*m_control_points[1]
|
||||
+4*m_control_points[2] - m_control_points[3])*m_t*m_t
|
||||
+ (- m_control_points[0] + m_control_points[2])*m_t
|
||||
+ 2*m_control_points[1] );
|
||||
@ -483,9 +483,9 @@ void RubberBall::interpolate(Vec3 *next_xyz, float dt)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Checks if the line from the previous ball position to the new position
|
||||
* hits something, which indicates that the ball is tunneling through. If
|
||||
* hits something, which indicates that the ball is tunneling through. If
|
||||
* this happens, the ball position is adjusted so that it is just before
|
||||
* the hit point. If tunneling happens four frames in a row the ball is
|
||||
* the hit point. If tunneling happens four frames in a row the ball is
|
||||
* considered stuck and explodes (e.g. the ball might try to tunnel through
|
||||
* a wall to get to a 'close' target. In this case the ball would not
|
||||
* move much anymore and be stuck).
|
||||
@ -501,12 +501,12 @@ bool RubberBall::checkTunneling()
|
||||
|
||||
if(material)
|
||||
{
|
||||
// If there are three consecutive tunnelling
|
||||
// If there are three consecutive tunnelling
|
||||
m_tunnel_count++;
|
||||
if(m_tunnel_count > 3)
|
||||
if(m_tunnel_count > 3)
|
||||
{
|
||||
#ifdef PRINT_BALL_REMOVE_INFO
|
||||
Log::debug("RubberBall",
|
||||
Log::debug("RubberBall",
|
||||
"Ball %d nearly tunneled at %f %f %f -> %f %f %f",
|
||||
m_id, m_previous_xyz.getX(),m_previous_xyz.getY(),
|
||||
m_previous_xyz.getZ(),
|
||||
@ -529,15 +529,15 @@ bool RubberBall::checkTunneling()
|
||||
} // checkTunneling
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updates the height of the rubber ball, and if necessary also adjusts the
|
||||
* maximum height of the ball depending on distance from the target. The
|
||||
/** Updates the height of the rubber ball, and if necessary also adjusts the
|
||||
* maximum height of the ball depending on distance from the target. The
|
||||
* height is decreased when the ball is getting closer to the target so it
|
||||
* hops faster and faster. This function modifies m_current_max_height.
|
||||
* \return Returns the new height of the ball.
|
||||
*/
|
||||
float RubberBall::updateHeight()
|
||||
{
|
||||
// When the ball hits the floor, we adjust maximum height and
|
||||
// When the ball hits the floor, we adjust maximum height and
|
||||
// interval so that the ball bounces faster when it is getting
|
||||
// closer to the target.
|
||||
if(m_height_timer>m_interval)
|
||||
@ -553,7 +553,7 @@ float RubberBall::updateHeight()
|
||||
{
|
||||
// Some experimental formulas
|
||||
m_current_max_height = 0.5f*sqrt(m_distance_to_target);
|
||||
// If the ball just missed the target, m_distance_to_target
|
||||
// If the ball just missed the target, m_distance_to_target
|
||||
// can be huge (close to track length) due to the order in
|
||||
// which a lost target is detected. Avoid this by clamping
|
||||
// m_current_max_height.
|
||||
@ -587,13 +587,13 @@ float RubberBall::updateHeight()
|
||||
} // updateHeight
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the maximum height of the terrain at the current point. While
|
||||
/** Returns the maximum height of the terrain at the current point. While
|
||||
* generall the height is arbitrary (a skybox is not part of the physics and
|
||||
* will therefore not be detected), it is important that a rubber ball does
|
||||
* will therefore not be detected), it is important that a rubber ball does
|
||||
* not end up on top of a tunnel.
|
||||
* \param vertical_offset A vertical offset which is added to the current
|
||||
* position of the kart in order to avoid tunneling effects (it could
|
||||
* happen that the raycast down find the track since it uses the
|
||||
* happen that the raycast down find the track since it uses the
|
||||
* vertical offset, while the raycast up would hit under the track
|
||||
* if the vertical offset is not used).
|
||||
* \returns The height (Y coordinate) of the next terrain element found by
|
||||
@ -621,7 +621,7 @@ void RubberBall::updateDistanceToTarget()
|
||||
const LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
|
||||
if(!world) return; // FIXME battle mode
|
||||
|
||||
float target_distance =
|
||||
float target_distance =
|
||||
world->getDistanceDownTrackForKart(m_target->getWorldKartId());
|
||||
float ball_distance = getDistanceFromStart();
|
||||
|
||||
@ -638,12 +638,12 @@ void RubberBall::updateDistanceToTarget()
|
||||
|
||||
float height_diff = fabsf(m_target->getXYZ().getY() - getXYZ().getY());
|
||||
|
||||
if(m_distance_to_target < m_st_fast_ping_distance &&
|
||||
if(m_distance_to_target < m_st_fast_ping_distance &&
|
||||
height_diff < m_st_max_height_difference)
|
||||
{
|
||||
m_fast_ping = true;
|
||||
}
|
||||
if(m_distance_to_target < m_st_target_distance &&
|
||||
if(m_distance_to_target < m_st_target_distance &&
|
||||
height_diff < m_st_max_height_difference)
|
||||
{
|
||||
m_aiming_at_target = true;
|
||||
@ -653,7 +653,7 @@ void RubberBall::updateDistanceToTarget()
|
||||
{
|
||||
// It appears that we have lost the target. It was within
|
||||
// the target distance, and now it isn't. That means either
|
||||
// the original target escaped, or perhaps that there is a
|
||||
// the original target escaped, or perhaps that there is a
|
||||
// new target. If the new distance is nearly the full track
|
||||
// length, assume that the rubber ball has overtaken the
|
||||
// original target, and start deleting it.
|
||||
@ -666,9 +666,9 @@ void RubberBall::updateDistanceToTarget()
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Otherwise (target disappeared, e.g. has finished the race or
|
||||
// was eliminated) we have to reset the control points, since
|
||||
// was eliminated) we have to reset the control points, since
|
||||
// it's likely that the ball is (after some time going directly
|
||||
// towards the target) far outside of the old control points.
|
||||
|
||||
@ -688,7 +688,7 @@ void RubberBall::updateDistanceToTarget()
|
||||
* hit earlier will only be flattened.
|
||||
* \params kart The kart hit (NULL if no kart was hit).
|
||||
* \params object The object that was hit (NULL if none).
|
||||
* \returns True if
|
||||
* \returns True if
|
||||
*/
|
||||
bool RubberBall::hit(AbstractKart* kart, PhysicalObject* object)
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ const wchar_t* getPlungerString()
|
||||
* root(!) of the graph. It's easier this way to get the right coordinates
|
||||
* than attaching it to the plunger or kart, and trying to find the other
|
||||
* coordinate.
|
||||
* \param plunger Pointer to the plunger (non const, since the rubber band
|
||||
* \param plunger Pointer to the plunger (non const, since the rubber band
|
||||
* can trigger an explosion)
|
||||
* \param kart Reference to the kart.
|
||||
*/
|
||||
@ -165,7 +165,7 @@ void RubberBand::update(float dt)
|
||||
{
|
||||
float force = m_owner->getKartProperties()->getRubberBandForce();
|
||||
Vec3 diff = m_end_position-k;
|
||||
|
||||
|
||||
// detach rubber band if kart gets very close to hit point
|
||||
if(m_attached_state==RB_TO_TRACK && diff.length2() < 10*10)
|
||||
{
|
||||
@ -175,13 +175,13 @@ void RubberBand::update(float dt)
|
||||
m_plunger->setKeepAlive(0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
diff.normalize(); // diff can't be zero here
|
||||
m_owner->getBody()->applyCentralForce(diff*force);
|
||||
m_owner->increaseMaxSpeed(MaxSpeed::MS_INCREASE_RUBBER,
|
||||
m_owner->getKartProperties()->getRubberBandSpeedIncrease(),
|
||||
/*engine_force*/ 0.0f,
|
||||
/*duration*/0.1f,
|
||||
/*engine_force*/ 0.0f,
|
||||
/*duration*/0.1f,
|
||||
m_owner->getKartProperties()->getRubberBandFadeOutTime());
|
||||
if(m_attached_state==RB_TO_KART)
|
||||
m_hit_kart->getBody()->applyCentralForce(diff*(-force));
|
||||
@ -208,7 +208,7 @@ void RubberBand::checkForHit(const Vec3 &k, const Vec3 &p)
|
||||
m_owner->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = 0;
|
||||
|
||||
// Do the raycast
|
||||
World::getWorld()->getPhysics()->getPhysicsWorld()->rayTest(k, p,
|
||||
World::getWorld()->getPhysics()->getPhysicsWorld()->rayTest(k, p,
|
||||
ray_callback);
|
||||
// Reset collision groups
|
||||
m_plunger->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = old_plunger_group;
|
||||
|
@ -51,10 +51,10 @@
|
||||
* \param attachment The attachment instance where the swatter is attached to.
|
||||
* \param kart The kart to which the swatter is attached.
|
||||
* \param was_bomb True if the kart had a bomb as attachment.
|
||||
* \param bomb_scene_node The scene node of the bomb (i.e. the previous
|
||||
* \param bomb_scene_node The scene node of the bomb (i.e. the previous
|
||||
* attachment scene node).
|
||||
*/
|
||||
Swatter::Swatter(AbstractKart *kart, bool was_bomb,
|
||||
Swatter::Swatter(AbstractKart *kart, bool was_bomb,
|
||||
scene::ISceneNode* bomb_scene_node)
|
||||
: AttachmentPlugin(kart)
|
||||
{
|
||||
@ -63,14 +63,14 @@ Swatter::Swatter(AbstractKart *kart, bool was_bomb,
|
||||
m_removing_bomb = was_bomb;
|
||||
m_bomb_scene_node = bomb_scene_node;
|
||||
m_swat_bomb_frame = 0.0f;
|
||||
|
||||
|
||||
// Setup the node
|
||||
m_scene_node = kart->getAttachment()->getNode();
|
||||
m_scene_node->setPosition(SWAT_POS_OFFSET);
|
||||
|
||||
|
||||
if (m_removing_bomb)
|
||||
{
|
||||
m_scene_node->setMesh(irr_driver->getAnimatedMesh(
|
||||
m_scene_node->setMesh(irr_driver->getAnimatedMesh(
|
||||
file_manager->getModelFile("swatter_anim2.b3d") ) );
|
||||
m_scene_node->setRotation(core::vector3df(0.0, -180.0, 0.0));
|
||||
m_scene_node->setAnimationSpeed(0.9f);
|
||||
@ -79,9 +79,9 @@ Swatter::Swatter(AbstractKart *kart, bool was_bomb,
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scene_node->setAnimationSpeed(0);
|
||||
m_scene_node->setAnimationSpeed(0);
|
||||
}
|
||||
|
||||
|
||||
if (kart->getIdent() == "nolok")
|
||||
m_swat_sound = sfx_manager->createSoundSource("hammer");
|
||||
else
|
||||
@ -116,9 +116,9 @@ bool Swatter::updateAndTestFinished(float dt)
|
||||
{
|
||||
m_swat_bomb_frame += dt*25.0f;
|
||||
m_scene_node->setRotation(core::vector3df(0.0, -180.0, 0.0));
|
||||
|
||||
|
||||
m_scene_node->setCurrentFrame(m_swat_bomb_frame);
|
||||
|
||||
|
||||
if (m_swat_bomb_frame >= 32.5f && m_bomb_scene_node != NULL)
|
||||
{
|
||||
m_bomb_scene_node->setPosition(m_bomb_scene_node->getPosition() +
|
||||
@ -126,7 +126,7 @@ bool Swatter::updateAndTestFinished(float dt)
|
||||
m_bomb_scene_node->setRotation(m_bomb_scene_node->getRotation() +
|
||||
core::vector3df(-dt*15.0f, 0.0f, 0.0f) );
|
||||
}
|
||||
|
||||
|
||||
if (m_swat_bomb_frame >= m_scene_node->getEndFrame())
|
||||
{
|
||||
return true;
|
||||
@ -139,10 +139,10 @@ bool Swatter::updateAndTestFinished(float dt)
|
||||
m_bomb_scene_node = NULL;
|
||||
}
|
||||
} // bom_frame > 35
|
||||
|
||||
|
||||
return false;
|
||||
} // if removing bomb
|
||||
|
||||
|
||||
switch(m_animation_phase)
|
||||
{
|
||||
case SWATTER_AIMING:
|
||||
@ -152,10 +152,10 @@ bool Swatter::updateAndTestFinished(float dt)
|
||||
if(!m_target) break;
|
||||
|
||||
// Is the target too near?
|
||||
float dist_to_target2 =
|
||||
float dist_to_target2 =
|
||||
(m_target->getXYZ()- Vec3(m_scene_node->getAbsolutePosition()))
|
||||
.length2();
|
||||
float min_dist2
|
||||
float min_dist2
|
||||
= m_kart->getKartProperties()->getSwatterDistance2();
|
||||
if(dist_to_target2 < min_dist2)
|
||||
{
|
||||
@ -179,7 +179,7 @@ bool Swatter::updateAndTestFinished(float dt)
|
||||
// Did we just finish the first part of the movement?
|
||||
if(current_frame >= middle_frame)
|
||||
{
|
||||
// Squash the karts and items around and
|
||||
// Squash the karts and items around and
|
||||
// change the current phase
|
||||
squashThingsAround();
|
||||
m_animation_phase = SWATTER_FROM_TARGET;
|
||||
@ -206,7 +206,7 @@ void Swatter::onAnimationEnd()
|
||||
} // onAnimationEnd
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determine the nearest kart or item and update the current target
|
||||
/** Determine the nearest kart or item and update the current target
|
||||
* accordingly.
|
||||
*/
|
||||
void Swatter::chooseTarget()
|
||||
@ -225,7 +225,7 @@ void Swatter::chooseTarget()
|
||||
// don't squash an already hurt kart
|
||||
if (kart->isInvulnerable() || kart->isSquashed())
|
||||
continue;
|
||||
|
||||
|
||||
float dist2 = (kart->getXYZ()-m_kart->getXYZ()).length2();
|
||||
if(dist2<min_dist2)
|
||||
{
|
||||
@ -237,7 +237,7 @@ void Swatter::chooseTarget()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** If there is a current target, point in its direction, otherwise adopt the
|
||||
/** If there is a current target, point in its direction, otherwise adopt the
|
||||
* default position. */
|
||||
void Swatter::pointToTarget()
|
||||
{
|
||||
@ -247,7 +247,7 @@ void Swatter::pointToTarget()
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3 swatter_to_target = m_target->getXYZ()
|
||||
Vec3 swatter_to_target = m_target->getXYZ()
|
||||
-Vec3(m_scene_node->getAbsolutePosition());
|
||||
float dy = -swatter_to_target.getZ();
|
||||
float dx = swatter_to_target.getX();
|
||||
@ -259,7 +259,7 @@ void Swatter::pointToTarget()
|
||||
} // pointToTarget
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Squash karts or items that are around the end position (determined using
|
||||
/** Squash karts or items that are around the end position (determined using
|
||||
* a joint) of the swatter.
|
||||
*/
|
||||
void Swatter::squashThingsAround()
|
||||
@ -277,7 +277,7 @@ void Swatter::squashThingsAround()
|
||||
|
||||
m_swat_sound->position(swatter_pos);
|
||||
m_swat_sound->play();
|
||||
|
||||
|
||||
// Squash karts around
|
||||
for(unsigned int i=0; i<world->getNumKarts(); i++)
|
||||
{
|
||||
@ -288,13 +288,13 @@ void Swatter::squashThingsAround()
|
||||
// don't swat an already hurt kart
|
||||
if (kart->isInvulnerable() || kart->isSquashed())
|
||||
continue;
|
||||
|
||||
|
||||
float dist2 = (kart->getXYZ()-swatter_pos).length2();
|
||||
|
||||
if(dist2 >= min_dist2) continue; // too far away, ignore this kart
|
||||
|
||||
kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());
|
||||
|
||||
|
||||
RaceGUIBase* gui = World::getWorld()->getRaceGUI();
|
||||
irr::core::stringw hit_message =
|
||||
StringUtils::insertValues(getHitString(kart),
|
||||
@ -304,7 +304,7 @@ void Swatter::squashThingsAround()
|
||||
if(hit_message.size()>0)
|
||||
gui->addMessage(translations->fribidize(hit_message), NULL, 3.0f,
|
||||
video::SColor(255, 255, 255, 255), false);
|
||||
|
||||
|
||||
if (kart->getAttachment()->getType()==Attachment::ATTACH_BOMB)
|
||||
{ // make bomb explode
|
||||
kart->getAttachment()->update(10000);
|
||||
@ -323,7 +323,7 @@ void Swatter::squashThingsAround()
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Picks a random message to be displayed when a kart is hit by a swatter
|
||||
/** Picks a random message to be displayed when a kart is hit by a swatter
|
||||
* \param kart The kart that was hit.
|
||||
* \returns The string to display.
|
||||
*/
|
||||
|
@ -26,14 +26,14 @@
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
/** Creates a kart.
|
||||
/** Creates a kart.
|
||||
* \param ident The identifier of the kart.
|
||||
* \param world_kart_id The world index of this kart.
|
||||
* \param position The start position of the kart (1<=position<=n).
|
||||
* \param init_transform The start position of the kart.
|
||||
*/
|
||||
AbstractKart::AbstractKart(const std::string& ident,
|
||||
int world_kart_id, int position,
|
||||
AbstractKart::AbstractKart(const std::string& ident,
|
||||
int world_kart_id, int position,
|
||||
const btTransform& init_transform)
|
||||
: Moveable()
|
||||
{
|
||||
@ -41,12 +41,12 @@ AbstractKart::AbstractKart(const std::string& ident,
|
||||
m_kart_properties = kart_properties_manager->getKart(ident);
|
||||
m_kart_animation = NULL;
|
||||
assert(m_kart_properties != NULL);
|
||||
|
||||
|
||||
// We have to take a copy of the kart model, since otherwise
|
||||
// the animations will be mixed up (i.e. different instances of
|
||||
// the same model will set different animation frames).
|
||||
// Technically the mesh in m_kart_model needs to be grab'ed and
|
||||
// released when the kart is deleted, but since the original
|
||||
// released when the kart is deleted, but since the original
|
||||
// kart_model is stored in the kart_properties all the time,
|
||||
// there is no risk of a mesh being deleted to early.
|
||||
m_kart_model = m_kart_properties->getKartModelCopy();
|
||||
@ -76,9 +76,9 @@ void AbstractKart::reset()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns a name to be displayed for this kart. */
|
||||
const wchar_t* AbstractKart::getName() const
|
||||
{
|
||||
return m_kart_properties->getName();
|
||||
const wchar_t* AbstractKart::getName() const
|
||||
{
|
||||
return m_kart_properties->getName();
|
||||
} // getName;
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns a unique identifier for this kart (name of the directory the
|
||||
@ -88,24 +88,24 @@ const std::string& AbstractKart::getIdent() const
|
||||
return m_kart_properties->getIdent();
|
||||
} // getIdent
|
||||
// ----------------------------------------------------------------------------
|
||||
bool AbstractKart::isWheeless() const
|
||||
bool AbstractKart::isWheeless() const
|
||||
{
|
||||
return m_kart_model->getWheelModel(0)==NULL;
|
||||
} // isWheeless
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sets a new kart animation. This function should either be called to
|
||||
* remove an existing kart animation (ka=NULL), or to set a new kart
|
||||
/** Sets a new kart animation. This function should either be called to
|
||||
* remove an existing kart animation (ka=NULL), or to set a new kart
|
||||
* animation, in which case the current kart animation must be NULL.
|
||||
* \param ka The new kart animation, or NULL if the current kart animation
|
||||
* is to be stopped.
|
||||
*/
|
||||
void AbstractKart::setKartAnimation(AbstractKartAnimation *ka)
|
||||
void AbstractKart::setKartAnimation(AbstractKartAnimation *ka)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if( ( (ka!=NULL) ^ (m_kart_animation!=NULL) ) ==0)
|
||||
{
|
||||
if(ka) Log::debug("Abstract_Kart", "Setting kart animation to '%s'.",
|
||||
if(ka) Log::debug("Abstract_Kart", "Setting kart animation to '%s'.",
|
||||
ka->getName().c_str());
|
||||
else Log::debug("Abstract_Kart", "Setting kart animation to NULL.");
|
||||
if(m_kart_animation) Log::info("Abstract_Kart", "Current kart"
|
||||
@ -118,5 +118,5 @@ void AbstractKart::setKartAnimation(AbstractKartAnimation *ka)
|
||||
// is set, or there is a current animation, then it must be set to 0. This
|
||||
// makes sure that the calling logic of this function is correct.
|
||||
assert( (ka!=NULL) ^ (m_kart_animation!=NULL) );
|
||||
m_kart_animation = ka;
|
||||
m_kart_animation = ka;
|
||||
} // setKartAnimation
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "modes/world.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
|
||||
AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
|
||||
AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
|
||||
const std::string &name)
|
||||
{
|
||||
m_timer = 0;
|
||||
|
@ -32,7 +32,7 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo)
|
||||
{
|
||||
m_curve = new AnimationBase(ipo);
|
||||
m_timer = ipo->getEndTime();
|
||||
|
||||
|
||||
// Compute the delta between the kart position and the start of the curve.
|
||||
// This delta is rotated with the kart and added to the interpolated curve
|
||||
// position to get the actual kart position during the animation.
|
||||
@ -54,7 +54,7 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo)
|
||||
btMatrix3x3 m(q);
|
||||
m_delta = m * m_delta;
|
||||
|
||||
// The previous call to m_curve->update will set the internal timer
|
||||
// The previous call to m_curve->update will set the internal timer
|
||||
// of the curve to dt. Reset it to 0 to make sure the timer is in
|
||||
// synch with the timer of the CanonAnimation
|
||||
m_curve->reset();
|
||||
@ -67,7 +67,7 @@ CannonAnimation::~CannonAnimation()
|
||||
|
||||
btTransform pos;
|
||||
pos.setOrigin(m_kart->getXYZ());
|
||||
pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f),
|
||||
pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f),
|
||||
m_kart->getHeading() ));
|
||||
|
||||
m_kart->getBody()->setCenterOfMassTransform(pos);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user