Continue work on scripting, fixing #2268. Use this as an opportunity to clean up a lot of old hardcoded overworld code, and replace it with cleaner scripting. Make sure to update SVN and the exporter (other commits in SVN coming soon)

This commit is contained in:
Marianne Gagnon 2015-08-09 21:38:01 -04:00
parent 43d5dbeb3e
commit d488c043d1
16 changed files with 278 additions and 276 deletions

View File

@ -978,6 +978,7 @@ SFXBase* SFXManager::quickSound(const std::string &sound_type)
else
{
SFXBase *base_sound = sound->second;
if (base_sound->getStatus() != SFXBase::SFX_PLAYING)
base_sound->play();
return base_sound;
}

View File

@ -1880,29 +1880,6 @@ void Kart::crashed(const Material *m, const Vec3 &normal)
push[1] = 0.1f;
m_body->applyCentralImpulse( -4000.0f*push );
m_bounce_back_time = 2.0f;
core::stringw msg = _("You need more points\n"
"to enter this challenge!\n"
"Check the minimap for\n"
"available challenges.");
std::vector<core::stringw> parts =
StringUtils::split(msg, '\n', false);
// For now, until we have scripting, special-case
// the overworld... (TODO)
if (dynamic_cast<OverWorld*>(World::getWorld()) != NULL)
{
SFXManager::get()->quickSound("forcefield");
World::getWorld()->getRaceGUI()->clearAllMessages();
for (unsigned int n = 0; n < parts.size(); n++)
{
World::getWorld()->getRaceGUI()
->addMessage(parts[n], NULL, 4.0f,
video::SColor(255, 255,255,255),
true, true);
} // for n<parts.size()
} // if world exist
} // if m_bounce_back_time <= 0.2f
} // if (m->getCollisionReaction() == Material::PUSH_BACK)
} // if(m && m->getCollisionReaction() != Material::NORMAL &&

View File

@ -224,10 +224,6 @@ void OverWorld::onFirePressed(Controller* who)
for (unsigned int n=0; n<challenges.size(); n++)
{
if ( challenges[n].isForceFieldSet() &&
challenges[n].getForceField().m_is_locked )
continue;
if ( (kart_xyz - Vec3(challenges[n].m_position)).length2_2d()
< CHALLENGE_DISTANCE_SQUARED)
{
@ -237,11 +233,24 @@ void OverWorld::onFirePressed(Controller* who)
return;
}
else
{
const ChallengeData* challenge = unlock_manager->getChallengeData(challenges[n].m_challenge_id);
if (challenge == NULL)
{
Log::error("track", "Cannot find challenge named '%s'\n",
challenges[n].m_challenge_id.c_str());
continue;
}
const unsigned int val = challenge->getNumTrophies();
bool unlocked = (PlayerManager::getCurrentPlayer()->getPoints() >= val);
if (unlocked)
{
race_manager->setKartLastPositionOnOverworld(kart_xyz);
new SelectChallengeDialog(0.8f, 0.8f,
challenges[n].m_challenge_id);
}
}
} // end if
} // end for
} // onFirePressed

View File

@ -211,8 +211,6 @@ void World::init()
m_weather = new Weather(m_track->getWeatherLightning(),
m_track->getWeatherSound());
}
m_script_engine->compileLoadedScripts();
} // init
//-----------------------------------------------------------------------------

View File

@ -129,7 +129,7 @@ PhysicalObject::PhysicalObject(bool is_dynamic,
m_object = object;
m_init_xyz = object->getAbsolutePosition();
m_init_xyz = object->getAbsoluteCenterPosition();
m_init_hpr = object->getRotation();
m_init_scale = object->getScale();
@ -461,8 +461,11 @@ void PhysicalObject::init()
// 2. Create the rigid object
// --------------------------
// m_init_pos is the point on the track - add the offset
if (m_is_dynamic)
{
m_init_pos.setOrigin(m_init_pos.getOrigin() +
btVector3(0,extend.getY()*0.5f, 0));
btVector3(0, extend.getY()*0.5f, 0));
}
m_motion_state = new btDefaultMotionState(m_init_pos);
btVector3 inertia(1,1,1);
if (m_body_type != MP_EXACT)

View File

@ -19,10 +19,14 @@
#include "script_track.hpp"
#include "animations/three_d_animation.hpp"
#include "input/device_manager.hpp"
#include "input/input_device.hpp"
#include "input/input_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/stk_text_billboard.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/scalable_font.hpp"
#include "modes/world.hpp"
#include "config/player_manager.hpp"
#include "states_screens/dialogs/tutorial_message_dialog.hpp"
#include "tracks/track.hpp"
#include "tracks/track_object.hpp"
@ -30,6 +34,8 @@
#include <angelscript.h>
#include <assert.h>
#include <ISceneManager.h>
#include <IBillboardTextSceneNode.h>
/** \cond DOXYGEN_IGNORE */
namespace Scripting
@ -58,6 +64,38 @@ namespace Scripting
return track->getChallengeList().size();
}
int getChallengeRequiredPoints(std::string* challenge_name)
{
::Track* track = World::getWorld()->getTrack();
const ChallengeData* challenge = unlock_manager->getChallengeData(*challenge_name);
if (challenge == NULL)
{
if (*challenge_name != "tutorial")
Log::error("track", "Cannot find challenge named '%s'\n",
challenge_name->c_str());
return false;
}
return challenge->getNumTrophies();
}
bool isChallengeUnlocked(std::string* challenge_name)
{
::Track* track = World::getWorld()->getTrack();
const ChallengeData* challenge = unlock_manager->getChallengeData(*challenge_name);
if (challenge == NULL)
{
if (*challenge_name != "tutorial")
Log::error("track", "Cannot find challenge named '%s'\n",
challenge_name->c_str());
return false;
}
const unsigned int val = challenge->getNumTrophies();
bool shown = (PlayerManager::getCurrentPlayer()->getPoints() >= val);
return shown;
}
/** @}*/
/** @}*/
@ -69,6 +107,8 @@ namespace Scripting
r = engine->RegisterGlobalFunction("int getCompletedChallengesCount()", asFUNCTION(getCompletedChallengesCount), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("int getChallengeCount()", asFUNCTION(getChallengeCount), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("bool isChallengeUnlocked(string &in)", asFUNCTION(isChallengeUnlocked), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("int getChallengeRequiredPoints(string &in)", asFUNCTION(getChallengeRequiredPoints), asCALL_CDECL); assert(r >= 0);
}
}

View File

@ -61,12 +61,33 @@ namespace Scripting
}
/** Show the specified message in a popup */
void displayMessage(std::string* input)
void displayModalMessage(std::string* input)
{
irr::core::stringw out = StringUtils::utf8_to_wide(input->c_str());
new TutorialMessageDialog((out), true);
}
void clearOverlayMessages()
{
World::getWorld()->getRaceGUI()->clearAllMessages();
}
/** Display text in the center of the screen for a few seconds */
void displayOverlayMessage(std::string* input)
{
irr::core::stringw msg = StringUtils::utf8_to_wide(input->c_str());
std::vector<core::stringw> parts =
StringUtils::split(msg, '\n', false);
for (unsigned int n = 0; n < parts.size(); n++)
{
World::getWorld()->getRaceGUI()
->addMessage(parts[n], NULL, 4.0f,
video::SColor(255, 255,255,255),
true, true);
} // for n<parts.size()
}
/** Get translated version of string */
std::string translate(std::string* input)
{
@ -150,7 +171,9 @@ namespace Scripting
{
int r; // of type asERetCodes
engine->SetDefaultNamespace("GUI");
r = engine->RegisterGlobalFunction("void displayMessage(const string &in)", asFUNCTION(displayMessage), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void displayModalMessage(const string &in)", asFUNCTION(displayModalMessage), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void displayOverlayMessage(const string &in)", asFUNCTION(displayOverlayMessage), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void clearOverlayMessages()", asFUNCTION(clearOverlayMessages), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("string getKeyBinding(int input)", asFUNCTION(getKeyBinding), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("string translate(const string &in)", asFUNCTION(proxy_translate), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("string translate(const string &in, const string &in)", asFUNCTION(proxy_translateAndInsertValues1), asCALL_CDECL); assert(r >= 0);

View File

@ -19,6 +19,9 @@
#include "script_track.hpp"
#include "animations/three_d_animation.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/stk_text_billboard.hpp"
#include "guiengine/scalable_font.hpp"
#include "input/device_manager.hpp"
#include "input/input_device.hpp"
#include "input/input_manager.hpp"
@ -29,8 +32,10 @@
#include "tracks/track_object.hpp"
#include "tracks/track_object_manager.hpp"
#include <IBillboardTextSceneNode.h>
#include <angelscript.h>
#include <assert.h>
#include <ISceneManager.h>
/** \cond DOXYGEN_IGNORE */
namespace Scripting
@ -57,13 +62,13 @@ namespace Scripting
* Get a track object by ID.
* @return An object of type @ref Scripting_TrackObject
*/
TrackObject* getTrackObject(std::string* libraryInstance, std::string* objID)
::TrackObject* getTrackObject(std::string* libraryInstance, std::string* objID)
{
return World::getWorld()->getTrack()->getTrackObjectManager()->getTrackObject(*libraryInstance, *objID);
}
/** Creates a trigger at the specified location */
void createTrigger(std::string* triggerID, Vec3* creation_loc, float distance)
void createTrigger(std::string* triggerID, SimpleVec3* creation_loc, float distance)
{
float x = creation_loc->getX();
float y = creation_loc->getY();
@ -73,12 +78,51 @@ namespace Scripting
core::vector3df scale(1.0f, 1.0f, 1.0f);
TrackObjectPresentationActionTrigger* newtrigger =
new TrackObjectPresentationActionTrigger(posi, *triggerID, distance);
TrackObject* tobj = new TrackObject(posi, hpr, scale,
::TrackObject* tobj = new ::TrackObject(posi, hpr, scale,
"none", newtrigger, false /* isDynamic */, NULL /* physics settings */);
tobj->setID(*triggerID);
World::getWorld()->getTrack()->getTrackObjectManager()->insertObject(tobj);
}
void createTextBillboard(std::string* text, SimpleVec3* location)
{
core::stringw wtext = StringUtils::utf8_to_wide(text->c_str());
core::dimension2d<u32> textsize = GUIEngine::getHighresDigitFont()
->getDimension(wtext.c_str());
assert(GUIEngine::getHighresDigitFont() != NULL);
core::vector3df xyz(location->getX(), location->getY(), location->getZ());
if (CVS->isGLSL())
{
gui::ScalableFont* font = GUIEngine::getHighresDigitFont();
STKTextBillboard* tb = new STKTextBillboard(wtext.c_str(), font,
video::SColor(255, 255, 225, 0),
video::SColor(255, 255, 89, 0),
irr_driver->getSceneManager()->getRootSceneNode(),
irr_driver->getSceneManager(), -1, xyz,
core::vector3df(1.5f, 1.5f, 1.5f));
World::getWorld()->getTrack()->addNode(tb);
}
else
{
scene::ISceneManager* sm = irr_driver->getSceneManager();
scene::ISceneNode* sn =
sm->addBillboardTextSceneNode(GUIEngine::getHighresDigitFont(),
wtext.c_str(),
NULL,
core::dimension2df(textsize.Width / 35.0f,
textsize.Height / 35.0f),
xyz,
-1, // id
video::SColor(255, 255, 225, 0),
video::SColor(255, 255, 89, 0));
World::getWorld()->getTrack()->addNode(sn);
}
}
/** Exits the race to the main menu */
void exitRace()
{
@ -96,6 +140,21 @@ namespace Scripting
{
/** \endcond */
namespace TrackObject
{
SimpleVec3 getCenterPosition(::TrackObject* obj)
{
core::vector3df pos = obj->getAbsoluteCenterPosition();
return SimpleVec3(pos.X, pos.Y, pos.Z);
}
SimpleVec3 getOrigin(::TrackObject* obj)
{
core::vector3df pos = obj->getAbsolutePosition();
return SimpleVec3(pos.X, pos.Y, pos.Z);
}
}
// ----------- TrackObjectPresentationMesh methods -----------
// TODO: this method is WRONG, we should in most cases move not the presentation but the entire object
//void movePresentation(Vec3 *new_pos, void *memory)
@ -237,19 +296,22 @@ namespace Scripting
//r = engine->RegisterGlobalFunction("void disableTrigger(const string &in)", asFUNCTION(disableTrigger), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void createTrigger(const string &in, const Vec3 &in, float distance)",
asFUNCTION(createTrigger), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void createTextBillboard(const string &in, const Vec3 &in)",
asFUNCTION(createTextBillboard), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("TrackObject@ getTrackObject(const string &in, const string &in)", asFUNCTION(getTrackObject), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void exitRace()", asFUNCTION(exitRace), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void pauseRace()", asFUNCTION(pauseRace), asCALL_CDECL); assert(r >= 0);
// TrackObject
r = engine->RegisterObjectMethod("TrackObject", "void setEnabled(bool status)", asMETHOD(TrackObject, setEnabled), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "SoundEmitter@ getSoundEmitter()", asMETHOD(TrackObject, getSoundEmitter), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "PhysicalObject@ getPhysics()", asMETHOD(TrackObject, getPhysics), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "Mesh@ getMesh()", asMETHOD(TrackObject, getMesh), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "ParticleEmitter@ getParticleEmitter()", asMETHOD(TrackObject, getParticleEmitter), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "Animator@ getIPOAnimator()", asMETHOD(TrackObject, getIPOAnimator), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "void moveTo(const Vec3 &in, bool)", asMETHOD(TrackObject, moveTo), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "void setEnabled(bool status)", asMETHOD(::TrackObject, setEnabled), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "SoundEmitter@ getSoundEmitter()", asMETHOD(::TrackObject, getSoundEmitter), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "PhysicalObject@ getPhysics()", asMETHOD(::TrackObject, getPhysics), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "Mesh@ getMesh()", asMETHOD(::TrackObject, getMesh), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "ParticleEmitter@ getParticleEmitter()", asMETHOD(::TrackObject, getParticleEmitter), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "Animator@ getIPOAnimator()", asMETHOD(::TrackObject, getIPOAnimator), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "void moveTo(const Vec3 &in, bool)", asMETHOD(::TrackObject, moveTo), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "Vec3 getCenterPosition()", asFUNCTION(TrackObject::getCenterPosition), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "Vec3 getOrigin()", asFUNCTION(TrackObject::getOrigin), asCALL_CDECL_OBJLAST); assert(r >= 0);
// PhysicalObject
r = engine->RegisterObjectMethod("PhysicalObject", "bool isFlattenKartObject()", asMETHOD(PhysicalObject, isFlattenKartObject), asCALL_THISCALL); assert(r >= 0);

View File

@ -399,9 +399,10 @@ void RaceGUIOverworld::drawGlobalMiniMap()
Vec3 draw_at;
track->mapPoint2MiniMap(challenges[n].m_position, &draw_at);
//const ChallengeData* c = unlock_manager->getChallenge(challenges[n].m_challenge_id);
// bool locked = (m_locked_challenges.find(c) != m_locked_challenges.end());
int state = (challenges[n].getForceField().m_is_locked ? LOCKED : OPEN);
const ChallengeData* challenge = unlock_manager->getChallengeData(challenges[n].m_challenge_id);
const unsigned int val = challenge->getNumTrophies();
bool unlocked = (PlayerManager::getCurrentPlayer()->getPoints() >= val);
int state = (unlocked ? OPEN : LOCKED);
const ChallengeStatus* c = PlayerManager::getCurrentPlayer()
->getChallengeStatus(challenges[n].m_challenge_id);
@ -441,8 +442,14 @@ void RaceGUIOverworld::drawGlobalMiniMap()
m_close_to_a_challenge = false;
for (unsigned int n=0; n<challenges.size(); n++)
{
if (challenges[n].m_challenge_id != "tutorial" &&
challenges[n].getForceField().m_is_locked) continue;
if (challenges[n].m_challenge_id != "tutorial")
{
const ChallengeData* challenge = unlock_manager->getChallengeData(challenges[n].m_challenge_id);
const unsigned int val = challenge->getNumTrophies();
bool unlocked = (PlayerManager::getCurrentPlayer()->getPoints() >= val);
if (!unlocked)
continue;
}
if ((kart_xyz - Vec3(challenges[n].m_position)).length2_2d() < CHALLENGE_DISTANCE_SQUARED &&
fabsf(kart_xyz[1] - challenges[n].m_position.Y) < CHALLENGE_HEIGHT)

View File

@ -988,7 +988,6 @@ bool Track::loadMainTrack(const XMLNode &root)
assert(m_gfx_effect_mesh==NULL);
m_challenges.clear();
m_force_fields.clear();
m_track_mesh = new TriangleMesh();
m_gfx_effect_mesh = new TriangleMesh();
@ -1117,7 +1116,6 @@ bool Track::loadMainTrack(const XMLNode &root)
continue;
}
core::vector3df xyz(0,0,0);
n->get("xyz", &xyz);
core::vector3df hpr(0,0,0);
@ -1125,117 +1123,6 @@ bool Track::loadMainTrack(const XMLNode &root)
core::vector3df scale(1.0f, 1.0f, 1.0f);
n->get("scale", &scale);
// some static meshes are conditional
std::string condition;
n->get("if", &condition);
// TODO: convert "if" and "ifnot" to scripting.
if (condition == "splatting")
{
if (!irr_driver->supportsSplatting()) continue;
}
else if (condition == "trophies")
{
// Associate force fields and challenges
// FIXME: this assumes that challenges will appear before force fields in scene.xml
// (which however seems to be the case atm)
int closest_challenge_id = -1;
float closest_distance = 99999.0f;
for (unsigned int c=0; c<m_challenges.size(); c++)
{
float dist = xyz.getDistanceFromSQ(m_challenges[c].m_position);
if (closest_challenge_id == -1 || dist < closest_distance)
{
closest_challenge_id = c;
closest_distance = dist;
}
}
assert(closest_challenge_id >= 0);
assert(closest_challenge_id < (int)m_challenges.size());
const std::string &s = m_challenges[closest_challenge_id].m_challenge_id;
const ChallengeData* challenge = unlock_manager->getChallengeData(s);
if (challenge == NULL)
{
if (s != "tutorial")
Log::error("track", "Cannot find challenge named '%s'\n",
m_challenges[closest_challenge_id].m_challenge_id.c_str());
continue;
}
const unsigned int val = challenge->getNumTrophies();
bool shown = (PlayerManager::getCurrentPlayer()->getPoints() < val);
m_force_fields.push_back(OverworldForceField(xyz, shown, val));
m_challenges[closest_challenge_id].setForceField(
m_force_fields[m_force_fields.size() - 1]);
core::stringw msg = StringUtils::toWString(val);
core::dimension2d<u32> textsize = GUIEngine::getHighresDigitFont()
->getDimension(msg.c_str());
assert(GUIEngine::getHighresDigitFont() != NULL);
if (CVS->isGLSL())
{
gui::ScalableFont* font = GUIEngine::getHighresDigitFont();
STKTextBillboard* tb = new STKTextBillboard(msg.c_str(), font,
video::SColor(255, 255, 225, 0),
video::SColor(255, 255, 89, 0),
irr_driver->getSceneManager()->getRootSceneNode(),
irr_driver->getSceneManager(), -1, xyz,
core::vector3df(1.5f, 1.5f, 1.5f));
m_all_nodes.push_back(tb);
}
else
{
scene::ISceneManager* sm = irr_driver->getSceneManager();
scene::ISceneNode* sn =
sm->addBillboardTextSceneNode(GUIEngine::getHighresDigitFont(),
msg.c_str(),
NULL,
core::dimension2df(textsize.Width / 35.0f,
textsize.Height / 35.0f),
xyz,
-1, // id
video::SColor(255, 255, 225, 0),
video::SColor(255, 255, 89, 0));
m_all_nodes.push_back(sn);
}
if (!shown) continue;
}
else if (condition.size() > 0)
{
unsigned char result = -1;
Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
std::function<void(asIScriptContext*)> null_callback;
script_engine->runFunction(true, "bool " + condition + "()", null_callback,
[&](asIScriptContext* ctx) { result = ctx->GetReturnByte(); });
if (result == 0)
continue;
}
std::string neg_condition;
n->get("ifnot", &neg_condition);
if (neg_condition == "splatting")
{
if (irr_driver->supportsSplatting()) continue;
}
else if (neg_condition.size() > 0)
{
unsigned char result = -1;
Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
std::function<void(asIScriptContext*)> null_callback;
script_engine->runFunction(true, "bool " + neg_condition + "()", null_callback,
[&](asIScriptContext* ctx) { result = ctx->GetReturnByte(); });
if (result != 0)
continue;
}
bool tangent = false;
n->get("tangents", &tangent);
@ -1253,49 +1140,6 @@ bool Track::loadMainTrack(const XMLNode &root)
bool lod_instance = false;
n->get("lod_instance", &lod_instance);
/*
if (tangent)
{
scene::IMesh* original_mesh = irr_driver->getMesh(full_path);
if (std::find(m_detached_cached_meshes.begin(),
m_detached_cached_meshes.end(),
original_mesh) == m_detached_cached_meshes.end())
{
m_detached_cached_meshes.push_back(original_mesh);
}
// create a node out of this mesh just for bullet; delete it after, normal maps are special
// and require tangent meshes
scene_node = irr_driver->addMesh(original_mesh, "original_mesh");
scene_node->setPosition(xyz);
scene_node->setRotation(hpr);
scene_node->setScale(scale);
convertTrackToBullet(scene_node);
scene_node->remove();
irr_driver->grabAllTextures(original_mesh);
scene::IMesh* mesh = MeshTools::createMeshWithTangents(original_mesh, &MeshTools::isNormalMap);
mesh->grab();
irr_driver->grabAllTextures(mesh);
m_all_cached_meshes.push_back(mesh);
scene_node = irr_driver->addMesh(mesh, "original_mesh_with_tangents");
scene_node->setPosition(xyz);
scene_node->setRotation(hpr);
scene_node->setScale(scale);
#ifdef DEBUG
std::string debug_name = model_name+" (tangent static track-object)";
scene_node->setName(debug_name.c_str());
#endif
handleAnimatedTextures(scene_node, *n);
m_all_nodes.push_back( scene_node );
}
else*/
if (lod_instance)
{
LODNode* node = lodLoader.instanciateAsLOD(n, NULL);
@ -1345,6 +1189,7 @@ bool Track::loadMainTrack(const XMLNode &root)
handleAnimatedTextures(scene_node, *n);
// for challenge orbs, a bit more work to do
// TODO: this is hardcoded for the overworld, convert to scripting
if (challenge.size() > 0)
{
const ChallengeData* c = NULL;
@ -1810,6 +1655,8 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
model_def_loader.cleanLibraryNodesAfterLoad();
World::getWorld()->getScriptEngine()->compileLoadedScripts();
// Init all track objects
m_track_object_manager->init();

View File

@ -69,30 +69,10 @@ namespace Scripting
const int HEIGHT_MAP_RESOLUTION = 256;
struct OverworldForceField
{
core::vector3df m_position;
bool m_is_locked;
int m_required_points;
OverworldForceField()
{
}
OverworldForceField(core::vector3df position, bool is_locked, int required_points)
{
m_position = position;
m_is_locked = is_locked;
m_required_points = required_points;
}
};
// TODO: eventually remove this and fully replace with scripting
struct OverworldChallenge
{
private:
OverworldForceField m_force_field;
bool m_force_field_set;
public:
core::vector3df m_position;
std::string m_challenge_id;
@ -100,27 +80,6 @@ public:
{
m_position = position;
m_challenge_id = challenge_id;
m_force_field_set = false;
}
void setForceField(OverworldForceField f)
{
m_force_field = f;
m_force_field_set = true;
}
OverworldForceField& getForceField()
{
assert(m_force_field_set);
return m_force_field;
}
bool isForceFieldSet() const { return m_force_field_set; }
const OverworldForceField& getForceField() const
{
assert(m_force_field_set);
return m_force_field;
}
};
@ -160,8 +119,6 @@ private:
/** Will only be used on overworld */
std::vector<OverworldChallenge> m_challenges;
std::vector<OverworldForceField> m_force_fields;
std::vector<Subtitle> m_subtitles;
/** Start transforms of karts (either the default, or the ones taken

View File

@ -131,23 +131,11 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
m_type = type;
m_initially_visible = true;
std::string condition;
xml_node.get("if", &condition);
if (condition == "false")
xml_node.get("if", &m_visibility_condition);
if (m_visibility_condition == "false")
{
m_initially_visible = false;
}
else if (condition.size() > 0)
{
unsigned char result = -1;
Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
std::function<void(asIScriptContext*)> null_callback;
script_engine->runFunction(true, "bool " + condition + "()", null_callback,
[&](asIScriptContext* ctx) { result = ctx->GetReturnByte(); });
if (result == 0)
m_initially_visible = false;
}
if (!m_initially_visible)
setEnabled(false);
@ -295,6 +283,68 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
// ----------------------------------------------------------------------------
void TrackObject::onWorldReady()
{
if (m_visibility_condition == "false")
{
m_initially_visible = false;
}
else if (m_visibility_condition.size() > 0)
{
unsigned char result = -1;
Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
std::ostringstream fn_signature;
std::vector<std::string> arguments;
if (m_visibility_condition.find("(") != std::string::npos &&
m_visibility_condition.find(")") != std::string::npos)
{
// There are arguments to pass to the function
// TODO: For the moment we only support string arguments
// TODO: this parsing could be improved
unsigned first = m_visibility_condition.find("(");
unsigned last = m_visibility_condition.find_last_of(")");
std::string fn_name = m_visibility_condition.substr(0, first);
std::string str_arguments = m_visibility_condition.substr(first + 1, last - first - 1);
arguments = StringUtils::split(str_arguments, ',');
fn_signature << "bool " << fn_name << "(";
for (int i = 0; i < arguments.size(); i++)
{
if (i > 0)
fn_signature << ",";
fn_signature << "string";
}
fn_signature << ",Track::TrackObject@)";
}
else
{
fn_signature << "bool " << m_visibility_condition << "(Track::TrackObject@)";
}
TrackObject* self = this;
script_engine->runFunction(true, fn_signature.str(),
[&](asIScriptContext* ctx)
{
for (int i = 0; i < arguments.size(); i++)
{
ctx->SetArgObject(i, &arguments[i]);
}
ctx->SetArgObject(arguments.size(), self);
},
[&](asIScriptContext* ctx) { result = ctx->GetReturnByte(); });
if (result == 0)
m_initially_visible = false;
}
if (!m_initially_visible)
setEnabled(false);
}
// ----------------------------------------------------------------------------
/** Destructor. Removes the node from the scene graph, and also
* drops the textures of the mesh. Sound buffers are also freed.
*/
@ -456,6 +506,17 @@ const core::vector3df& TrackObject::getPosition() const
return m_init_xyz;
} // getPosition
// ----------------------------------------------------------------------------
const core::vector3df TrackObject::getAbsoluteCenterPosition() const
{
if (m_presentation != NULL)
return m_presentation->getAbsoluteCenterPosition();
else
return m_init_xyz;
} // getAbsolutePosition
// ----------------------------------------------------------------------------
const core::vector3df TrackObject::getAbsolutePosition() const

View File

@ -94,6 +94,8 @@ protected:
bool m_initially_visible;
std::string m_visibility_condition;
void init(const XMLNode &xml_node, scene::ISceneNode* parent,
ModelDefinitionLoader& model_def_loader,
TrackObject* parent_library);
@ -120,6 +122,7 @@ public:
virtual void reset();
const core::vector3df& getPosition() const;
const core::vector3df getAbsolutePosition() const;
const core::vector3df getAbsoluteCenterPosition() const;
const core::vector3df& getRotation() const;
const core::vector3df& getScale() const;
bool castRay(const btVector3 &from,
@ -135,7 +138,7 @@ public:
// ------------------------------------------------------------------------
/** To finish object constructions. Called after the track model
* is ready. */
virtual void init() {};
virtual void onWorldReady();
// ------------------------------------------------------------------------
/** Called when an explosion happens. As a default does nothing, will
* e.g. be overwritten by physical objects etc. */

View File

@ -66,11 +66,9 @@ void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent,
*/
void TrackObjectManager::init()
{
TrackObject* curr;
for_in (curr, m_all_objects)
for_var_in(TrackObject*, curr, m_all_objects)
{
curr->init();
curr->onWorldReady();
}
} // reset
// ----------------------------------------------------------------------------

View File

@ -88,6 +88,16 @@ const core::vector3df TrackObjectPresentationSceneNode::getAbsolutePosition() co
return m_node->getAbsolutePosition();
} // getAbsolutePosition
// ----------------------------------------------------------------------------
const core::vector3df& TrackObjectPresentationSceneNode::getAbsoluteCenterPosition() const
{
if (m_node == NULL) return m_init_xyz;
m_node->updateAbsolutePosition();
core::aabbox3d<f32> bounds = m_node->getTransformedBoundingBox();
return bounds.getCenter();
}
// ----------------------------------------------------------------------------
const core::vector3df& TrackObjectPresentationSceneNode::getRotation() const
{

View File

@ -100,6 +100,11 @@ public:
return m_init_xyz;
} // getAbsolutePosition
// ------------------------------------------------------------------------
virtual const core::vector3df& getAbsoluteCenterPosition() const
{
return m_init_xyz;
}
// ------------------------------------------------------------------------
/** Returns the initial rotation. */
virtual const core::vector3df& getRotation() const { return m_init_hpr; }
// ------------------------------------------------------------------------
@ -141,6 +146,7 @@ public:
// ------------------------------------------------------------------------
virtual const core::vector3df& getPosition() const OVERRIDE;
virtual const core::vector3df getAbsolutePosition() const OVERRIDE;
virtual const core::vector3df& getAbsoluteCenterPosition() const OVERRIDE;
virtual const core::vector3df& getRotation() const OVERRIDE;
virtual const core::vector3df& getScale() const OVERRIDE;
virtual void move(const core::vector3df& xyz, const core::vector3df& hpr,