Merge remote-tracking branch 'origin/master' into soft-physics-landing

This commit is contained in:
hiker
2014-09-30 15:15:56 +10:00
25 changed files with 403 additions and 1412 deletions

View File

@@ -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)

View File

@@ -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" />

View File

@@ -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"

View File

@@ -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

View File

@@ -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
{

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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()

View File

@@ -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"...");
}

View File

@@ -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

View File

@@ -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 );
}
}
}

View File

@@ -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); }
};
}

View File

@@ -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

View File

@@ -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};

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
//-----------------------------------------------------------------------------

View File

@@ -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;

View File

@@ -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+");
}

View File

@@ -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();

View File

@@ -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;
}