Merge remote-tracking branch 'origin/master' into soft-physics-landing
This commit is contained in:
@@ -171,7 +171,7 @@ endif()
|
||||
|
||||
|
||||
# Set some compiler options
|
||||
if(UNIX)
|
||||
if(UNIX OR MINGW)
|
||||
add_definitions(-Wall)
|
||||
endif()
|
||||
|
||||
@@ -181,6 +181,9 @@ if(WIN32)
|
||||
|
||||
# And shut up about unsafe stuff
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# VS will automatically add NDEBUG for release mode, but only _DEBUG in debug mode.
|
||||
# Since STK uses DEBUG, this is added for debug compilation only:
|
||||
set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUG)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<particles emitter="sphere" radius="5">
|
||||
<particles emitter="sphere" radius="2">
|
||||
|
||||
<spreading angle="45" />
|
||||
<spreading angle="12" />
|
||||
|
||||
<velocity x="0.000"
|
||||
y="0.005"
|
||||
@@ -18,8 +18,8 @@
|
||||
max="2000" />
|
||||
|
||||
<!-- Size of the particles -->
|
||||
<size min="4.0"
|
||||
max="7.2"
|
||||
<size min="2.0"
|
||||
max="3.2"
|
||||
x-increase-factor="2.6"
|
||||
y-increase-factor="2.6" />
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<particles emitter="box" box_x="12.0" box_y="0.5" box_z="12.0">
|
||||
<particles emitter="box" box_x="3.0" box_y="0.5" box_z="3.0">
|
||||
|
||||
<spreading angle="24" />
|
||||
<spreading angle="45" />
|
||||
|
||||
<velocity x="0.000"
|
||||
y="0.005"
|
||||
y="0.001"
|
||||
z="0.000" />
|
||||
|
||||
<material file="waterparticles.png" />
|
||||
|
||||
<!-- Amount of particles emitted per second -->
|
||||
<rate min="5"
|
||||
max="20" />
|
||||
<rate min="1"
|
||||
max="6" />
|
||||
|
||||
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
|
||||
<lifetime min="1000"
|
||||
|
||||
@@ -9,7 +9,7 @@ endif()
|
||||
|
||||
add_library(glew STATIC
|
||||
include/GL/glew.h include/GL/glxew.h include/GL/wglew.h
|
||||
src/glew.c src/glewinfo.c src/visualinfo.c
|
||||
src/glew.c src/glewinfo.c
|
||||
)
|
||||
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,8 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound, const char
|
||||
{
|
||||
// short emision time, explosion, not constant flame
|
||||
m_remaining_time = burst_time;
|
||||
|
||||
m_emission_frames = 0;
|
||||
|
||||
ParticleKindManager* pkm = ParticleKindManager::get();
|
||||
ParticleKind* particles = pkm->getParticles(particle_file);
|
||||
m_emitter = new ParticleEmitter(particles, coord, NULL);
|
||||
@@ -67,6 +68,7 @@ bool Explosion::updateAndDelete(float dt)
|
||||
// so no need to save the result of the update call.
|
||||
HitSFX::updateAndDelete(dt);
|
||||
|
||||
m_emission_frames++;
|
||||
m_remaining_time -= dt;
|
||||
|
||||
if (m_remaining_time < 0.0f && m_remaining_time >= -explosion_time)
|
||||
@@ -77,15 +79,14 @@ bool Explosion::updateAndDelete(float dt)
|
||||
node->getMaterial(0).AmbientColor.setGreen(intensity);
|
||||
node->getMaterial(0).DiffuseColor.setGreen(intensity);
|
||||
node->getMaterial(0).EmissiveColor.setGreen(intensity);
|
||||
|
||||
|
||||
node->getMaterial(0).AmbientColor.setBlue(intensity);
|
||||
node->getMaterial(0).DiffuseColor.setBlue(intensity);
|
||||
node->getMaterial(0).EmissiveColor.setBlue(intensity);
|
||||
|
||||
|
||||
node->getMaterial(0).AmbientColor.setRed(intensity);
|
||||
node->getMaterial(0).DiffuseColor.setRed(intensity);
|
||||
node->getMaterial(0).EmissiveColor.setRed(intensity);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -97,9 +98,14 @@ bool Explosion::updateAndDelete(float dt)
|
||||
// object is removed.
|
||||
if (m_remaining_time > -explosion_time)
|
||||
{
|
||||
// Stop the emitter and wait a little while for all particles to have time to fade out
|
||||
m_emitter->getNode()->getEmitter()->setMinParticlesPerSecond(0);
|
||||
m_emitter->getNode()->getEmitter()->setMaxParticlesPerSecond(0);
|
||||
// if framerate is very low, emit for at least a few frames, in case
|
||||
// burst time is lower than the time of 1 frame
|
||||
if (m_emission_frames > 2)
|
||||
{
|
||||
// Stop the emitter and wait a little while for all particles to have time to fade out
|
||||
m_emitter->getNode()->getEmitter()->setMinParticlesPerSecond(0);
|
||||
m_emitter->getNode()->getEmitter()->setMaxParticlesPerSecond(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ class Vec3;
|
||||
class SFXBase;
|
||||
class ParticleEmitter;
|
||||
|
||||
const float explosion_time = 1.5f;
|
||||
const float explosion_time = 2.0f;
|
||||
|
||||
/**
|
||||
* \ingroup graphics
|
||||
@@ -41,6 +41,7 @@ class Explosion : public HitSFX
|
||||
{
|
||||
private:
|
||||
float m_remaining_time;
|
||||
int m_emission_frames;
|
||||
ParticleEmitter* m_emitter;
|
||||
|
||||
public:
|
||||
|
||||
@@ -434,6 +434,8 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predic
|
||||
clone->recalculateBoundingBox();
|
||||
if (calculateTangents)
|
||||
recalculateTangents(clone, recalculateNormals, smooth, angleWeighted);
|
||||
|
||||
irr_driver->removeMeshFromCache(mesh);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -1512,13 +1512,13 @@ void Skin::drawIconButton(const core::recti &rect, Widget* widget,
|
||||
SColor(100,255,255,255),
|
||||
SColor(100,255,255,255) };
|
||||
core::recti r(0,0,icon_widget->m_texture_w, icon_widget->m_texture_h);
|
||||
draw2DImage(icon_widget->m_texture, sized_rect,
|
||||
draw2DImage(icon_widget->getTexture(), sized_rect,
|
||||
r, 0 /* no clipping */, colors,
|
||||
true /* alpha */);
|
||||
}
|
||||
else
|
||||
{
|
||||
video::ITexture* t = icon_widget->m_texture;
|
||||
const video::ITexture* t = icon_widget->getTexture();
|
||||
|
||||
const bool mouseInside =
|
||||
rect.isPointInside(irr_driver->getDevice()->getCursorControl()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
@@ -53,10 +54,14 @@ DynamicRibbonWidget::DynamicRibbonWidget(const bool combo, const bool multi_row)
|
||||
m_selected_item[0] = 0; // only player 0 has a selection by default
|
||||
|
||||
m_item_count_hint = 0;
|
||||
|
||||
m_font = GUIEngine::getFont()->getHollowCopy();
|
||||
m_max_label_width = 0;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
DynamicRibbonWidget::~DynamicRibbonWidget()
|
||||
{
|
||||
m_font->drop();
|
||||
if (m_animated_contents)
|
||||
{
|
||||
GUIEngine::needsUpdate.remove(this);
|
||||
@@ -379,6 +384,13 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
ribbon->m_properties[PROP_ID] = name.str();
|
||||
ribbon->m_event_handler = this;
|
||||
|
||||
// calculate font size
|
||||
if (m_col_amount > 0)
|
||||
{
|
||||
m_font->setScale(GUIEngine::getFont()->getScale() *
|
||||
getFontScale((ribbon->m_w / m_col_amount) - 30));
|
||||
}
|
||||
|
||||
// add columns
|
||||
for (int i=0; i<m_col_amount; i++)
|
||||
{
|
||||
@@ -392,6 +404,7 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
icon->m_properties[PROP_HEIGHT] = m_properties[PROP_CHILD_HEIGHT];
|
||||
icon->m_w = atoi(icon->m_properties[PROP_WIDTH].c_str());
|
||||
icon->m_h = atoi(icon->m_properties[PROP_HEIGHT].c_str());
|
||||
icon->setLabelFont(m_font);
|
||||
|
||||
// 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)
|
||||
@@ -438,14 +451,14 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
assert(childrenCount == (int)m_items.size());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void DynamicRibbonWidget::addItem( const irr::core::stringw& user_name, const std::string& code_name,
|
||||
const std::string& image_file, const unsigned int badges,
|
||||
IconButtonWidget::IconPathType image_path_type)
|
||||
{
|
||||
ItemDescription desc;
|
||||
desc.m_user_name = user_name;
|
||||
desc.m_user_name = getUserName(user_name);
|
||||
desc.m_code_name = code_name;
|
||||
desc.m_sshot_file = image_file;
|
||||
desc.m_badges = badges;
|
||||
@@ -453,6 +466,8 @@ void DynamicRibbonWidget::addItem( const irr::core::stringw& user_name, const st
|
||||
desc.m_image_path_type = image_path_type;
|
||||
|
||||
m_items.push_back(desc);
|
||||
|
||||
setLabelSize(desc.m_user_name);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -462,7 +477,7 @@ void DynamicRibbonWidget::addAnimatedItem( const irr::core::stringw& user_name,
|
||||
const unsigned int badges, IconButtonWidget::IconPathType image_path_type )
|
||||
{
|
||||
ItemDescription desc;
|
||||
desc.m_user_name = user_name;
|
||||
desc.m_user_name = getUserName(user_name);
|
||||
desc.m_code_name = code_name;
|
||||
desc.m_all_images = image_files;
|
||||
desc.m_badges = badges;
|
||||
@@ -473,6 +488,8 @@ void DynamicRibbonWidget::addAnimatedItem( const irr::core::stringw& user_name,
|
||||
|
||||
m_items.push_back(desc);
|
||||
|
||||
setLabelSize(desc.m_user_name);
|
||||
|
||||
if (!m_animated_contents)
|
||||
{
|
||||
m_animated_contents = true;
|
||||
@@ -498,6 +515,7 @@ void DynamicRibbonWidget::clearItems()
|
||||
m_items.clear();
|
||||
m_animated_contents = false;
|
||||
m_scroll_offset = 0;
|
||||
m_max_label_width = 0;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void DynamicRibbonWidget::elementRemoved()
|
||||
@@ -1097,7 +1115,9 @@ bool DynamicRibbonWidget::setSelection(int item_id, const int playerID,
|
||||
propagateSelection();
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool DynamicRibbonWidget::setSelection(const std::string &item_codename,
|
||||
const int playerID, const bool focusIt,
|
||||
bool evenIfDeactivated)
|
||||
@@ -1117,4 +1137,29 @@ bool DynamicRibbonWidget::setSelection(const std::string &item_codename,
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void DynamicRibbonWidget::setLabelSize(const irr::core::stringw& text)
|
||||
{
|
||||
int w = GUIEngine::getFont()->getDimension(text.c_str()).Width;
|
||||
if (w > m_max_label_width)
|
||||
m_max_label_width = w;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
float DynamicRibbonWidget::getFontScale(int icon_width) const
|
||||
{
|
||||
if (m_max_label_width <= icon_width || m_max_label_width == 0 || icon_width == 0)
|
||||
return 1.0f;
|
||||
else
|
||||
return std::max (0.5f, ((float)icon_width / (float)m_max_label_width));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
irr::core::stringw DynamicRibbonWidget::getUserName(const irr::core::stringw& user_name) const
|
||||
{
|
||||
if (user_name.size() < MAX_LABEL_LENGTH)
|
||||
return user_name;
|
||||
else
|
||||
return (user_name.subString(0, MAX_LABEL_LENGTH - 3) + L"...");
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
namespace GUIEngine
|
||||
{
|
||||
class IconButtonWidget;
|
||||
|
||||
|
||||
/**
|
||||
* Even if you have a ribbon that only acts on click/enter, you may wish to know which
|
||||
* item is currently highlighted. In this case, create a listener and pass it to the ribbon.
|
||||
@@ -44,7 +44,7 @@ namespace GUIEngine
|
||||
const irr::core::stringw& selectionText,
|
||||
const int playerID) = 0;
|
||||
};
|
||||
|
||||
|
||||
/** The description of an item added to a DynamicRibbonWidget */
|
||||
struct ItemDescription
|
||||
{
|
||||
@@ -52,16 +52,16 @@ namespace GUIEngine
|
||||
std::string m_code_name;
|
||||
std::string m_sshot_file;
|
||||
IconButtonWidget::IconPathType m_image_path_type;
|
||||
|
||||
|
||||
bool m_animated;
|
||||
/** used instead of 'm_sshot_file' if m_animated is true */
|
||||
std::vector<std::string> m_all_images;
|
||||
float m_curr_time;
|
||||
float m_time_per_frame;
|
||||
|
||||
|
||||
unsigned int m_badges;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief An extended version of RibbonWidget, with more capabilities.
|
||||
* A dynamic ribbon builds upon RibbonWidget, adding dynamic contents creation and sizing,
|
||||
@@ -73,55 +73,55 @@ namespace GUIEngine
|
||||
class DynamicRibbonWidget : public Widget, public RibbonWidget::IRibbonListener
|
||||
{
|
||||
friend class RibbonWidget;
|
||||
|
||||
|
||||
/** A list of all listeners that registered to be notified on hover/selection */
|
||||
PtrVector<DynamicRibbonHoverListener> m_hover_listeners;
|
||||
|
||||
|
||||
virtual ~DynamicRibbonWidget();
|
||||
|
||||
|
||||
/** Used for ribbon grids that have a label at the bottom */
|
||||
bool m_has_label;
|
||||
irr::gui::IGUIStaticText* m_label;
|
||||
|
||||
|
||||
/** Height of ONE label text line (if label is multiline only one line is measured here).
|
||||
* If there is no label, will be 0.
|
||||
*/
|
||||
int m_label_height;
|
||||
|
||||
|
||||
/** Whether this ribbon contains at least one animated item */
|
||||
bool m_animated_contents;
|
||||
|
||||
|
||||
/** Whether there are more items than can fit in a single screen; arrows will then appear
|
||||
* on each side of the ribbon to scroll the contents
|
||||
*/
|
||||
bool m_scrolling_enabled;
|
||||
|
||||
|
||||
/** Used to keep track of item count changes */
|
||||
int m_previous_item_count;
|
||||
|
||||
|
||||
/** List of items in the ribbon */
|
||||
std::vector<ItemDescription> m_items;
|
||||
|
||||
|
||||
/** Width of the scrolling arrows on each side */
|
||||
int m_arrows_w;
|
||||
|
||||
|
||||
/** Current scroll offset within items */
|
||||
int m_scroll_offset;
|
||||
|
||||
|
||||
/** Width and height of children as declared in the GUI file */
|
||||
int m_child_width, m_child_height;
|
||||
|
||||
|
||||
/** Number of rows and columns. Number of columns can dynamically change, number of row is
|
||||
determined at creation */
|
||||
int m_row_amount;
|
||||
int m_col_amount;
|
||||
|
||||
|
||||
/** The total number of columns given item count and row count (even counting not visible with current scrolling) */
|
||||
int m_needed_cols;
|
||||
|
||||
|
||||
/** Whether this ribbon can have multiple rows (i.e. ribbon grid) or is a single line */
|
||||
bool m_multi_row;
|
||||
|
||||
|
||||
/** irrlicht relies on consecutive IDs to perform keyboard navigation between widgets. However, since this
|
||||
widget is dynamic, irrlicht widgets are not created as early as all others, so by the time we're ready
|
||||
to create the full contents of this widget, the ID generator is already incremented, thus messing up
|
||||
@@ -129,65 +129,81 @@ namespace GUIEngine
|
||||
number of IDs (the number of rows) and store them here. Then, when we're finally ready to create the
|
||||
contents dynamically, we can re-use these IDs and get correct navigation order. */
|
||||
std::vector<int> m_ids;
|
||||
|
||||
|
||||
/** Whether this is a "combo" style ribbon grid widget */
|
||||
bool m_combo;
|
||||
|
||||
|
||||
/* reference pointers only, the actual instances are owned by m_children */
|
||||
IconButtonWidget* m_left_widget;
|
||||
IconButtonWidget* m_right_widget;
|
||||
|
||||
|
||||
/** Returns the currently selected row */
|
||||
RibbonWidget* getSelectedRibbon(const int playerID);
|
||||
|
||||
|
||||
/** Returns the row */
|
||||
RibbonWidget* getRowContaining(Widget* w);
|
||||
|
||||
|
||||
/** Updates the visible label to match the currently selected item */
|
||||
void updateLabel(RibbonWidget* from_this_ribbon=NULL);
|
||||
|
||||
|
||||
/** Even though the ribbon grid widget looks like a grid, it is really a vertical stack of
|
||||
independant ribbons. When moving selection horizontally, this method is used to notify
|
||||
other rows above and below of which column is selected, so that moving vertically to
|
||||
another row keeps the same selected column. */
|
||||
void propagateSelection();
|
||||
|
||||
|
||||
/** Callback called widget is focused */
|
||||
EventPropagation focused(const int playerID);
|
||||
|
||||
|
||||
/** Removes all previously added contents icons, and re-adds them (calculating the new amount) */
|
||||
void buildInternalStructure();
|
||||
|
||||
/** Call this to scroll within a scrollable ribbon */
|
||||
void scroll(const int x_delta);
|
||||
|
||||
|
||||
/** Used for combo ribbons, to contain the ID of the currently selected item for each player */
|
||||
int m_selected_item[MAX_PLAYER_COUNT];
|
||||
|
||||
|
||||
/** Callbacks */
|
||||
virtual void add();
|
||||
virtual EventPropagation mouseHovered(Widget* child, const int playerID);
|
||||
virtual EventPropagation transmitEvent(Widget* w, const std::string& originator, const int playerID);
|
||||
|
||||
|
||||
bool findItemInRows(const char* name, int* p_row, int* p_id);
|
||||
|
||||
|
||||
int m_item_count_hint;
|
||||
|
||||
|
||||
float getFontScale(int icon_width) const;
|
||||
void setLabelSize(const irr::core::stringw& text);
|
||||
irr::core::stringw getUserName(const irr::core::stringw& user_name) const;
|
||||
|
||||
/**
|
||||
* Font used to write the labels, can be scaled down depending on the
|
||||
* length of the text
|
||||
*/
|
||||
irr::gui::ScalableFont* m_font;
|
||||
|
||||
/** Max width of a label, in pixels */
|
||||
int m_max_label_width;
|
||||
|
||||
/** Max length of a label, in characters */
|
||||
static const int MAX_LABEL_LENGTH = 30;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
|
||||
/**
|
||||
* \param combo Whether this is a "combo" ribbon, i.e. whether there is always one selected item.
|
||||
* If set to false, will behave more like a toolbar.
|
||||
* \param multi_row Whether this ribbon can have more than one row
|
||||
*/
|
||||
DynamicRibbonWidget(const bool combo, const bool multi_row);
|
||||
|
||||
|
||||
/** Reference pointers only, the actual instances are owned by m_children. Used to create mtultiple-row
|
||||
ribbons (what appears to be a grid of icons is actually a vector of stacked basic ribbons) */
|
||||
PtrVector<RibbonWidget, REF> m_rows;
|
||||
|
||||
|
||||
/** Dynamically add an item to the ribbon's list of items (will not be visible until you
|
||||
* call 'updateItemDisplay' or 'add').
|
||||
*
|
||||
@@ -200,7 +216,7 @@ namespace GUIEngine
|
||||
void addItem( const irr::core::stringw& user_name, const std::string& code_name,
|
||||
const std::string& image_file, const unsigned int badge=0,
|
||||
IconButtonWidget::IconPathType image_path_type=IconButtonWidget::ICON_PATH_TYPE_RELATIVE);
|
||||
|
||||
|
||||
/** Dynamically add an animated item to the ribbon's list of items (will not be visible until you
|
||||
* call 'updateItemDisplay' or 'add'). Animated means it has many images that will be shown in
|
||||
* a slideshown fashion.
|
||||
@@ -220,7 +236,7 @@ namespace GUIEngine
|
||||
/** Clears all items added through 'addItem'. You can then add new items with 'addItem' and call
|
||||
'updateItemDisplay' to update the display. */
|
||||
void clearItems();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Register a listener to be notified of selection changes within the ribbon.
|
||||
* \note The ribbon takes ownership of this listener and will delete it.
|
||||
@@ -228,26 +244,26 @@ namespace GUIEngine
|
||||
* want to add a listener in the "init" callback of your screen.
|
||||
*/
|
||||
void registerHoverListener(DynamicRibbonHoverListener* listener);
|
||||
|
||||
|
||||
/** Called when right key is pressed */
|
||||
EventPropagation rightPressed(const int playerID);
|
||||
|
||||
|
||||
/** Called when left key is pressed */
|
||||
EventPropagation leftPressed(const int playerID);
|
||||
|
||||
|
||||
/** Updates icons/labels given current items and scrolling offset, taking care of resizing
|
||||
the dynamic ribbon if the number of items changed */
|
||||
void updateItemDisplay();
|
||||
|
||||
|
||||
/** Get the internal name (ID) of the selected item */
|
||||
const std::string& getSelectionIDString(const int playerID);
|
||||
|
||||
|
||||
/** Get the user-visible text of the selected item */
|
||||
irr::core::stringw getSelectionText(const int playerID);
|
||||
|
||||
|
||||
/** Returns a read-only list of items added to this ribbon */
|
||||
const std::vector<ItemDescription>& getItems() const { return m_items; }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Select an item from its numerical ID. Only for [1-row] combo ribbons.
|
||||
*
|
||||
@@ -255,7 +271,7 @@ namespace GUIEngine
|
||||
* \return Whether setting the selection was successful (whether the item exists)
|
||||
*/
|
||||
bool setSelection(int item_id, const int playerID, const bool focusIt, bool evenIfDeactivated=false);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Select an item from its codename.
|
||||
*
|
||||
@@ -264,26 +280,26 @@ namespace GUIEngine
|
||||
bool setSelection(const std::string &item_codename,
|
||||
const int playerID, const bool focusIt,
|
||||
bool evenIfDeactivated=false);
|
||||
|
||||
|
||||
/** \brief Callback from parent class Widget. */
|
||||
virtual void elementRemoved();
|
||||
|
||||
|
||||
/** \brief callback from IRibbonListener */
|
||||
virtual void onRibbonWidgetScroll(const int delta_x);
|
||||
|
||||
|
||||
/** \brief callback from IRibbonListener */
|
||||
virtual void onRibbonWidgetFocus(RibbonWidget* emitter, const int playerID);
|
||||
|
||||
|
||||
/** \brief callback from IRibbonListener */
|
||||
virtual void onSelectionChange(){}
|
||||
|
||||
virtual void update(float delta);
|
||||
|
||||
|
||||
/** Set approximately how many items are expected to be in this ribbon; will help the layout
|
||||
* algorithm next time add() is called */
|
||||
void setItemCountHint(int hint) { m_item_count_hint = hint; }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <IGUIEnvironment.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace GUIEngine;
|
||||
using namespace irr::video;
|
||||
@@ -39,10 +40,15 @@ IconButtonWidget::IconButtonWidget(ScaleMode scale_mode, const bool tab_stop,
|
||||
const bool focusable, IconPathType pathType) : Widget(WTYPE_ICON_BUTTON)
|
||||
{
|
||||
m_label = NULL;
|
||||
m_font = NULL;
|
||||
m_texture = NULL;
|
||||
m_highlight_texture = NULL;
|
||||
m_deactivated_texture = NULL;
|
||||
m_custom_aspect_ratio = 1.0f;
|
||||
|
||||
m_texture_w = 0;
|
||||
m_texture_h = 0;
|
||||
|
||||
m_tab_stop = tab_stop;
|
||||
m_focusable = focusable;
|
||||
m_scale_mode = scale_mode;
|
||||
@@ -50,6 +56,12 @@ IconButtonWidget::IconButtonWidget(ScaleMode scale_mode, const bool tab_stop,
|
||||
m_icon_path_type = pathType;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
IconButtonWidget::~IconButtonWidget()
|
||||
{
|
||||
if (m_deactivated_texture != NULL)
|
||||
m_deactivated_texture->drop();
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::add()
|
||||
{
|
||||
// ---- Icon
|
||||
@@ -57,12 +69,12 @@ void IconButtonWidget::add()
|
||||
{
|
||||
if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE)
|
||||
{
|
||||
m_texture = irr_driver->getTexture(m_properties[PROP_ICON]);
|
||||
setTexture(irr_driver->getTexture(m_properties[PROP_ICON]));
|
||||
}
|
||||
else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE)
|
||||
{
|
||||
std::string file = file_manager->getAsset(m_properties[PROP_ICON]);
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,13 +84,11 @@ void IconButtonWidget::add()
|
||||
"add() : error, cannot find texture '%s'.",
|
||||
m_properties[PROP_ICON].c_str());
|
||||
std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png");
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
if(!m_texture)
|
||||
Log::fatal("IconButtonWidget",
|
||||
"Can't find fallback texture 'gui/main_help.png, aborting.");
|
||||
}
|
||||
m_texture_w = m_texture->getSize().Width;
|
||||
m_texture_h = m_texture->getSize().Height;
|
||||
|
||||
if (m_properties[PROP_FOCUS_ICON].size() > 0)
|
||||
{
|
||||
@@ -174,13 +184,7 @@ void IconButtonWidget::add()
|
||||
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() );
|
||||
}
|
||||
setLabelFont();
|
||||
|
||||
#if IRRLICHT_VERSION_MAJOR > 1 || (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8)
|
||||
m_label->setRightToLeft( translations->isRTLLanguage() );
|
||||
@@ -207,12 +211,12 @@ void IconButtonWidget::setImage(const char* path_to_texture, IconPathType pathTy
|
||||
|
||||
if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE)
|
||||
{
|
||||
m_texture = irr_driver->getTexture(m_properties[PROP_ICON]);
|
||||
setTexture(irr_driver->getTexture(m_properties[PROP_ICON]));
|
||||
}
|
||||
else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE)
|
||||
{
|
||||
std::string file = file_manager->getAsset(m_properties[PROP_ICON]);
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
|
||||
if (!m_texture)
|
||||
@@ -220,11 +224,8 @@ void IconButtonWidget::setImage(const char* path_to_texture, IconPathType pathTy
|
||||
Log::error("icon_button", "Texture '%s' not found!\n",
|
||||
m_properties[PROP_ICON].c_str());
|
||||
std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png");
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
|
||||
m_texture_w = m_texture->getSize().Width;
|
||||
m_texture_h = m_texture->getSize().Height;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -233,39 +234,28 @@ 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;
|
||||
setTexture(texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("icon_button",
|
||||
"setImage invoked with NULL image pointer\n");
|
||||
std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png");
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setLabel(stringw new_label)
|
||||
void IconButtonWidget::setLabel(const 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
|
||||
> max_w + 4) // arbitrarily allow for 4 pixels
|
||||
{
|
||||
m_label->setOverrideFont( GUIEngine::getSmallFont() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_label->setOverrideFont( NULL );
|
||||
}
|
||||
setLabelFont();
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setLabelFont(irr::gui::ScalableFont* font)
|
||||
{
|
||||
m_font = font;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation IconButtonWidget::focused(const int playerID)
|
||||
@@ -288,4 +278,78 @@ void IconButtonWidget::unfocused(const int playerID, Widget* new_focus)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
video::ITexture* IconButtonWidget::getDeactivatedTexture(video::ITexture* texture)
|
||||
{
|
||||
SColor c;
|
||||
u32 g;
|
||||
|
||||
video::IVideoDriver* driver = irr_driver->getVideoDriver();
|
||||
video::IImage* image = driver->createImageFromData (texture->getColorFormat(),
|
||||
texture->getSize(), texture->lock(), false);
|
||||
texture->unlock();
|
||||
|
||||
//Turn the image into grayscale
|
||||
for (u32 x = 0; x < image->getDimension().Width; x++)
|
||||
{
|
||||
for (u32 y = 0; y < image->getDimension().Height; y++)
|
||||
{
|
||||
c = image->getPixel(x, y);
|
||||
g = ((c.getRed() + c.getGreen() + c.getBlue()) / 3);
|
||||
c.set(std::max (0, (int)c.getAlpha() - 120), g, g, g);
|
||||
image->setPixel(x, y, c);
|
||||
}
|
||||
}
|
||||
|
||||
texture = driver->addTexture(texture->getName().getPath() + "_disabled", image);
|
||||
texture->grab();
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setTexture(video::ITexture* texture)
|
||||
{
|
||||
m_texture = texture;
|
||||
if (texture == NULL)
|
||||
{
|
||||
if (m_deactivated_texture != NULL)
|
||||
m_deactivated_texture->drop();
|
||||
|
||||
m_deactivated_texture = NULL;
|
||||
m_texture_w = 0;
|
||||
m_texture_h = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_deactivated_texture = getDeactivatedTexture(texture);
|
||||
m_texture_w = texture->getSize().Width;
|
||||
m_texture_h = texture->getSize().Height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setLabelFont()
|
||||
{
|
||||
if (m_font != NULL)
|
||||
{
|
||||
m_label->setOverrideFont( m_font );
|
||||
}
|
||||
else
|
||||
{
|
||||
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(m_label->getText()).Width
|
||||
> max_w + 4) // arbitrarily allow for 4 pixels
|
||||
{
|
||||
m_label->setOverrideFont( GUIEngine::getSmallFont() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_label->setOverrideFont( NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,16 @@
|
||||
#include <irrString.h>
|
||||
namespace irr
|
||||
{
|
||||
namespace gui { class IGUIStaticText; }
|
||||
namespace gui
|
||||
{
|
||||
class IGUIStaticText;
|
||||
class ScalableFont;
|
||||
}
|
||||
namespace video { class ITexture; }
|
||||
}
|
||||
|
||||
#include "guiengine/widget.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
@@ -38,6 +41,15 @@ namespace GUIEngine
|
||||
*/
|
||||
class IconButtonWidget : public Widget
|
||||
{
|
||||
private:
|
||||
irr::video::ITexture* m_texture;
|
||||
irr::video::ITexture* m_highlight_texture;
|
||||
irr::video::ITexture* m_deactivated_texture;
|
||||
int m_texture_w, m_texture_h;
|
||||
|
||||
video::ITexture* getDeactivatedTexture(video::ITexture* texture);
|
||||
void setLabelFont();
|
||||
|
||||
public:
|
||||
enum ScaleMode
|
||||
{
|
||||
@@ -54,42 +66,41 @@ namespace GUIEngine
|
||||
* the path type as it currently is */
|
||||
ICON_PATH_TYPE_NO_CHANGE
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
IconPathType m_icon_path_type;
|
||||
|
||||
friend class Skin;
|
||||
|
||||
irr::gui::IGUIStaticText* m_label;
|
||||
irr::video::ITexture* m_texture;
|
||||
irr::video::ITexture* m_highlight_texture;
|
||||
|
||||
int m_texture_w, m_texture_h;
|
||||
|
||||
protected:
|
||||
|
||||
IconPathType m_icon_path_type;
|
||||
|
||||
friend class Skin;
|
||||
|
||||
irr::gui::IGUIStaticText* m_label;
|
||||
irr::gui::ScalableFont* m_font;
|
||||
|
||||
ScaleMode m_scale_mode;
|
||||
float m_custom_aspect_ratio;
|
||||
|
||||
|
||||
void setTexture(video::ITexture* texture);
|
||||
|
||||
public:
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
|
||||
/** Whether to make the widget included in keyboard navigation order when adding */
|
||||
bool m_tab_stop;
|
||||
|
||||
IconButtonWidget(ScaleMode scale_mode=SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO, const bool tab_stop=true,
|
||||
const bool focusable=true, IconPathType pathType=ICON_PATH_TYPE_RELATIVE);
|
||||
virtual ~IconButtonWidget() {}
|
||||
|
||||
virtual ~IconButtonWidget();
|
||||
|
||||
/** \brief Implement callback from base class Widget */
|
||||
virtual void add();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Call this if scale mode is SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO.
|
||||
* \param custom_aspect_ratio The width/height aspect ratio
|
||||
*/
|
||||
void setCustomAspectRatio(float custom_aspect_ratio) { m_custom_aspect_ratio = custom_aspect_ratio; }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Temporarily change the text label if there is a label (next time this screen is
|
||||
* visited, the previous label will be back. For a permanent change, edit the 'text'
|
||||
@@ -98,8 +109,15 @@ namespace GUIEngine
|
||||
* \pre Must be called after this widget is add()ed to have any effect
|
||||
* \note Calling this method on a button without label will have no effect
|
||||
*/
|
||||
void setLabel(irr::core::stringw new_label);
|
||||
|
||||
void setLabel(const irr::core::stringw& new_label);
|
||||
|
||||
/**
|
||||
* \brief Sets the font used to draw the label.
|
||||
*
|
||||
* \note Calling this method on a button without label will have no effect
|
||||
*/
|
||||
void setLabelFont(irr::gui::ScalableFont* font);
|
||||
|
||||
/**
|
||||
* Change the texture used for this icon.
|
||||
* \pre At the moment, the new texture must have the same aspct ratio
|
||||
@@ -109,7 +127,7 @@ namespace GUIEngine
|
||||
*/
|
||||
void setImage(const char* path_to_texture,
|
||||
IconPathType path_type=ICON_PATH_TYPE_NO_CHANGE);
|
||||
// --------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------
|
||||
/** Convenience function taking std::string. */
|
||||
void setImage(const std::string &path_to_texture,
|
||||
IconPathType path_type=ICON_PATH_TYPE_NO_CHANGE)
|
||||
@@ -126,23 +144,24 @@ namespace GUIEngine
|
||||
* \note May safely be called no matter if the widget is add()ed or not
|
||||
*/
|
||||
void setImage(irr::video::ITexture* texture);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
void setHighlightedImage(irr::video::ITexture* texture)
|
||||
{
|
||||
m_highlight_texture = texture;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** \brief override from base class */
|
||||
virtual EventPropagation focused(const int playerID);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** \brief override from base class */
|
||||
virtual void unfocused(const int playerID, Widget* new_focus);
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns the texture of this button. */
|
||||
const video::ITexture* getTexture() const { return m_texture; }
|
||||
const video::ITexture* getTexture() const {
|
||||
return (Widget::isActivated() ? m_texture : m_deactivated_texture); }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -114,13 +114,14 @@ FileManager::FileManager()
|
||||
m_subdir_name[GFX ] = "gfx";
|
||||
m_subdir_name[GRANDPRIX ] = "grandprix";
|
||||
m_subdir_name[GUI ] = "gui";
|
||||
m_subdir_name[LIBRARY ] = "library";
|
||||
m_subdir_name[MODEL ] = "models";
|
||||
m_subdir_name[MUSIC ] = "music";
|
||||
m_subdir_name[TRANSLATION] = "po";
|
||||
m_subdir_name[TEXTURE ] = "textures";
|
||||
m_subdir_name[SFX ] = "sfx";
|
||||
m_subdir_name[SKIN ] = "skins";
|
||||
m_subdir_name[SHADER ] = "shaders";
|
||||
m_subdir_name[TEXTURE ] = "textures";
|
||||
m_subdir_name[TRANSLATION] = "po";
|
||||
#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
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
* The last entry ASSET_COUNT specifies the number of entries. */
|
||||
enum AssetType {ASSET_MIN,
|
||||
CHALLENGE=ASSET_MIN,
|
||||
FONT, GFX, GRANDPRIX, GUI, MODEL, MUSIC,
|
||||
FONT, GFX, GRANDPRIX, GUI, LIBRARY, MODEL, MUSIC,
|
||||
SFX, SHADER, SKIN, TEXTURE, TRANSLATION,
|
||||
ASSET_MAX = TRANSLATION,
|
||||
ASSET_COUNT};
|
||||
|
||||
@@ -414,6 +414,10 @@ public:
|
||||
/** Set a text that is displayed on top of a kart.
|
||||
*/
|
||||
virtual void setOnScreenText(const wchar_t *text) = 0;
|
||||
// -------------------------------------------------------------------------
|
||||
/** Counter which is used for displaying wrong way message after a delay */
|
||||
virtual float getWrongwayCounter() = 0;
|
||||
virtual void setWrongwayCounter(float counter) = 0;
|
||||
|
||||
}; // AbstractKart
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
|
||||
m_is_jumping = false;
|
||||
m_min_nitro_time = 0.0f;
|
||||
m_fire_clicked = 0;
|
||||
m_wrongway_counter = 0;
|
||||
|
||||
m_view_blocked_by_plunger = 0;
|
||||
m_has_caught_nolok_bubblegum = false;
|
||||
|
||||
@@ -148,7 +148,9 @@ private:
|
||||
|
||||
/** True if fire button was pushed and not released */
|
||||
bool m_fire_clicked;
|
||||
|
||||
|
||||
/** Counter which is used for displaying wrong way message after a delay */
|
||||
float m_wrongway_counter;
|
||||
|
||||
|
||||
// Bullet physics parameters
|
||||
@@ -437,6 +439,10 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** For debugging only: check if a kart is flying. */
|
||||
bool isFlying() const { return m_flying; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Counter which is used for displaying wrong way message after a delay */
|
||||
float getWrongwayCounter() { return m_wrongway_counter; }
|
||||
void setWrongwayCounter(float counter) { m_wrongway_counter = counter; }
|
||||
}; // Kart
|
||||
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ void EasterEggHunt::getKartsDisplayInfo(
|
||||
* direction messages in the easter egg mode since there is no direction there.
|
||||
* \param i Kart id.
|
||||
*/
|
||||
void EasterEggHunt::checkForWrongDirection(unsigned int i)
|
||||
void EasterEggHunt::checkForWrongDirection(unsigned int i, float dt)
|
||||
{
|
||||
} // checkForWrongDirection
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
void collectedEasterEgg(const AbstractKart *kart);
|
||||
void readData(const std::string &filename);
|
||||
|
||||
virtual void checkForWrongDirection(unsigned int i) OVERRIDE;
|
||||
virtual void checkForWrongDirection(unsigned int i, float dt) OVERRIDE;
|
||||
virtual float estimateFinishTimeForKart(AbstractKart* kart) OVERRIDE;
|
||||
|
||||
}; // EasterEggHunt
|
||||
|
||||
@@ -92,6 +92,7 @@ void LinearWorld::reset()
|
||||
{
|
||||
m_kart_info[i].reset();
|
||||
m_kart_info[i].getTrackSector()->update(m_karts[i]->getXYZ());
|
||||
m_karts[i]->setWrongwayCounter(0);
|
||||
} // next kart
|
||||
|
||||
// At the moment the last kart would be the one that is furthest away
|
||||
@@ -200,7 +201,7 @@ void LinearWorld::update(float dt)
|
||||
m_kart_info[i].m_estimated_finish =
|
||||
estimateFinishTimeForKart(m_karts[i]);
|
||||
}
|
||||
checkForWrongDirection(i);
|
||||
checkForWrongDirection(i, dt);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -830,38 +831,63 @@ void LinearWorld::updateRacePosition()
|
||||
* player karts to display a message to the player.
|
||||
* \param i Kart id.
|
||||
*/
|
||||
void LinearWorld::checkForWrongDirection(unsigned int i)
|
||||
void LinearWorld::checkForWrongDirection(unsigned int i, float dt)
|
||||
{
|
||||
if(!m_karts[i]->getController()->isPlayerController()) return;
|
||||
if(!m_kart_info[i].getTrackSector()->isOnRoad()||
|
||||
m_karts[i]->getKartAnimation()) return;
|
||||
if (!m_karts[i]->getController()->isPlayerController())
|
||||
return;
|
||||
|
||||
float wrongway_counter = m_karts[i]->getWrongwayCounter();
|
||||
|
||||
const AbstractKart *kart=m_karts[i];
|
||||
// If the kart can go in more than one directions from the current track
|
||||
// don't do any reverse message handling, since it is likely that there
|
||||
// will be one direction in which it isn't going backwards anyway.
|
||||
int sector = m_kart_info[i].getTrackSector()->getCurrentGraphNode();
|
||||
if(QuadGraph::get()->getNumberOfSuccessors(sector)>1)
|
||||
|
||||
if (QuadGraph::get()->getNumberOfSuccessors(sector) > 1)
|
||||
return;
|
||||
|
||||
// check if the player is going in the wrong direction
|
||||
float angle_diff = kart->getHeading() -
|
||||
m_track->getAngle(sector);
|
||||
if(angle_diff > M_PI) angle_diff -= 2*M_PI;
|
||||
else if (angle_diff < -M_PI) angle_diff += 2*M_PI;
|
||||
float angle_diff = kart->getHeading() - m_track->getAngle(sector);
|
||||
|
||||
if (angle_diff > M_PI)
|
||||
angle_diff -= 2*M_PI;
|
||||
else if (angle_diff < -M_PI)
|
||||
angle_diff += 2*M_PI;
|
||||
|
||||
// Display a warning message if the kart is going back way (unless
|
||||
// the kart has already finished the race).
|
||||
if (( angle_diff > DEGREE_TO_RAD* 120.0f ||
|
||||
angle_diff < -DEGREE_TO_RAD*120.0f) &&
|
||||
kart->getVelocityLC().getY() > 0.0f &&
|
||||
!kart->hasFinishedRace() )
|
||||
if ((angle_diff > DEGREE_TO_RAD * 120.0f ||
|
||||
angle_diff < -DEGREE_TO_RAD * 120.0f) &&
|
||||
kart->getVelocityLC().getY() > 0.0f &&
|
||||
!kart->hasFinishedRace())
|
||||
{
|
||||
wrongway_counter += dt;
|
||||
|
||||
if (wrongway_counter > 2.0f)
|
||||
wrongway_counter = 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
wrongway_counter -= dt;
|
||||
|
||||
if (wrongway_counter < 0)
|
||||
wrongway_counter = 0;
|
||||
}
|
||||
|
||||
if (kart->getKartAnimation())
|
||||
wrongway_counter = 0;
|
||||
|
||||
if (wrongway_counter > 1.0f)
|
||||
{
|
||||
m_race_gui->addMessage(_("WRONG WAY!"), kart,
|
||||
/* time */ -1.0f,
|
||||
/* time */ -1.0f,
|
||||
video::SColor(255,255,255,255),
|
||||
/*important*/ true,
|
||||
/*big font*/ true);
|
||||
} // if angle is too big
|
||||
|
||||
m_karts[i]->setWrongwayCounter(wrongway_counter);
|
||||
} // checkForWrongDirection
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -111,7 +111,7 @@ protected:
|
||||
*/
|
||||
AlignedArray<KartInfo> m_kart_info;
|
||||
|
||||
virtual void checkForWrongDirection(unsigned int i);
|
||||
virtual void checkForWrongDirection(unsigned int i, float dt);
|
||||
void updateRacePosition();
|
||||
virtual float estimateFinishTimeForKart(AbstractKart* kart) OVERRIDE;
|
||||
|
||||
|
||||
@@ -25,16 +25,9 @@
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#if defined(WIN32) && !defined(__MINGW32__)
|
||||
#if defined(WIN32)
|
||||
# include "Ws2tcpip.h"
|
||||
# define inet_ntop InetNtop
|
||||
|
||||
// TODO: It's very ugly hack which allows to compile STK on windows using gcc.
|
||||
// Solution would be nice seen.
|
||||
#elif defined(__MINGW32__)
|
||||
# include "Ws2tcpip.h"
|
||||
# define inet_ntop
|
||||
|
||||
# define inet_ntop InetNtop
|
||||
#else
|
||||
# include <arpa/inet.h>
|
||||
# include <errno.h>
|
||||
@@ -42,6 +35,25 @@
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
const char* inet_ntop(int af, const void* src, char* dst, int cnt)
|
||||
{
|
||||
struct sockaddr_in srcaddr;
|
||||
|
||||
memset(&srcaddr, 0, sizeof(struct sockaddr_in));
|
||||
memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
|
||||
|
||||
srcaddr.sin_family = af;
|
||||
if (WSAAddressToString((struct sockaddr*) &srcaddr,
|
||||
sizeof(struct sockaddr_in), 0, dst, (LPDWORD) &cnt) != 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
FILE* STKHost::m_log_file = NULL;
|
||||
pthread_mutex_t STKHost::m_log_mutex;
|
||||
|
||||
@@ -98,7 +110,7 @@ STKHost::STKHost()
|
||||
pthread_mutex_init(&m_log_mutex, NULL);
|
||||
if (UserConfigParams::m_packets_log_filename.toString() != "")
|
||||
{
|
||||
std::string s =
|
||||
std::string s =
|
||||
file_manager->getUserConfigFile(UserConfigParams::m_packets_log_filename);
|
||||
m_log_file = fopen(s.c_str(), "w+");
|
||||
}
|
||||
|
||||
@@ -122,18 +122,20 @@ void ProfileManager::addToCache(OnlineProfile * profile)
|
||||
void ProfileManager::addDirectToCache(OnlineProfile* profile)
|
||||
{
|
||||
assert(profile != NULL);
|
||||
if (m_profiles_cache.size() == m_max_cache_size)
|
||||
if (m_profiles_cache.size() >= m_max_cache_size)
|
||||
{
|
||||
// We have to replace a cached entry, find one entry that
|
||||
// doesn't have its used bit set
|
||||
// Cache already full, try to find entries that
|
||||
// don't have their used bit set
|
||||
ProfilesMap::iterator iter;
|
||||
for (iter = m_profiles_cache.begin(); iter != m_profiles_cache.end();)
|
||||
{
|
||||
if (!iter->second->getCacheBit())
|
||||
{
|
||||
delete iter->second;
|
||||
m_profiles_cache.erase(iter);
|
||||
break;
|
||||
iter = m_profiles_cache.erase(iter);
|
||||
// Keep on deleting till enough space is available.
|
||||
if(m_profiles_cache.size()<m_max_cache_size)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -143,7 +145,6 @@ void ProfileManager::addDirectToCache(OnlineProfile* profile)
|
||||
}
|
||||
|
||||
m_profiles_cache[profile->getID()] = profile;
|
||||
assert(m_profiles_cache.size() <= m_max_cache_size);
|
||||
} // addDirectToCache
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@@ -175,7 +176,7 @@ bool ProfileManager::isInCache(const uint32_t id)
|
||||
void ProfileManager::updateCacheBits(OnlineProfile * profile)
|
||||
{
|
||||
profile->setCacheBit(true);
|
||||
if (m_profiles_cache.size() == m_max_cache_size)
|
||||
if (m_profiles_cache.size() >= m_max_cache_size)
|
||||
{
|
||||
ProfilesMap::iterator iter;
|
||||
for (iter = m_profiles_cache.begin();
|
||||
|
||||
@@ -426,6 +426,17 @@ void Track::cleanup()
|
||||
}
|
||||
#endif
|
||||
} // if verbose
|
||||
|
||||
#ifdef __DEBUG_DUMP_MESH_CACHE_AFTER_CLEANUP__
|
||||
scene::IMeshCache* meshCache = irr_driver->getSceneManager()->getMeshCache();
|
||||
int count = meshCache->getMeshCount();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
scene::IAnimatedMesh* mesh = meshCache->getMeshByIndex(i);
|
||||
io::SNamedPath path = meshCache->getMeshName(mesh);
|
||||
Log::info("CACHE", "[%i] %s", i, path.getPath().c_str());
|
||||
}
|
||||
#endif
|
||||
} // cleanup
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1928,17 +1939,17 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin
|
||||
node->get("scale", &scale);
|
||||
|
||||
XMLNode* libroot;
|
||||
std::string lib_path = file_manager->getAsset("library/" + name);
|
||||
std::string lib_path =
|
||||
file_manager->getAsset(FileManager::LIBRARY, name)+"/";
|
||||
bool create_lod_definitions = true;
|
||||
|
||||
if (library_nodes.find(name) == library_nodes.end())
|
||||
{
|
||||
std::string node_path = "library/" + name + "/node.xml";
|
||||
std::string lib_node_path = file_manager->getAsset(node_path);
|
||||
std::string lib_node_path = lib_path+"node.xml";
|
||||
libroot = file_manager->createXMLTree(lib_node_path);
|
||||
if (libroot == NULL)
|
||||
{
|
||||
Log::error("Track", "Cannot find library '%s'", node_path.c_str());
|
||||
Log::error("Track", "Cannot find library '%s'", lib_node_path.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user