Renormalise line endings

This should replace accidental CRLF with LF
make_linux_ci_do_zoomies
AnyOldName3 2 years ago
parent 4d01489011
commit 84f8a6848a

@ -1,63 +1,63 @@
#include "aiactivate.hpp"
#include <components/esm3/aisequence.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwworld/class.hpp"
#include "creaturestats.hpp"
#include "movement.hpp"
#include "steering.hpp"
namespace MWMechanics
{
AiActivate::AiActivate(std::string_view objectId, bool repeat)
: TypedAiPackage<AiActivate>(repeat), mObjectId(objectId)
{
}
bool AiActivate::execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
{
const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow
actor.getClass().getCreatureStats(actor).setDrawState(DrawState::Nothing);
// Stop if the target doesn't exist
// Really we should be checking whether the target is currently registered with the MechanicsManager
if (target == MWWorld::Ptr() || !target.getRefData().getCount() || !target.getRefData().isEnabled())
return true;
// Turn to target and move to it directly, without pathfinding.
const osg::Vec3f targetDir = target.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3();
zTurn(actor, std::atan2(targetDir.x(), targetDir.y()), 0.f);
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
actor.getClass().getMovementSettings(actor).mPosition[0] = 0;
if (MWBase::Environment::get().getWorld()->getMaxActivationDistance() >= targetDir.length())
{
// Note: we intentionally do not cancel package after activation here for backward compatibility with original engine.
MWBase::Environment::get().getWorld()->activate(target, actor);
}
return false;
}
void AiActivate::writeState(ESM::AiSequence::AiSequence &sequence) const
{
auto activate = std::make_unique<ESM::AiSequence::AiActivate>();
activate->mTargetId = mObjectId;
activate->mRepeat = getRepeat();
ESM::AiSequence::AiPackageContainer package;
package.mType = ESM::AiSequence::Ai_Activate;
package.mPackage = std::move(activate);
sequence.mPackages.push_back(std::move(package));
}
AiActivate::AiActivate(const ESM::AiSequence::AiActivate *activate)
: AiActivate(activate->mTargetId, activate->mRepeat)
{
}
}
#include "aiactivate.hpp"
#include <components/esm3/aisequence.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwworld/class.hpp"
#include "creaturestats.hpp"
#include "movement.hpp"
#include "steering.hpp"
namespace MWMechanics
{
AiActivate::AiActivate(std::string_view objectId, bool repeat)
: TypedAiPackage<AiActivate>(repeat), mObjectId(objectId)
{
}
bool AiActivate::execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
{
const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow
actor.getClass().getCreatureStats(actor).setDrawState(DrawState::Nothing);
// Stop if the target doesn't exist
// Really we should be checking whether the target is currently registered with the MechanicsManager
if (target == MWWorld::Ptr() || !target.getRefData().getCount() || !target.getRefData().isEnabled())
return true;
// Turn to target and move to it directly, without pathfinding.
const osg::Vec3f targetDir = target.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3();
zTurn(actor, std::atan2(targetDir.x(), targetDir.y()), 0.f);
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
actor.getClass().getMovementSettings(actor).mPosition[0] = 0;
if (MWBase::Environment::get().getWorld()->getMaxActivationDistance() >= targetDir.length())
{
// Note: we intentionally do not cancel package after activation here for backward compatibility with original engine.
MWBase::Environment::get().getWorld()->activate(target, actor);
}
return false;
}
void AiActivate::writeState(ESM::AiSequence::AiSequence &sequence) const
{
auto activate = std::make_unique<ESM::AiSequence::AiActivate>();
activate->mTargetId = mObjectId;
activate->mRepeat = getRepeat();
ESM::AiSequence::AiPackageContainer package;
package.mType = ESM::AiSequence::Ai_Activate;
package.mPackage = std::move(activate);
sequence.mPackages.push_back(std::move(package));
}
AiActivate::AiActivate(const ESM::AiSequence::AiActivate *activate)
: AiActivate(activate->mTargetId, activate->mRepeat)
{
}
}

@ -1,40 +1,40 @@
#ifndef GAME_MWMECHANICS_AIACTIVATE_H
#define GAME_MWMECHANICS_AIACTIVATE_H
#include "typedaipackage.hpp"
#include <string>
#include <string_view>
namespace ESM
{
namespace AiSequence
{
struct AiActivate;
}
}
namespace MWMechanics
{
/// \brief Causes actor to walk to activatable object and activate it
/** Will activate when close to object **/
class AiActivate final : public TypedAiPackage<AiActivate>
{
public:
/// Constructor
/** \param objectId Reference to object to activate **/
explicit AiActivate(std::string_view objectId, bool repeat);
explicit AiActivate(const ESM::AiSequence::AiActivate* activate);
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override;
static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Activate; }
void writeState(ESM::AiSequence::AiSequence& sequence) const override;
private:
const std::string mObjectId;
};
}
#endif // GAME_MWMECHANICS_AIACTIVATE_H
#ifndef GAME_MWMECHANICS_AIACTIVATE_H
#define GAME_MWMECHANICS_AIACTIVATE_H
#include "typedaipackage.hpp"
#include <string>
#include <string_view>
namespace ESM
{
namespace AiSequence
{
struct AiActivate;
}
}
namespace MWMechanics
{
/// \brief Causes actor to walk to activatable object and activate it
/** Will activate when close to object **/
class AiActivate final : public TypedAiPackage<AiActivate>
{
public:
/// Constructor
/** \param objectId Reference to object to activate **/
explicit AiActivate(std::string_view objectId, bool repeat);
explicit AiActivate(const ESM::AiSequence::AiActivate* activate);
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override;
static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Activate; }
void writeState(ESM::AiSequence::AiSequence& sequence) const override;
private:
const std::string mObjectId;
};
}
#endif // GAME_MWMECHANICS_AIACTIVATE_H

@ -1,123 +1,123 @@
#include "aiescort.hpp"
#include <components/esm3/aisequence.hpp>
#include <components/esm3/loadcell.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp"
#include "creaturestats.hpp"
#include "movement.hpp"
/*
TODO: Different behavior for AIEscort a d x y z and AIEscortCell a c d x y z.
TODO: Take account for actors being in different cells.
*/
namespace MWMechanics
{
AiEscort::AiEscort(std::string_view actorId, int duration, float x, float y, float z, bool repeat)
: TypedAiPackage<AiEscort>(repeat), mX(x), mY(y), mZ(z), mDuration(duration), mRemainingDuration(static_cast<float>(duration))
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = std::string(actorId);
}
AiEscort::AiEscort(std::string_view actorId, std::string_view cellId, int duration, float x, float y, float z, bool repeat)
: TypedAiPackage<AiEscort>(repeat), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration), mRemainingDuration(static_cast<float>(duration))
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = std::string(actorId);
}
AiEscort::AiEscort(const ESM::AiSequence::AiEscort *escort)
: TypedAiPackage<AiEscort>(escort->mRepeat), mCellId(escort->mCellId), mX(escort->mData.mX), mY(escort->mData.mY), mZ(escort->mData.mZ)
, mDuration(escort->mData.mDuration)
, mRemainingDuration(escort->mRemainingDuration)
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = escort->mTargetId;
mTargetActorId = escort->mTargetActorId;
}
bool AiEscort::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
{
// If AiEscort has ran for as long or longer then the duration specified
// and the duration is not infinite, the package is complete.
if (mDuration > 0)
{
mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
if (mRemainingDuration <= 0)
{
mRemainingDuration = mDuration;
return true;
}
}
if (!mCellId.empty() && mCellId != actor.getCell()->getCell()->getCellId().mWorldspace)
return false; // Not in the correct cell, pause and rely on the player to go back through a teleport door
actor.getClass().getCreatureStats(actor).setDrawState(DrawState::Nothing);
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false);
const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->getPtr(mTargetActorRefId, false);
const osg::Vec3f leaderPos = actor.getRefData().getPosition().asVec3();
const osg::Vec3f followerPos = follower.getRefData().getPosition().asVec3();
const osg::Vec3f halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor);
const float maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
if ((leaderPos - followerPos).length2() <= mMaxDist * mMaxDist)
{
const osg::Vec3f dest(mX, mY, mZ);
if (pathTo(actor, dest, duration, maxHalfExtent)) //Returns true on path complete
{
mRemainingDuration = mDuration;
return true;
}
mMaxDist = maxHalfExtent + 450.0f;
}
else
{
// Stop moving if the player is too far away
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle3", 0, 1);
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
mMaxDist = maxHalfExtent + 250.0f;
}
return false;
}
void AiEscort::writeState(ESM::AiSequence::AiSequence &sequence) const
{
auto escort = std::make_unique<ESM::AiSequence::AiEscort>();
escort->mData.mX = mX;
escort->mData.mY = mY;
escort->mData.mZ = mZ;
escort->mData.mDuration = mDuration;
escort->mTargetId = mTargetActorRefId;
escort->mTargetActorId = mTargetActorId;
escort->mRemainingDuration = mRemainingDuration;
escort->mCellId = mCellId;
escort->mRepeat = getRepeat();
ESM::AiSequence::AiPackageContainer package;
package.mType = ESM::AiSequence::Ai_Escort;
package.mPackage = std::move(escort);
sequence.mPackages.push_back(std::move(package));
}
void AiEscort::fastForward(const MWWorld::Ptr& actor, AiState &state)
{
// Update duration counter if this package has a duration
if (mDuration > 0)
mRemainingDuration--;
}
}
#include "aiescort.hpp"
#include <components/esm3/aisequence.hpp>
#include <components/esm3/loadcell.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp"
#include "creaturestats.hpp"
#include "movement.hpp"
/*
TODO: Different behavior for AIEscort a d x y z and AIEscortCell a c d x y z.
TODO: Take account for actors being in different cells.
*/
namespace MWMechanics
{
AiEscort::AiEscort(std::string_view actorId, int duration, float x, float y, float z, bool repeat)
: TypedAiPackage<AiEscort>(repeat), mX(x), mY(y), mZ(z), mDuration(duration), mRemainingDuration(static_cast<float>(duration))
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = std::string(actorId);
}
AiEscort::AiEscort(std::string_view actorId, std::string_view cellId, int duration, float x, float y, float z, bool repeat)
: TypedAiPackage<AiEscort>(repeat), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration), mRemainingDuration(static_cast<float>(duration))
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = std::string(actorId);
}
AiEscort::AiEscort(const ESM::AiSequence::AiEscort *escort)
: TypedAiPackage<AiEscort>(escort->mRepeat), mCellId(escort->mCellId), mX(escort->mData.mX), mY(escort->mData.mY), mZ(escort->mData.mZ)
, mDuration(escort->mData.mDuration)
, mRemainingDuration(escort->mRemainingDuration)
, mCellX(std::numeric_limits<int>::max())
, mCellY(std::numeric_limits<int>::max())
{
mTargetActorRefId = escort->mTargetId;
mTargetActorId = escort->mTargetActorId;
}
bool AiEscort::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
{
// If AiEscort has ran for as long or longer then the duration specified
// and the duration is not infinite, the package is complete.
if (mDuration > 0)
{
mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
if (mRemainingDuration <= 0)
{
mRemainingDuration = mDuration;
return true;
}
}
if (!mCellId.empty() && mCellId != actor.getCell()->getCell()->getCellId().mWorldspace)
return false; // Not in the correct cell, pause and rely on the player to go back through a teleport door
actor.getClass().getCreatureStats(actor).setDrawState(DrawState::Nothing);
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false);
const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->getPtr(mTargetActorRefId, false);
const osg::Vec3f leaderPos = actor.getRefData().getPosition().asVec3();
const osg::Vec3f followerPos = follower.getRefData().getPosition().asVec3();
const osg::Vec3f halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor);
const float maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
if ((leaderPos - followerPos).length2() <= mMaxDist * mMaxDist)
{
const osg::Vec3f dest(mX, mY, mZ);
if (pathTo(actor, dest, duration, maxHalfExtent)) //Returns true on path complete
{
mRemainingDuration = mDuration;
return true;
}
mMaxDist = maxHalfExtent + 450.0f;
}
else
{
// Stop moving if the player is too far away
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle3", 0, 1);
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
mMaxDist = maxHalfExtent + 250.0f;
}
return false;
}
void AiEscort::writeState(ESM::AiSequence::AiSequence &sequence) const
{
auto escort = std::make_unique<ESM::AiSequence::AiEscort>();
escort->mData.mX = mX;
escort->mData.mY = mY;
escort->mData.mZ = mZ;
escort->mData.mDuration = mDuration;
escort->mTargetId = mTargetActorRefId;
escort->mTargetActorId = mTargetActorId;
escort->mRemainingDuration = mRemainingDuration;
escort->mCellId = mCellId;
escort->mRepeat = getRepeat();
ESM::AiSequence::AiPackageContainer package;
package.mType = ESM::AiSequence::Ai_Escort;
package.mPackage = std::move(escort);
sequence.mPackages.push_back(std::move(package));
}
void AiEscort::fastForward(const MWWorld::Ptr& actor, AiState &state)
{
// Update duration counter if this package has a duration
if (mDuration > 0)
mRemainingDuration--;
}
}

@ -1,71 +1,71 @@
#ifndef GAME_MWMECHANICS_AITRAVEL_H
#define GAME_MWMECHANICS_AITRAVEL_H
#include "typedaipackage.hpp"
namespace ESM
{
namespace AiSequence
{
struct AiTravel;
}
}
namespace MWMechanics
{
struct AiInternalTravel;
/// \brief Causes the AI to travel to the specified point
class AiTravel : public TypedAiPackage<AiTravel>
{
public:
AiTravel(float x, float y, float z, bool repeat, AiTravel* derived);
AiTravel(float x, float y, float z, AiInternalTravel* derived);
AiTravel(float x, float y, float z, bool repeat);
explicit AiTravel(const ESM::AiSequence::AiTravel* travel);
/// Simulates the passing of time
void fastForward(const MWWorld::Ptr& actor, AiState& state) override;
void writeState(ESM::AiSequence::AiSequence &sequence) const override;
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override;
static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Travel; }
static constexpr Options makeDefaultOptions()
{
AiPackage::Options options;
options.mUseVariableSpeed = true;
options.mAlwaysActive = true;
return options;
}
osg::Vec3f getDestination() const override { return osg::Vec3f(mX, mY, mZ); }
private:
const float mX;
const float mY;
const float mZ;
const bool mHidden;
float mDestinationTimer;
};
struct AiInternalTravel final : public AiTravel
{
AiInternalTravel(float x, float y, float z);
explicit AiInternalTravel(const ESM::AiSequence::AiTravel* travel);
static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::InternalTravel; }
std::unique_ptr<AiPackage> clone() const override;
};
}
#endif
#ifndef GAME_MWMECHANICS_AITRAVEL_H
#define GAME_MWMECHANICS_AITRAVEL_H
#include "typedaipackage.hpp"
namespace ESM
{
namespace AiSequence
{
struct AiTravel;
}
}
namespace MWMechanics
{
struct AiInternalTravel;
/// \brief Causes the AI to travel to the specified point
class AiTravel : public TypedAiPackage<AiTravel>
{
public:
AiTravel(float x, float y, float z, bool repeat, AiTravel* derived);
AiTravel(float x, float y, float z, AiInternalTravel* derived);
AiTravel(float x, float y, float z, bool repeat);
explicit AiTravel(const ESM::AiSequence::AiTravel* travel);
/// Simulates the passing of time
void fastForward(const MWWorld::Ptr& actor, AiState& state) override;
void writeState(ESM::AiSequence::AiSequence &sequence) const override;
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override;
static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Travel; }
static constexpr Options makeDefaultOptions()
{
AiPackage::Options options;
options.mUseVariableSpeed = true;
options.mAlwaysActive = true;
return options;
}
osg::Vec3f getDestination() const override { return osg::Vec3f(mX, mY, mZ); }
private:
const float mX;
const float mY;
const float mZ;
const bool mHidden;
float mDestinationTimer;
};
struct AiInternalTravel final : public AiTravel
{
AiInternalTravel(float x, float y, float z);
explicit AiInternalTravel(const ESM::AiSequence::AiTravel* travel);
static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::InternalTravel; }
std::unique_ptr<AiPackage> clone() const override;
};
}
#endif

@ -1,75 +1,75 @@
#include "weatherstate.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
namespace ESM
{
namespace
{
constexpr NAME currentRegionRecord = "CREG";
constexpr NAME timePassedRecord = "TMPS";
constexpr NAME fastForwardRecord = "FAST";
constexpr NAME weatherUpdateTimeRecord = "WUPD";
constexpr NAME transitionFactorRecord = "TRFC";
constexpr NAME currentWeatherRecord = "CWTH";
constexpr NAME nextWeatherRecord = "NWTH";
constexpr NAME queuedWeatherRecord = "QWTH";
constexpr NAME regionNameRecord = "RGNN";
constexpr NAME regionWeatherRecord = "RGNW";
constexpr NAME regionChanceRecord = "RGNC";
}
}
namespace ESM
{
void WeatherState::load(ESMReader& esm)
{
mCurrentRegion = esm.getHNString(currentRegionRecord);
esm.getHNT(mTimePassed, timePassedRecord);
esm.getHNT(mFastForward, fastForwardRecord);
esm.getHNT(mWeatherUpdateTime, weatherUpdateTimeRecord);
esm.getHNT(mTransitionFactor, transitionFactorRecord);
esm.getHNT(mCurrentWeather, currentWeatherRecord);
esm.getHNT(mNextWeather, nextWeatherRecord);
esm.getHNT(mQueuedWeather, queuedWeatherRecord);
while (esm.isNextSub(regionNameRecord))
{
std::string regionID = esm.getHString();
RegionWeatherState region;
esm.getHNT(region.mWeather, regionWeatherRecord);
while (esm.isNextSub(regionChanceRecord))
{
char chance;
esm.getHT(chance);
region.mChances.push_back(chance);
}
mRegions.insert(std::make_pair(regionID, region));
}
}
void WeatherState::save(ESMWriter& esm) const
{
esm.writeHNCString(currentRegionRecord, mCurrentRegion);
esm.writeHNT(timePassedRecord, mTimePassed);
esm.writeHNT(fastForwardRecord, mFastForward);
esm.writeHNT(weatherUpdateTimeRecord, mWeatherUpdateTime);
esm.writeHNT(transitionFactorRecord, mTransitionFactor);
esm.writeHNT(currentWeatherRecord, mCurrentWeather);
esm.writeHNT(nextWeatherRecord, mNextWeather);
esm.writeHNT(queuedWeatherRecord, mQueuedWeather);
std::map<std::string, RegionWeatherState>::const_iterator it = mRegions.begin();
for(; it != mRegions.end(); ++it)
{
esm.writeHNCString(regionNameRecord, it->first.c_str());
esm.writeHNT(regionWeatherRecord, it->second.mWeather);
for(size_t i = 0; i < it->second.mChances.size(); ++i)
{
esm.writeHNT(regionChanceRecord, it->second.mChances[i]);
}
}
}
}
#include "weatherstate.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
namespace ESM
{
namespace
{
constexpr NAME currentRegionRecord = "CREG";
constexpr NAME timePassedRecord = "TMPS";
constexpr NAME fastForwardRecord = "FAST";
constexpr NAME weatherUpdateTimeRecord = "WUPD";
constexpr NAME transitionFactorRecord = "TRFC";
constexpr NAME currentWeatherRecord = "CWTH";
constexpr NAME nextWeatherRecord = "NWTH";
constexpr NAME queuedWeatherRecord = "QWTH";
constexpr NAME regionNameRecord = "RGNN";
constexpr NAME regionWeatherRecord = "RGNW";
constexpr NAME regionChanceRecord = "RGNC";
}
}
namespace ESM
{
void WeatherState::load(ESMReader& esm)
{
mCurrentRegion = esm.getHNString(currentRegionRecord);
esm.getHNT(mTimePassed, timePassedRecord);
esm.getHNT(mFastForward, fastForwardRecord);
esm.getHNT(mWeatherUpdateTime, weatherUpdateTimeRecord);
esm.getHNT(mTransitionFactor, transitionFactorRecord);
esm.getHNT(mCurrentWeather, currentWeatherRecord);
esm.getHNT(mNextWeather, nextWeatherRecord);
esm.getHNT(mQueuedWeather, queuedWeatherRecord);
while (esm.isNextSub(regionNameRecord))
{
std::string regionID = esm.getHString();
RegionWeatherState region;
esm.getHNT(region.mWeather, regionWeatherRecord);
while (esm.isNextSub(regionChanceRecord))
{
char chance;
esm.getHT(chance);
region.mChances.push_back(chance);
}
mRegions.insert(std::make_pair(regionID, region));
}
}
void WeatherState::save(ESMWriter& esm) const
{
esm.writeHNCString(currentRegionRecord, mCurrentRegion);
esm.writeHNT(timePassedRecord, mTimePassed);
esm.writeHNT(fastForwardRecord, mFastForward);
esm.writeHNT(weatherUpdateTimeRecord, mWeatherUpdateTime);
esm.writeHNT(transitionFactorRecord, mTransitionFactor);
esm.writeHNT(currentWeatherRecord, mCurrentWeather);
esm.writeHNT(nextWeatherRecord, mNextWeather);
esm.writeHNT(queuedWeatherRecord, mQueuedWeather);
std::map<std::string, RegionWeatherState>::const_iterator it = mRegions.begin();
for(; it != mRegions.end(); ++it)
{
esm.writeHNCString(regionNameRecord, it->first.c_str());
esm.writeHNT(regionWeatherRecord, it->second.mWeather);
for(size_t i = 0; i < it->second.mChances.size(); ++i)
{
esm.writeHNT(regionChanceRecord, it->second.mChances[i]);
}
}
}
}

@ -1,36 +1,36 @@
#ifndef OPENMW_ESM_WEATHERSTATE_H
#define OPENMW_ESM_WEATHERSTATE_H
#include <map>
#include <string>
#include <vector>
namespace ESM
{
class ESMReader;
class ESMWriter;
struct RegionWeatherState
{
int mWeather;
std::vector<char> mChances;
};
struct WeatherState
{
std::string mCurrentRegion;
float mTimePassed;
bool mFastForward;
float mWeatherUpdateTime;
float mTransitionFactor;
int mCurrentWeather;
int mNextWeather;
int mQueuedWeather;
std::map<std::string, RegionWeatherState> mRegions;
void load(ESMReader& esm);
void save(ESMWriter& esm) const;
};
}
#endif
#ifndef OPENMW_ESM_WEATHERSTATE_H
#define OPENMW_ESM_WEATHERSTATE_H
#include <map>
#include <string>
#include <vector>
namespace ESM
{
class ESMReader;
class ESMWriter;
struct RegionWeatherState
{
int mWeather;
std::vector<char> mChances;
};
struct WeatherState
{
std::string mCurrentRegion;
float mTimePassed;
bool mFastForward;
float mWeatherUpdateTime;
float mTransitionFactor;
int mCurrentWeather;
int mNextWeather;
int mQueuedWeather;
std::map<std::string, RegionWeatherState> mRegions;
void load(ESMReader& esm);
void save(ESMWriter& esm) const;
};
}
#endif

@ -1,40 +1,40 @@
#include "myguiloglistener.hpp"
#include <iomanip>
#include <components/debug/debuglog.hpp>
namespace osgMyGUI
{
void CustomLogListener::open()
{
mStream.open(mFileName, std::ios_base::out);
if (!mStream.is_open())
Log(Debug::Error) << "Unable to create MyGUI log with path " << mFileName;
}
void CustomLogListener::close()
{
if (mStream.is_open())
mStream.close();
}
void CustomLogListener::flush()
{
if (mStream.is_open())
mStream.flush();
}
void CustomLogListener::log(const std::string& _section, MyGUI::LogLevel _level, const struct tm* _time, const std::string& _message, const char* _file, int _line)
{
if (mStream.is_open())
{
const char* separator = " | ";
mStream << std::setw(2) << std::setfill('0') << _time->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << _time->tm_min << ":"
<< std::setw(2) << std::setfill('0') << _time->tm_sec << separator
<< _section << separator << _level.print() << separator
<< _message << separator << _file << separator << _line << std::endl;
}
}
}
#include "myguiloglistener.hpp"
#include <iomanip>
#include <components/debug/debuglog.hpp>
namespace osgMyGUI
{
void CustomLogListener::open()
{
mStream.open(mFileName, std::ios_base::out);
if (!mStream.is_open())
Log(Debug::Error) << "Unable to create MyGUI log with path " << mFileName;
}
void CustomLogListener::close()
{
if (mStream.is_open())
mStream.close();
}
void CustomLogListener::flush()
{
if (mStream.is_open())
mStream.flush();
}
void CustomLogListener::log(const std::string& _section, MyGUI::LogLevel _level, const struct tm* _time, const std::string& _message, const char* _file, int _line)
{
if (mStream.is_open())
{
const char* separator = " | ";
mStream << std::setw(2) << std::setfill('0') << _time->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << _time->tm_min << ":"
<< std::setw(2) << std::setfill('0') << _time->tm_sec << separator
<< _section << separator << _level.print() << separator
<< _message << separator << _file << separator << _line << std::endl;
}
}
}

@ -1,68 +1,68 @@
#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_LOGLISTENER_H
#define OPENMW_COMPONENTS_MYGUIPLATFORM_LOGLISTENER_H
#include <string>
#include <filesystem>
#include <fstream>
#include <MyGUI_ILogListener.h>
#include <MyGUI_LogSource.h>
#include <MyGUI_ConsoleLogListener.h>
#include <MyGUI_LevelLogFilter.h>
namespace osgMyGUI
{
/// \brief Custom MyGUI::ILogListener interface implementation
/// being able to portably handle UTF-8 encoded path.
/// \todo try patching MyGUI to make this easier
class CustomLogListener : public MyGUI::ILogListener
{
public:
CustomLogListener(const std::filesystem::path &name)
: mFileName(name)
{}
~CustomLogListener() {}
void open() override;
void close() override;
void flush() override;
void log(const std::string& _section, MyGUI::LogLevel _level, const struct tm* _time, const std::string& _message, const char* _file, int _line) override;
private:
std::ofstream mStream;
std::filesystem::path mFileName;
};
/// \brief Helper class holding data that required during
/// MyGUI log creation
class LogFacility
{
MyGUI::ConsoleLogListener mConsole;
CustomLogListener mFile;
MyGUI::LevelLogFilter mFilter;
MyGUI::LogSource mSource;
public:
LogFacility(const std::filesystem::path &output, bool console)
: mFile(output)
{
mConsole.setEnabled(console);
mFilter.setLoggingLevel(MyGUI::LogLevel::Info);
mSource.addLogListener(&mFile);
mSource.addLogListener(&mConsole);
mSource.setLogFilter(&mFilter);
mSource.open();
}
MyGUI::LogSource *getSource() { return &mSource; }
};
}
#endif
#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_LOGLISTENER_H
#define OPENMW_COMPONENTS_MYGUIPLATFORM_LOGLISTENER_H
#include <string>
#include <filesystem>
#include <fstream>
#include <MyGUI_ILogListener.h>
#include <MyGUI_LogSource.h>
#include <MyGUI_ConsoleLogListener.h>
#include <MyGUI_LevelLogFilter.h>
namespace osgMyGUI
{
/// \brief Custom MyGUI::ILogListener interface implementation
/// being able to portably handle UTF-8 encoded path.
/// \todo try patching MyGUI to make this easier
class CustomLogListener : public MyGUI::ILogListener
{
public:
CustomLogListener(const std::filesystem::path &name)
: mFileName(name)
{}
~CustomLogListener() {}
void open() override;
void close() override;
void flush() override;
void log(const std::string& _section, MyGUI::LogLevel _level, const struct tm* _time, const std::string& _message, const char* _file, int _line) override;
private:
std::ofstream mStream;
std::filesystem::path mFileName;
};
/// \brief Helper class holding data that required during
/// MyGUI log creation
class LogFacility
{
MyGUI::ConsoleLogListener mConsole;
CustomLogListener mFile;
MyGUI::LevelLogFilter mFilter;
MyGUI::LogSource mSource;
public:
LogFacility(const std::filesystem::path &output, bool console)
: mFile(output)
{
mConsole.setEnabled(console);
mFilter.setLoggingLevel(MyGUI::LogLevel::Info);
mSource.addLogListener(&mFile);
mSource.addLogListener(&mConsole);
mSource.setLogFilter(&mFilter);
mSource.open();
}
MyGUI::LogSource *getSource() { return &mSource; }
};
}
#endif

@ -1,42 +1,42 @@
#ifndef OPENMW_COMPONENTS_SCENEUTIL_CLEARCOLOR_H
#define OPENMW_COMPONENTS_SCENEUTIL_CLEARCOLOR_H
#include <osg/StateAttribute>
#include <osg/Vec4f>
namespace SceneUtil
{
class ClearColor : public osg::StateAttribute
{
public:
ClearColor() : mMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) {}
ClearColor(const osg::Vec4f& color, GLbitfield mask) : mColor(color), mMask(mask) {}
ClearColor(const ClearColor& copy,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
: osg::StateAttribute(copy,copyop), mColor(copy.mColor), mMask(copy.mMask) {}
META_StateAttribute(fx, ClearColor, static_cast<osg::StateAttribute::Type>(100))
int compare(const StateAttribute& sa) const override
{
COMPARE_StateAttribute_Types(ClearColor, sa);
COMPARE_StateAttribute_Parameter(mColor);
COMPARE_StateAttribute_Parameter(mMask);
return 0;
}
void apply(osg::State& state) const override
{
glClearColor(mColor[0], mColor[1], mColor[2], mColor[3]);
glClear(mMask);
}
private:
osg::Vec4f mColor;
GLbitfield mMask;
};
}
#endif
#ifndef OPENMW_COMPONENTS_SCENEUTIL_CLEARCOLOR_H
#define OPENMW_COMPONENTS_SCENEUTIL_CLEARCOLOR_H
#include <osg/StateAttribute>
#include <osg/Vec4f>
namespace SceneUtil
{
class ClearColor : public osg::StateAttribute
{
public:
ClearColor() : mMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) {}
ClearColor(const osg::Vec4f& color, GLbitfield mask) : mColor(color), mMask(mask) {}
ClearColor(const ClearColor& copy,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
: osg::StateAttribute(copy,copyop), mColor(copy.mColor), mMask(copy.mMask) {}
META_StateAttribute(fx, ClearColor, static_cast<osg::StateAttribute::Type>(100))
int compare(const StateAttribute& sa) const override
{
COMPARE_StateAttribute_Types(ClearColor, sa);
COMPARE_StateAttribute_Parameter(mColor);
COMPARE_StateAttribute_Parameter(mMask);
return 0;
}
void apply(osg::State& state) const override
{
glClearColor(mColor[0], mColor[1], mColor[2], mColor[3]);
glClear(mMask);
}
private:
osg::Vec4f mColor;
GLbitfield mMask;
};
}
#endif

@ -1,265 +1,265 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSInputControlSystem.h"
#define B1(t) (t*t)
#define B2(t) (2*t*(1-t))
#define B3(t) ((1-t)*(1-t))
namespace ICS
{
Channel::Channel(int number, float initialValue
, float bezierMidPointY, float bezierMidPointX, float symmetricAt, float bezierStep)
: mNumber(number)
, mValue(initialValue)
, mSymmetricAt(symmetricAt)
, mBezierStep(bezierStep)
, mEnabled(true)
{
mBezierMidPoint.x = bezierMidPointX;
mBezierMidPoint.y = bezierMidPointY;
setBezierFunction(bezierMidPointY, bezierMidPointX, symmetricAt, bezierStep);
}
void Channel::setEnabled(bool enabled)
{
mEnabled = enabled;
}
float Channel::getValue()
{
if(mValue == 0 || mValue == 1)
{
return mValue;
}
assert (!mBezierFunction.empty());
BezierFunction::iterator it = mBezierFunction.begin();
//size_t size_minus_1 = mBezierFunction.size() - 1;
BezierFunction::iterator last = mBezierFunction.end();
--last;
for ( ; it != last ; )
{
BezierPoint left = (*it);
BezierPoint right = (*(++it));
if( (left.x <= mValue) && (right.x > mValue) )
{
float val = left.y - (left.x - mValue) * (left.y - right.y) / (left.x - right.x);
return std::max<float>(0.0,std::min<float>(1.0, val));
}
}
return -1;
}
void Channel::setValue(float value)
{
float previousValue = this->getValue();
mValue = value;
if(previousValue != value && mEnabled)
{
notifyListeners(previousValue);
}
}
void Channel::notifyListeners(float previousValue)
{
std::list<ChannelListener*>::iterator pos = mListeners.begin();
while (pos != mListeners.end())
{
(*pos)->channelChanged((Channel*)this, this->getValue(), previousValue);
++pos;
}
}
void Channel::addControl(Control* control, Channel::ChannelDirection dir, float percentage)
{
ControlChannelBinderItem ccBinderItem;
ccBinderItem.control = control;
ccBinderItem.direction = dir;
ccBinderItem.percentage = percentage;
mAttachedControls.push_back(ccBinderItem);
}
Channel::ControlChannelBinderItem Channel::getAttachedControlBinding(Control* control)
{
for(std::vector<ControlChannelBinderItem>::iterator it = mAttachedControls.begin() ;
it != mAttachedControls.end() ; it++)
{
if((*it).control == control)
{
return (*it);
}
}
ControlChannelBinderItem nullBinderItem;
nullBinderItem.control = NULL;
nullBinderItem.direction = Channel/*::ChannelDirection*/::DIRECT;
nullBinderItem.percentage = 0;
return nullBinderItem;
}
void Channel::update()
{
if(this->getControlsCount() == 1)
{
ControlChannelBinderItem ccBinderItem = mAttachedControls.back();
float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue();
if(ccBinderItem.direction == ICS::Channel::DIRECT)
{
this->setValue(ccBinderItem.control->getInitialValue() + (ccBinderItem.percentage * diff));
}
else
{
this->setValue(ccBinderItem.control->getInitialValue() - (ccBinderItem.percentage * diff));
}
}
else
{
float val = 0;
std::vector<ControlChannelBinderItem>::const_iterator it;
for(it=mAttachedControls.begin(); it!=mAttachedControls.end(); ++it)
{
ControlChannelBinderItem ccBinderItem = (*it);
float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue();
if(ccBinderItem.direction == ICS::Channel::DIRECT)
{
val += (ccBinderItem.percentage * diff);
}
else
{
val -= (ccBinderItem.percentage * diff);
}
}
if(mAttachedControls.size() > 0)
{
this->setValue(mAttachedControls.begin()->control->getInitialValue() + val);
}
}
}
void Channel::setBezierFunction(float bezierMidPointY, float bezierMidPointX, float symmetricAt, float bezierStep)
{
mBezierMidPoint.x = bezierMidPointX;
mBezierMidPoint.y = bezierMidPointY;
mBezierStep = bezierStep;
mSymmetricAt = symmetricAt;
mBezierFunction.clear();
BezierPoint start;
start.x = 0;
start.y = 0;
BezierPoint end;
end.x = 1;
end.y = 1;
mBezierFunction.push_front(end);
FilterInterval interval;
interval.startX = start.x;
interval.startY = start.y;
interval.midX = mBezierMidPoint.x;
interval.midY = mBezierMidPoint.y;
interval.endX = end.x;
interval.endY = end.y;
interval.step = bezierStep;
mIntervals.push_back(interval);
if(!(mBezierMidPoint.x == 0.5 && mBezierMidPoint.y == 0.5))
{
float t = mBezierStep;
while(t < 1)
{
BezierPoint p;
p.x = start.x * B1(t) + mBezierMidPoint.x * B2(t) + end.x * B3(t);
p.y = start.y * B1(t) + mBezierMidPoint.y * B2(t) + end.y * B3(t);
mBezierFunction.push_front(p);
t += mBezierStep;
}
}
mBezierFunction.push_front(start);
}
void Channel::addBezierInterval(float startX, float startY, float midX, float midY
, float endX, float endY, float step)
{
FilterInterval interval;
interval.startX = startX;
interval.startY = startY;
interval.midX = midX;
interval.midY = midY;
interval.endX = endX;
interval.endY = endY;
interval.step = step;
mIntervals.push_back(interval);
float t = 0;
while(t <= 1)
{
BezierPoint p;
p.x = startX * B1(t) + midX * B2(t) + endX * B3(t);
p.y = startY * B1(t) + midY * B2(t) + endY * B3(t);
BezierFunction::iterator it = mBezierFunction.begin();
while( it != mBezierFunction.end() )
{
BezierPoint left = (*it);
BezierPoint right;
++it;
if( it != mBezierFunction.end() )
{
right = (*it);
}
else
{
right.x = endX;
right.y = endY;
}
if(p.x > left.x && p.x < right.x)
{
mBezierFunction.insert(it, p);
break;
}
}
t += 1.0f / ((endX-startX)/step);
}
}
}
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSInputControlSystem.h"
#define B1(t) (t*t)
#define B2(t) (2*t*(1-t))
#define B3(t) ((1-t)*(1-t))
namespace ICS
{
Channel::Channel(int number, float initialValue
, float bezierMidPointY, float bezierMidPointX, float symmetricAt, float bezierStep)
: mNumber(number)
, mValue(initialValue)
, mSymmetricAt(symmetricAt)
, mBezierStep(bezierStep)
, mEnabled(true)
{
mBezierMidPoint.x = bezierMidPointX;
mBezierMidPoint.y = bezierMidPointY;
setBezierFunction(bezierMidPointY, bezierMidPointX, symmetricAt, bezierStep);
}
void Channel::setEnabled(bool enabled)
{
mEnabled = enabled;
}
float Channel::getValue()
{
if(mValue == 0 || mValue == 1)
{
return mValue;
}
assert (!mBezierFunction.empty());
BezierFunction::iterator it = mBezierFunction.begin();
//size_t size_minus_1 = mBezierFunction.size() - 1;
BezierFunction::iterator last = mBezierFunction.end();
--last;
for ( ; it != last ; )
{
BezierPoint left = (*it);
BezierPoint right = (*(++it));
if( (left.x <= mValue) && (right.x > mValue) )
{
float val = left.y - (left.x - mValue) * (left.y - right.y) / (left.x - right.x);
return std::max<float>(0.0,std::min<float>(1.0, val));
}
}
return -1;
}
void Channel::setValue(float value)
{
float previousValue = this->getValue();
mValue = value;
if(previousValue != value && mEnabled)
{
notifyListeners(previousValue);
}
}
void Channel::notifyListeners(float previousValue)
{
std::list<ChannelListener*>::iterator pos = mListeners.begin();
while (pos != mListeners.end())
{
(*pos)->channelChanged((Channel*)this, this->getValue(), previousValue);
++pos;
}
}
void Channel::addControl(Control* control, Channel::ChannelDirection dir, float percentage)
{
ControlChannelBinderItem ccBinderItem;
ccBinderItem.control = control;
ccBinderItem.direction = dir;
ccBinderItem.percentage = percentage;
mAttachedControls.push_back(ccBinderItem);
}
Channel::ControlChannelBinderItem Channel::getAttachedControlBinding(Control* control)
{
for(std::vector<ControlChannelBinderItem>::iterator it = mAttachedControls.begin() ;
it != mAttachedControls.end() ; it++)
{
if((*it).control == control)
{
return (*it);
}
}
ControlChannelBinderItem nullBinderItem;
nullBinderItem.control = NULL;
nullBinderItem.direction = Channel/*::ChannelDirection*/::DIRECT;
nullBinderItem.percentage = 0;
return nullBinderItem;
}
void Channel::update()
{
if(this->getControlsCount() == 1)
{
ControlChannelBinderItem ccBinderItem = mAttachedControls.back();
float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue();
if(ccBinderItem.direction == ICS::Channel::DIRECT)
{
this->setValue(ccBinderItem.control->getInitialValue() + (ccBinderItem.percentage * diff));
}
else
{
this->setValue(ccBinderItem.control->getInitialValue() - (ccBinderItem.percentage * diff));
}
}
else
{
float val = 0;
std::vector<ControlChannelBinderItem>::const_iterator it;
for(it=mAttachedControls.begin(); it!=mAttachedControls.end(); ++it)
{
ControlChannelBinderItem ccBinderItem = (*it);
float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue();
if(ccBinderItem.direction == ICS::Channel::DIRECT)
{
val += (ccBinderItem.percentage * diff);
}
else
{
val -= (ccBinderItem.percentage * diff);
}
}
if(mAttachedControls.size() > 0)
{
this->setValue(mAttachedControls.begin()->control->getInitialValue() + val);
}
}
}
void Channel::setBezierFunction(float bezierMidPointY, float bezierMidPointX, float symmetricAt, float bezierStep)
{
mBezierMidPoint.x = bezierMidPointX;
mBezierMidPoint.y = bezierMidPointY;
mBezierStep = bezierStep;
mSymmetricAt = symmetricAt;
mBezierFunction.clear();
BezierPoint start;
start.x = 0;
start.y = 0;
BezierPoint end;
end.x = 1;
end.y = 1;
mBezierFunction.push_front(end);
FilterInterval interval;
interval.startX = start.x;
interval.startY = start.y;
interval.midX = mBezierMidPoint.x;
interval.midY = mBezierMidPoint.y;
interval.endX = end.x;
interval.endY = end.y;
interval.step = bezierStep;
mIntervals.push_back(interval);
if(!(mBezierMidPoint.x == 0.5 && mBezierMidPoint.y == 0.5))
{
float t = mBezierStep;
while(t < 1)
{
BezierPoint p;
p.x = start.x * B1(t) + mBezierMidPoint.x * B2(t) + end.x * B3(t);
p.y = start.y * B1(t) + mBezierMidPoint.y * B2(t) + end.y * B3(t);
mBezierFunction.push_front(p);
t += mBezierStep;
}
}
mBezierFunction.push_front(start);
}
void Channel::addBezierInterval(float startX, float startY, float midX, float midY
, float endX, float endY, float step)
{
FilterInterval interval;
interval.startX = startX;
interval.startY = startY;
interval.midX = midX;
interval.midY = midY;
interval.endX = endX;
interval.endY = endY;
interval.step = step;
mIntervals.push_back(interval);
float t = 0;
while(t <= 1)
{
BezierPoint p;
p.x = startX * B1(t) + midX * B2(t) + endX * B3(t);
p.y = startY * B1(t) + midY * B2(t) + endY * B3(t);
BezierFunction::iterator it = mBezierFunction.begin();
while( it != mBezierFunction.end() )
{
BezierPoint left = (*it);
BezierPoint right;
++it;
if( it != mBezierFunction.end() )
{
right = (*it);
}
else
{
right.x = endX;
right.y = endY;
}
if(p.x > left.x && p.x < right.x)
{
mBezierFunction.insert(it, p);
break;
}
}
t += 1.0f / ((endX-startX)/step);
}
}
}

@ -1,126 +1,126 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef OICS_Channel_H_
#define OICS_Channel_H_
#include "ICSPrerequisites.h"
#include "ICSChannelListener.h"
namespace ICS
{
struct FilterInterval{
//std::string type; //! @todo uncomment when more types implemented
float startX;
float startY;
float midX;
float midY;
float endX;
float endY;
float step;
};
typedef std::list<FilterInterval> IntervalList;
class DllExport Channel
{
public:
enum ChannelDirection
{
INVERSE = -1, DIRECT = 1
};
typedef struct {
ChannelDirection direction;
float percentage;
Control* control;
} ControlChannelBinderItem;
Channel(int number, float initialValue = 0.5
, float bezierMidPointY = 0.5, float bezierMidPointX = 0.5
, float symmetricAt = 0, float bezierStep = 0.2); //! @todo implement symetry
~Channel(){};
void setValue(float value);
float getValue();
inline int getNumber(){ return mNumber; };
void addControl(Control* control, Channel::ChannelDirection dir, float percentage);
inline size_t getControlsCount(){ return mAttachedControls.size(); };
std::vector<ControlChannelBinderItem> getAttachedControls(){ return mAttachedControls; };
ControlChannelBinderItem getAttachedControlBinding(Control* control);
void addListener(ChannelListener* ob){ mListeners.push_back(ob); };
void removeListener(ChannelListener* ob){ mListeners.remove(ob); };
void update();
void setBezierFunction(float bezierMidPointY, float bezierMidPointX = 0.5
, float symmetricAt = 0, float bezierStep = 0.2);
void addBezierInterval(float startX, float startY, float midX, float midY
, float endX, float endY, float step = 0.1);
IntervalList& getIntervals(){ return mIntervals; };
void setEnabled(bool enabled);
protected:
int mNumber;
float mValue;
struct BezierPoint{
float x;
float y;
bool operator < (const BezierPoint& other){ return x < other.x; }
};
typedef std::list<BezierPoint> BezierFunction;
BezierPoint mBezierMidPoint;
BezierFunction mBezierFunction;
float mSymmetricAt;
float mBezierStep;
IntervalList mIntervals;
std::vector<ControlChannelBinderItem> mAttachedControls;
std::list<ChannelListener* > mListeners;
void notifyListeners(float previousValue);
bool mEnabled;
};
}
#endif
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef OICS_Channel_H_
#define OICS_Channel_H_
#include "ICSPrerequisites.h"
#include "ICSChannelListener.h"
namespace ICS
{
struct FilterInterval{
//std::string type; //! @todo uncomment when more types implemented
float startX;
float startY;
float midX;
float midY;
float endX;
float endY;
float step;
};
typedef std::list<FilterInterval> IntervalList;
class DllExport Channel
{
public:
enum ChannelDirection
{
INVERSE = -1, DIRECT = 1
};
typedef struct {
ChannelDirection direction;
float percentage;
Control* control;
} ControlChannelBinderItem;
Channel(int number, float initialValue = 0.5
, float bezierMidPointY = 0.5, float bezierMidPointX = 0.5
, float symmetricAt = 0, float bezierStep = 0.2); //! @todo implement symetry
~Channel(){};
void setValue(float value);
float getValue();
inline int getNumber(){ return mNumber; };
void addControl(Control* control, Channel::ChannelDirection dir, float percentage);
inline size_t getControlsCount(){ return mAttachedControls.size(); };
std::vector<ControlChannelBinderItem> getAttachedControls(){ return mAttachedControls; };
ControlChannelBinderItem getAttachedControlBinding(Control* control);
void addListener(ChannelListener* ob){ mListeners.push_back(ob); };
void removeListener(ChannelListener* ob){ mListeners.remove(ob); };
void update();
void setBezierFunction(float bezierMidPointY, float bezierMidPointX = 0.5
, float symmetricAt = 0, float bezierStep = 0.2);
void addBezierInterval(float startX, float startY, float midX, float midY
, float endX, float endY, float step = 0.1);
IntervalList& getIntervals(){ return mIntervals; };
void setEnabled(bool enabled);
protected:
int mNumber;
float mValue;
struct BezierPoint{
float x;
float y;
bool operator < (const BezierPoint& other){ return x < other.x; }
};
typedef std::list<BezierPoint> BezierFunction;
BezierPoint mBezierMidPoint;
BezierFunction mBezierFunction;
float mSymmetricAt;
float mBezierStep;
IntervalList mIntervals;
std::vector<ControlChannelBinderItem> mAttachedControls;
std::list<ChannelListener* > mListeners;
void notifyListeners(float previousValue);
bool mEnabled;
};
}
#endif

@ -1,48 +1,48 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef _ChannelListener_H_
#define _ChannelListener_H_
#include "ICSPrerequisites.h"
#include "ICSChannel.h"
namespace ICS
{
class DllExport ChannelListener
{
public:
virtual void channelChanged(Channel* channel, float currentValue, float previousValue) = 0;
virtual ~ChannelListener() = default;
};
}
#endif
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef _ChannelListener_H_
#define _ChannelListener_H_
#include "ICSPrerequisites.h"
#include "ICSChannel.h"
namespace ICS
{
class DllExport ChannelListener
{
public:
virtual void channelChanged(Channel* channel, float currentValue, float previousValue) = 0;
virtual ~ChannelListener() = default;
};
}
#endif

@ -1,161 +1,161 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSInputControlSystem.h"
#include "ICSControl.h"
namespace ICS
{
Control::Control(const std::string& name, bool autoChangeDirectionOnLimitsAfterStop, bool autoReverseToInitialValue
, float initialValue, float stepSize, float stepsPerSeconds, bool axisBindable)
: mValue(initialValue)
, mInitialValue(initialValue)
, mName(name)
, mStepSize(stepSize)
, mStepsPerSeconds(stepsPerSeconds)
, mAutoReverseToInitialValue(autoReverseToInitialValue)
, mIgnoreAutoReverse(false)
, mAutoChangeDirectionOnLimitsAfterStop(autoChangeDirectionOnLimitsAfterStop)
, mAxisBindable(axisBindable)
, currentChangingDirection(STOP)
{
}
Control::~Control()
{
mAttachedChannels.clear();
}
void Control::setValue(float value)
{
float previousValue = mValue;
mValue = std::max<float>(0.0,std::min<float>(1.0,value));
if(mValue != previousValue)
{
updateChannels();
notifyListeners(previousValue);
}
}
void Control::attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage)
{
mAttachedChannels.push_back(channel);
channel->addControl(this, direction, percentage);
}
void Control::updateChannels()
{
std::list<Channel*>::iterator pos = mAttachedChannels.begin();
while (pos != mAttachedChannels.end())
{
((Channel* )(*pos))->update();
++pos;
}
}
void Control::notifyListeners(float previousValue)
{
std::list<ControlListener*>::iterator pos = mListeners.begin();
while (pos != mListeners.end())
{
(*pos)->controlChanged((Control*)this, this->getValue(), previousValue);
++pos;
}
}
void Control::setChangingDirection(ControlChangingDirection direction)
{
currentChangingDirection = direction;
mPendingActions.push_back(direction);
}
void Control::update(float timeSinceLastFrame)
{
if(!mPendingActions.empty())
{
size_t timedActionsCount = 0;
std::list<Control::ControlChangingDirection>::iterator cached_end = mPendingActions.end();
for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ;
it != cached_end ; ++it)
{
if( (*it) != Control::STOP )
{
timedActionsCount++;
}
}
float timeSinceLastFramePart = timeSinceLastFrame / std::max<size_t>(1, timedActionsCount);
for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ;
it != cached_end ; ++it)
{
if( (*it) != Control::STOP )
{
this->setValue(mValue +
(((int)(*it)) * mStepSize * mStepsPerSeconds * (timeSinceLastFramePart)));
}
else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue )
{
if(mValue > mInitialValue)
{
this->setValue( std::max<float>( mInitialValue,
mValue - (mStepSize * mStepsPerSeconds * (timeSinceLastFramePart))));
}
else if(mValue < mInitialValue)
{
this->setValue( std::min<float>( mInitialValue,
mValue + (mStepSize * mStepsPerSeconds * (timeSinceLastFramePart))));
}
}
}
mPendingActions.clear();
}
else if( currentChangingDirection != Control::STOP )
{
this->setValue(mValue +
(((int)currentChangingDirection) * mStepSize * mStepsPerSeconds * (timeSinceLastFrame)));
}
else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue )
{
if(mValue > mInitialValue)
{
this->setValue( std::max<float>( mInitialValue,
mValue - (mStepSize * mStepsPerSeconds * (timeSinceLastFrame))));
}
else if(mValue < mInitialValue)
{
this->setValue( std::min<float>( mInitialValue,
mValue + (mStepSize * mStepsPerSeconds * (timeSinceLastFrame))));
}
}
}
}
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSInputControlSystem.h"
#include "ICSControl.h"
namespace ICS
{
Control::Control(const std::string& name, bool autoChangeDirectionOnLimitsAfterStop, bool autoReverseToInitialValue
, float initialValue, float stepSize, float stepsPerSeconds, bool axisBindable)
: mValue(initialValue)
, mInitialValue(initialValue)
, mName(name)
, mStepSize(stepSize)
, mStepsPerSeconds(stepsPerSeconds)
, mAutoReverseToInitialValue(autoReverseToInitialValue)
, mIgnoreAutoReverse(false)
, mAutoChangeDirectionOnLimitsAfterStop(autoChangeDirectionOnLimitsAfterStop)
, mAxisBindable(axisBindable)
, currentChangingDirection(STOP)
{
}
Control::~Control()
{
mAttachedChannels.clear();
}
void Control::setValue(float value)
{
float previousValue = mValue;
mValue = std::max<float>(0.0,std::min<float>(1.0,value));
if(mValue != previousValue)
{
updateChannels();
notifyListeners(previousValue);
}
}
void Control::attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage)
{
mAttachedChannels.push_back(channel);
channel->addControl(this, direction, percentage);
}
void Control::updateChannels()
{
std::list<Channel*>::iterator pos = mAttachedChannels.begin();
while (pos != mAttachedChannels.end())
{
((Channel* )(*pos))->update();
++pos;
}
}
void Control::notifyListeners(float previousValue)
{
std::list<ControlListener*>::iterator pos = mListeners.begin();
while (pos != mListeners.end())
{
(*pos)->controlChanged((Control*)this, this->getValue(), previousValue);
++pos;
}
}
void Control::setChangingDirection(ControlChangingDirection direction)
{
currentChangingDirection = direction;
mPendingActions.push_back(direction);
}
void Control::update(float timeSinceLastFrame)
{
if(!mPendingActions.empty())
{
size_t timedActionsCount = 0;
std::list<Control::ControlChangingDirection>::iterator cached_end = mPendingActions.end();
for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ;
it != cached_end ; ++it)
{
if( (*it) != Control::STOP )
{
timedActionsCount++;
}
}
float timeSinceLastFramePart = timeSinceLastFrame / std::max<size_t>(1, timedActionsCount);
for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ;
it != cached_end ; ++it)
{
if( (*it) != Control::STOP )
{
this->setValue(mValue +
(((int)(*it)) * mStepSize * mStepsPerSeconds * (timeSinceLastFramePart)));
}
else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue )
{
if(mValue > mInitialValue)
{
this->setValue( std::max<float>( mInitialValue,
mValue - (mStepSize * mStepsPerSeconds * (timeSinceLastFramePart))));
}
else if(mValue < mInitialValue)
{
this->setValue( std::min<float>( mInitialValue,
mValue + (mStepSize * mStepsPerSeconds * (timeSinceLastFramePart))));
}
}
}
mPendingActions.clear();
}
else if( currentChangingDirection != Control::STOP )
{
this->setValue(mValue +
(((int)currentChangingDirection) * mStepSize * mStepsPerSeconds * (timeSinceLastFrame)));
}
else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue )
{
if(mValue > mInitialValue)
{
this->setValue( std::max<float>( mInitialValue,
mValue - (mStepSize * mStepsPerSeconds * (timeSinceLastFrame))));
}
else if(mValue < mInitialValue)
{
this->setValue( std::min<float>( mInitialValue,
mValue + (mStepSize * mStepsPerSeconds * (timeSinceLastFrame))));
}
}
}
}

@ -1,108 +1,108 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef OICS_Control_H_
#define OICS_Control_H_
#include "ICSPrerequisites.h"
#include "ICSChannel.h"
#include "ICSControlListener.h"
namespace ICS
{
class DllExport Control
{
public:
enum ControlChangingDirection
{
DECREASE = -1, STOP = 0, INCREASE = 1
};
Control(const std::string& name, bool autoChangeDirectionOnLimitsAfterStop = false, bool autoReverseToInitialValue = false, float initialValue = 0.5, float stepSize = 0.1, float stepsPerSeconds = 2.0, bool axisBindable = true);
~Control();
void setChangingDirection(ControlChangingDirection direction);
inline ControlChangingDirection getChangingDirection(){ return currentChangingDirection; };
void setValue(float value);
inline float getValue(){ return mValue; };
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef OICS_Control_H_
#define OICS_Control_H_
#include "ICSPrerequisites.h"
#include "ICSChannel.h"
#include "ICSControlListener.h"
namespace ICS
{
class DllExport Control
{
public:
enum ControlChangingDirection
{
DECREASE = -1, STOP = 0, INCREASE = 1
};
Control(const std::string& name, bool autoChangeDirectionOnLimitsAfterStop = false, bool autoReverseToInitialValue = false, float initialValue = 0.5, float stepSize = 0.1, float stepsPerSeconds = 2.0, bool axisBindable = true);
~Control();
void setChangingDirection(ControlChangingDirection direction);
inline ControlChangingDirection getChangingDirection(){ return currentChangingDirection; };
void setValue(float value);
inline float getValue(){ return mValue; };
inline float getInitialValue(){ return mInitialValue; };
inline void setInitialValue(float i) {mInitialValue = i;};
void attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage = 1.0);
std::list<Channel*> getAttachedChannels(){ return mAttachedChannels; };
inline float getStepSize(){ return mStepSize; };
inline float getStepsPerSeconds(){ return mStepsPerSeconds; };
inline void setIgnoreAutoReverse(bool value){ mIgnoreAutoReverse = value; }; // mouse disable autoreverse
inline bool isAutoReverseIgnored(){ return mIgnoreAutoReverse; };
inline bool getAutoReverse(){ return mAutoReverseToInitialValue; };
inline bool getAutoChangeDirectionOnLimitsAfterStop(){ return mAutoChangeDirectionOnLimitsAfterStop; };
inline std::string getName(){ return mName; };
inline bool isAxisBindable(){ return mAxisBindable; };
inline void setAxisBindable(bool value){ mAxisBindable = value; };
inline void addListener(ControlListener* ob){ mListeners.push_back(ob); };
inline void removeListener(ControlListener* ob){ mListeners.remove(ob); };
void update(float timeSinceLastFrame);
protected:
float mValue;
float mInitialValue;
std::string mName;
float mStepSize;
float mStepsPerSeconds;
bool mAutoReverseToInitialValue;
bool mIgnoreAutoReverse;
bool mAutoChangeDirectionOnLimitsAfterStop;
bool mAxisBindable;
Control::ControlChangingDirection currentChangingDirection;
std::list<Channel*> mAttachedChannels;
std::list<ControlListener*> mListeners;
std::list<Control::ControlChangingDirection> mPendingActions;
protected:
void updateChannels();
void notifyListeners(float previousValue);
};
}
#endif
inline void setInitialValue(float i) {mInitialValue = i;};
void attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage = 1.0);
std::list<Channel*> getAttachedChannels(){ return mAttachedChannels; };
inline float getStepSize(){ return mStepSize; };
inline float getStepsPerSeconds(){ return mStepsPerSeconds; };
inline void setIgnoreAutoReverse(bool value){ mIgnoreAutoReverse = value; }; // mouse disable autoreverse
inline bool isAutoReverseIgnored(){ return mIgnoreAutoReverse; };
inline bool getAutoReverse(){ return mAutoReverseToInitialValue; };
inline bool getAutoChangeDirectionOnLimitsAfterStop(){ return mAutoChangeDirectionOnLimitsAfterStop; };
inline std::string getName(){ return mName; };
inline bool isAxisBindable(){ return mAxisBindable; };
inline void setAxisBindable(bool value){ mAxisBindable = value; };
inline void addListener(ControlListener* ob){ mListeners.push_back(ob); };
inline void removeListener(ControlListener* ob){ mListeners.remove(ob); };
void update(float timeSinceLastFrame);
protected:
float mValue;
float mInitialValue;
std::string mName;
float mStepSize;
float mStepsPerSeconds;
bool mAutoReverseToInitialValue;
bool mIgnoreAutoReverse;
bool mAutoChangeDirectionOnLimitsAfterStop;
bool mAxisBindable;
Control::ControlChangingDirection currentChangingDirection;
std::list<Channel*> mAttachedChannels;
std::list<ControlListener*> mListeners;
std::list<Control::ControlChangingDirection> mPendingActions;
protected:
void updateChannels();
void notifyListeners(float previousValue);
};
}
#endif

@ -1,48 +1,48 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef _ControlListener_H_
#define _ControlListener_H_
#include "ICSPrerequisites.h"
#include "ICSControl.h"
namespace ICS
{
class DllExport ControlListener
{
public:
virtual void controlChanged(Control* control, float currentValue, float previousValue) = 0;
virtual ~ControlListener() = default;
};
}
#endif
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef _ControlListener_H_
#define _ControlListener_H_
#include "ICSPrerequisites.h"
#include "ICSControl.h"
namespace ICS
{
class DllExport ControlListener
{
public:
virtual void controlChanged(Control* control, float currentValue, float previousValue) = 0;
virtual ~ControlListener() = default;
};
}
#endif

File diff suppressed because it is too large Load Diff

@ -1,281 +1,281 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef OICS_InputControlSystem_H_
#define OICS_InputControlSystem_H_
#include "ICSPrerequisites.h"
#include "ICSControl.h"
#include "ICSChannel.h"
#define ICS_LOG(text) if(mLog) mLog->logMessage( ("ICS: " + std::string(text)).c_str() );
#define ICS_MAX_JOYSTICK_AXIS 16
#define ICS_MOUSE_BINDING_MARGIN 30
#define ICS_JOYSTICK_AXIS_BINDING_MARGIN 10000
#define ICS_JOYSTICK_SLIDER_BINDING_MARGIN 10000
#define ICS_MOUSE_AXIS_BINDING_NULL_VALUE std::numeric_limits<int>::max()
namespace ICS
{
class DllExport InputControlSystemLog
{
public:
virtual void logMessage(const char* text) = 0;
virtual ~InputControlSystemLog() = default;
};
class DllExport InputControlSystem
{
public:
enum NamedAxis { X = -1, Y = -2, Z = -3, UNASSIGNED = -4 };
enum POVAxis { NorthSouth = 0, EastWest = 1 };
typedef NamedAxis MouseAxis; // MouseAxis is deprecated. It will be removed in future versions
typedef std::map<int, SDL_GameController*> JoystickInstanceMap;
typedef std::list<int> JoystickIDList;
typedef struct
{
int index;
POVAxis axis;
} POVBindingPair;
InputControlSystem(std::string file = "", bool active = true
, DetectingBindingListener* detectingBindingListener = NULL
, InputControlSystemLog* log = NULL, size_t channelCount = 16);
~InputControlSystem();
std::string getFileName(){ return mFileName; };
std::string getBaseFileName();
void setDetectingBindingListener(DetectingBindingListener* detectingBindingListener){ mDetectingBindingListener = detectingBindingListener; };
DetectingBindingListener* getDetectingBindingListener(){ return mDetectingBindingListener; };
void setJoystickDeadZone(float deadZone){ mDeadZone = deadZone; };
// in seconds
void update(float timeSinceLastFrame);
inline Channel* getChannel(int i){ return mChannels[i]; };
float getChannelValue(int i);
inline int getChannelCount(){ return (int)mChannels.size(); };
inline Control* getControl(int i){ return mControls[i]; };
float getControlValue(int i);
inline int getControlCount(){ return (int)mControls.size(); };
inline void addControl(Control* control){ mControls.push_back(control); };
Control* findControl(std::string name);
inline void activate(){ this->mActive = true; };
inline void deactivate(){ this->mActive = false; };
void controllerAdded (int deviceID, const SDL_ControllerDeviceEvent &args);
void controllerRemoved(const SDL_ControllerDeviceEvent &args);
JoystickIDList& getJoystickIdList(){ return mJoystickIDList; };
JoystickInstanceMap& getJoystickInstanceMap(){ return mJoystickInstanceMap; };
// MouseListener
void mouseMoved(const SDL_MouseMotionEvent &evt);
void mousePressed(const SDL_MouseButtonEvent &evt, Uint8);
void mouseReleased(const SDL_MouseButtonEvent &evt, Uint8);
// KeyListener
void keyPressed(const SDL_KeyboardEvent &evt);
void keyReleased(const SDL_KeyboardEvent &evt);
// ControllerListener
void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &evt);
void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &evt);
void axisMoved(int deviceID, const SDL_ControllerAxisEvent &evt);
void addKeyBinding(Control* control, SDL_Scancode key, Control::ControlChangingDirection direction);
bool isKeyBound(SDL_Scancode key) const;
void addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction);
void addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction);
bool isMouseButtonBound(unsigned int button) const;
void addJoystickAxisBinding(Control* control, int deviceID, int axis, Control::ControlChangingDirection direction);
void addJoystickButtonBinding(Control* control, int deviceID, unsigned int button, Control::ControlChangingDirection direction);
bool isJoystickButtonBound(int deviceID, unsigned int button) const;
bool isJoystickAxisBound(int deviceID, unsigned int axis) const;
void removeKeyBinding(SDL_Scancode key);
void removeMouseAxisBinding(NamedAxis axis);
void removeMouseButtonBinding(unsigned int button);
void removeJoystickAxisBinding(int deviceID, int axis);
void removeJoystickButtonBinding(int deviceID, unsigned int button);
SDL_Scancode getKeyBinding(Control* control, ICS::Control::ControlChangingDirection direction);
NamedAxis getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction);
unsigned int getMouseButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction);
int getJoystickAxisBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction);
unsigned int getJoystickButtonBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction);
std::string scancodeToString(SDL_Scancode key);
void enableDetectingBindingState(Control* control, Control::ControlChangingDirection direction);
void cancelDetectingBindingState();
bool detectingBindingState();
bool save(std::string fileName = "");
void adjustMouseRegion (Uint16 width, Uint16 height);
protected:
void loadKeyBinders(TiXmlElement* xmlControlNode);
void loadMouseAxisBinders(TiXmlElement* xmlControlNode);
void loadMouseButtonBinders(TiXmlElement* xmlControlNode);
void loadJoystickAxisBinders(TiXmlElement* xmlControlNode);
void loadJoystickButtonBinders(TiXmlElement* xmlControlNode);
void loadJoystickPOVBinders(TiXmlElement* xmlControlNode);
void loadJoystickSliderBinders(TiXmlElement* xmlControlNode);
void addMouseAxisBinding_(Control* control, int axis, Control::ControlChangingDirection direction);
void removeMouseAxisBinding_(int axis);
protected:
typedef struct {
Control::ControlChangingDirection direction;
Control* control;
} ControlKeyBinderItem;
typedef ControlKeyBinderItem ControlAxisBinderItem;
typedef ControlKeyBinderItem ControlButtonBinderItem;
typedef ControlKeyBinderItem ControlPOVBinderItem;
typedef ControlKeyBinderItem ControlSliderBinderItem;
typedef struct {
Control* control;
Control::ControlChangingDirection direction;
} PendingActionItem;
std::list<PendingActionItem> mPendingActions;
std::string mFileName;
float mDeadZone;
typedef std::map<SDL_Scancode, ControlKeyBinderItem> ControlsKeyBinderMapType; // <Scancode, [direction, control]>
typedef std::map<int, ControlAxisBinderItem> ControlsAxisBinderMapType; // <axis, [direction, control]>
typedef std::map<int, ControlButtonBinderItem> ControlsButtonBinderMapType; // <button, [direction, control]>
typedef std::map<int, ControlsAxisBinderMapType> JoystickAxisBinderMapType; // <joystick_id, <axis, [direction, control]> >
typedef std::map<int, ControlsButtonBinderMapType> JoystickButtonBinderMapType; // <joystick_id, <button, [direction, control]> >
ControlsAxisBinderMapType mControlsMouseAxisBinderMap; // <axis, [direction, control]>
ControlsButtonBinderMapType mControlsMouseButtonBinderMap; // <int, [direction, control]>
JoystickAxisBinderMapType mControlsJoystickAxisBinderMap; // <axis, [direction, control]>
JoystickButtonBinderMapType mControlsJoystickButtonBinderMap; // <button, [direction, control]>
std::vector<Control *> mControls;
std::vector<Channel *> mChannels;
ControlsKeyBinderMapType mControlsKeyBinderMap;
bool mActive;
InputControlSystemLog* mLog;
DetectingBindingListener* mDetectingBindingListener;
Control* mDetectingBindingControl;
Control::ControlChangingDirection mDetectingBindingDirection;
bool mXmouseAxisBinded;
bool mYmouseAxisBinded;
JoystickIDList mJoystickIDList;
JoystickInstanceMap mJoystickInstanceMap;
int mMouseAxisBindingInitialValues[3];
private:
Uint16 mClientWidth;
Uint16 mClientHeight;
/* ----------------------------------------------------------------------------------------
* OPENMW CODE STARTS HERE
* Mouse Wheel support added by Michael Stopa (Stomy) */
public:
enum class MouseWheelClick : int { UNASSIGNED = 0, UP = 1, DOWN = 2, LEFT = 3, RIGHT = 4};
void mouseWheelMoved(const SDL_MouseWheelEvent &evt);
void addMouseWheelBinding(Control* control, MouseWheelClick click, Control::ControlChangingDirection direction);
void removeMouseWheelBinding(MouseWheelClick click);
MouseWheelClick getMouseWheelBinding(Control* control, ICS::Control::ControlChangingDirection direction);
bool isMouseWheelBound(MouseWheelClick button) const;
protected:
void loadMouseWheelBinders(TiXmlElement* xmlControlNode);
ControlsButtonBinderMapType mControlsMouseWheelBinderMap;
/* OPENMW CODE ENDS HERE
* ------------------------------------------------------------------------------------- */
};
class DllExport DetectingBindingListener
{
public:
virtual void keyBindingDetected(InputControlSystem* ICS, Control* control
, SDL_Scancode key, Control::ControlChangingDirection direction);
virtual void mouseAxisBindingDetected(InputControlSystem* ICS, Control* control
, InputControlSystem::NamedAxis axis, Control::ControlChangingDirection direction);
virtual void mouseButtonBindingDetected(InputControlSystem* ICS, Control* control
, unsigned int button, Control::ControlChangingDirection direction);
virtual void joystickAxisBindingDetected(InputControlSystem* ICS, int deviceID, Control* control
, int axis, Control::ControlChangingDirection direction);
virtual void joystickButtonBindingDetected(InputControlSystem* ICS, int deviceID, Control* control
, unsigned int button, Control::ControlChangingDirection direction);
/* ----------------------------------------------------------------------------------------
* OPENMW CODE STARTS HERE
* Mouse Wheel support added by Michael Stopa (Stomy) */
virtual void mouseWheelBindingDetected(InputControlSystem* ICS, Control* control,
InputControlSystem::MouseWheelClick click,
Control::ControlChangingDirection direction);
virtual ~DetectingBindingListener() = default;
/* OPENMW CODE ENDS HERE
* ------------------------------------------------------------------------------------- */
};
extern const float ICS_MAX;
}
#endif
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#ifndef OICS_InputControlSystem_H_
#define OICS_InputControlSystem_H_
#include "ICSPrerequisites.h"
#include "ICSControl.h"
#include "ICSChannel.h"
#define ICS_LOG(text) if(mLog) mLog->logMessage( ("ICS: " + std::string(text)).c_str() );
#define ICS_MAX_JOYSTICK_AXIS 16
#define ICS_MOUSE_BINDING_MARGIN 30
#define ICS_JOYSTICK_AXIS_BINDING_MARGIN 10000
#define ICS_JOYSTICK_SLIDER_BINDING_MARGIN 10000
#define ICS_MOUSE_AXIS_BINDING_NULL_VALUE std::numeric_limits<int>::max()
namespace ICS
{
class DllExport InputControlSystemLog
{
public:
virtual void logMessage(const char* text) = 0;
virtual ~InputControlSystemLog() = default;
};
class DllExport InputControlSystem
{
public:
enum NamedAxis { X = -1, Y = -2, Z = -3, UNASSIGNED = -4 };
enum POVAxis { NorthSouth = 0, EastWest = 1 };
typedef NamedAxis MouseAxis; // MouseAxis is deprecated. It will be removed in future versions
typedef std::map<int, SDL_GameController*> JoystickInstanceMap;
typedef std::list<int> JoystickIDList;
typedef struct
{
int index;
POVAxis axis;
} POVBindingPair;
InputControlSystem(std::string file = "", bool active = true
, DetectingBindingListener* detectingBindingListener = NULL
, InputControlSystemLog* log = NULL, size_t channelCount = 16);
~InputControlSystem();
std::string getFileName(){ return mFileName; };
std::string getBaseFileName();
void setDetectingBindingListener(DetectingBindingListener* detectingBindingListener){ mDetectingBindingListener = detectingBindingListener; };
DetectingBindingListener* getDetectingBindingListener(){ return mDetectingBindingListener; };
void setJoystickDeadZone(float deadZone){ mDeadZone = deadZone; };
// in seconds
void update(float timeSinceLastFrame);
inline Channel* getChannel(int i){ return mChannels[i]; };
float getChannelValue(int i);
inline int getChannelCount(){ return (int)mChannels.size(); };
inline Control* getControl(int i){ return mControls[i]; };
float getControlValue(int i);
inline int getControlCount(){ return (int)mControls.size(); };
inline void addControl(Control* control){ mControls.push_back(control); };
Control* findControl(std::string name);
inline void activate(){ this->mActive = true; };
inline void deactivate(){ this->mActive = false; };
void controllerAdded (int deviceID, const SDL_ControllerDeviceEvent &args);
void controllerRemoved(const SDL_ControllerDeviceEvent &args);
JoystickIDList& getJoystickIdList(){ return mJoystickIDList; };
JoystickInstanceMap& getJoystickInstanceMap(){ return mJoystickInstanceMap; };
// MouseListener
void mouseMoved(const SDL_MouseMotionEvent &evt);
void mousePressed(const SDL_MouseButtonEvent &evt, Uint8);
void mouseReleased(const SDL_MouseButtonEvent &evt, Uint8);
// KeyListener
void keyPressed(const SDL_KeyboardEvent &evt);
void keyReleased(const SDL_KeyboardEvent &evt);
// ControllerListener
void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &evt);
void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &evt);
void axisMoved(int deviceID, const SDL_ControllerAxisEvent &evt);
void addKeyBinding(Control* control, SDL_Scancode key, Control::ControlChangingDirection direction);
bool isKeyBound(SDL_Scancode key) const;
void addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction);
void addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction);
bool isMouseButtonBound(unsigned int button) const;
void addJoystickAxisBinding(Control* control, int deviceID, int axis, Control::ControlChangingDirection direction);
void addJoystickButtonBinding(Control* control, int deviceID, unsigned int button, Control::ControlChangingDirection direction);
bool isJoystickButtonBound(int deviceID, unsigned int button) const;
bool isJoystickAxisBound(int deviceID, unsigned int axis) const;
void removeKeyBinding(SDL_Scancode key);
void removeMouseAxisBinding(NamedAxis axis);
void removeMouseButtonBinding(unsigned int button);
void removeJoystickAxisBinding(int deviceID, int axis);
void removeJoystickButtonBinding(int deviceID, unsigned int button);
SDL_Scancode getKeyBinding(Control* control, ICS::Control::ControlChangingDirection direction);
NamedAxis getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction);
unsigned int getMouseButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction);
int getJoystickAxisBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction);
unsigned int getJoystickButtonBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction);
std::string scancodeToString(SDL_Scancode key);
void enableDetectingBindingState(Control* control, Control::ControlChangingDirection direction);
void cancelDetectingBindingState();
bool detectingBindingState();
bool save(std::string fileName = "");
void adjustMouseRegion (Uint16 width, Uint16 height);
protected:
void loadKeyBinders(TiXmlElement* xmlControlNode);
void loadMouseAxisBinders(TiXmlElement* xmlControlNode);
void loadMouseButtonBinders(TiXmlElement* xmlControlNode);
void loadJoystickAxisBinders(TiXmlElement* xmlControlNode);
void loadJoystickButtonBinders(TiXmlElement* xmlControlNode);
void loadJoystickPOVBinders(TiXmlElement* xmlControlNode);
void loadJoystickSliderBinders(TiXmlElement* xmlControlNode);
void addMouseAxisBinding_(Control* control, int axis, Control::ControlChangingDirection direction);
void removeMouseAxisBinding_(int axis);
protected:
typedef struct {
Control::ControlChangingDirection direction;
Control* control;
} ControlKeyBinderItem;
typedef ControlKeyBinderItem ControlAxisBinderItem;
typedef ControlKeyBinderItem ControlButtonBinderItem;
typedef ControlKeyBinderItem ControlPOVBinderItem;
typedef ControlKeyBinderItem ControlSliderBinderItem;
typedef struct {
Control* control;
Control::ControlChangingDirection direction;
} PendingActionItem;
std::list<PendingActionItem> mPendingActions;
std::string mFileName;
float mDeadZone;
typedef std::map<SDL_Scancode, ControlKeyBinderItem> ControlsKeyBinderMapType; // <Scancode, [direction, control]>
typedef std::map<int, ControlAxisBinderItem> ControlsAxisBinderMapType; // <axis, [direction, control]>
typedef std::map<int, ControlButtonBinderItem> ControlsButtonBinderMapType; // <button, [direction, control]>
typedef std::map<int, ControlsAxisBinderMapType> JoystickAxisBinderMapType; // <joystick_id, <axis, [direction, control]> >
typedef std::map<int, ControlsButtonBinderMapType> JoystickButtonBinderMapType; // <joystick_id, <button, [direction, control]> >
ControlsAxisBinderMapType mControlsMouseAxisBinderMap; // <axis, [direction, control]>
ControlsButtonBinderMapType mControlsMouseButtonBinderMap; // <int, [direction, control]>
JoystickAxisBinderMapType mControlsJoystickAxisBinderMap; // <axis, [direction, control]>
JoystickButtonBinderMapType mControlsJoystickButtonBinderMap; // <button, [direction, control]>
std::vector<Control *> mControls;
std::vector<Channel *> mChannels;
ControlsKeyBinderMapType mControlsKeyBinderMap;
bool mActive;
InputControlSystemLog* mLog;
DetectingBindingListener* mDetectingBindingListener;
Control* mDetectingBindingControl;
Control::ControlChangingDirection mDetectingBindingDirection;
bool mXmouseAxisBinded;
bool mYmouseAxisBinded;
JoystickIDList mJoystickIDList;
JoystickInstanceMap mJoystickInstanceMap;
int mMouseAxisBindingInitialValues[3];
private:
Uint16 mClientWidth;
Uint16 mClientHeight;
/* ----------------------------------------------------------------------------------------
* OPENMW CODE STARTS HERE
* Mouse Wheel support added by Michael Stopa (Stomy) */
public:
enum class MouseWheelClick : int { UNASSIGNED = 0, UP = 1, DOWN = 2, LEFT = 3, RIGHT = 4};
void mouseWheelMoved(const SDL_MouseWheelEvent &evt);
void addMouseWheelBinding(Control* control, MouseWheelClick click, Control::ControlChangingDirection direction);
void removeMouseWheelBinding(MouseWheelClick click);
MouseWheelClick getMouseWheelBinding(Control* control, ICS::Control::ControlChangingDirection direction);
bool isMouseWheelBound(MouseWheelClick button) const;
protected:
void loadMouseWheelBinders(TiXmlElement* xmlControlNode);
ControlsButtonBinderMapType mControlsMouseWheelBinderMap;
/* OPENMW CODE ENDS HERE
* ------------------------------------------------------------------------------------- */
};
class DllExport DetectingBindingListener
{
public:
virtual void keyBindingDetected(InputControlSystem* ICS, Control* control
, SDL_Scancode key, Control::ControlChangingDirection direction);
virtual void mouseAxisBindingDetected(InputControlSystem* ICS, Control* control
, InputControlSystem::NamedAxis axis, Control::ControlChangingDirection direction);
virtual void mouseButtonBindingDetected(InputControlSystem* ICS, Control* control
, unsigned int button, Control::ControlChangingDirection direction);
virtual void joystickAxisBindingDetected(InputControlSystem* ICS, int deviceID, Control* control
, int axis, Control::ControlChangingDirection direction);
virtual void joystickButtonBindingDetected(InputControlSystem* ICS, int deviceID, Control* control
, unsigned int button, Control::ControlChangingDirection direction);
/* ----------------------------------------------------------------------------------------
* OPENMW CODE STARTS HERE
* Mouse Wheel support added by Michael Stopa (Stomy) */
virtual void mouseWheelBindingDetected(InputControlSystem* ICS, Control* control,
InputControlSystem::MouseWheelClick click,
Control::ControlChangingDirection direction);
virtual ~DetectingBindingListener() = default;
/* OPENMW CODE ENDS HERE
* ------------------------------------------------------------------------------------- */
};
extern const float ICS_MAX;
}
#endif

@ -1,266 +1,266 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSInputControlSystem.h"
#define SDL_JOY_AXIS_MIN -32768
#define SDL_JOY_AXIS_MAX 32767
namespace ICS
{
// load xml
void InputControlSystem::loadJoystickAxisBinders(TiXmlElement* xmlControlNode)
{
TiXmlElement* xmlJoystickBinder = xmlControlNode->FirstChildElement("JoystickAxisBinder");
while(xmlJoystickBinder)
{
Control::ControlChangingDirection dir = Control::STOP;
if(std::string(xmlJoystickBinder->Attribute("direction")) == "INCREASE")
{
dir = Control::INCREASE;
}
else if(std::string(xmlJoystickBinder->Attribute("direction")) == "DECREASE")
{
dir = Control::DECREASE;
}
addJoystickAxisBinding(mControls.back(), FromString<int>(xmlJoystickBinder->Attribute("deviceId")), FromString<int>(xmlJoystickBinder->Attribute("axis")), dir);
xmlJoystickBinder = xmlJoystickBinder->NextSiblingElement("JoystickAxisBinder");
}
}
void InputControlSystem::loadJoystickButtonBinders(TiXmlElement* xmlControlNode)
{
TiXmlElement* xmlJoystickButtonBinder = xmlControlNode->FirstChildElement("JoystickButtonBinder");
while(xmlJoystickButtonBinder)
{
Control::ControlChangingDirection dir = Control::STOP;
if(std::string(xmlJoystickButtonBinder->Attribute("direction")) == "INCREASE")
{
dir = Control::INCREASE;
}
else if(std::string(xmlJoystickButtonBinder->Attribute("direction")) == "DECREASE")
{
dir = Control::DECREASE;
}
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSInputControlSystem.h"
#define SDL_JOY_AXIS_MIN -32768
#define SDL_JOY_AXIS_MAX 32767
namespace ICS
{
// load xml
void InputControlSystem::loadJoystickAxisBinders(TiXmlElement* xmlControlNode)
{
TiXmlElement* xmlJoystickBinder = xmlControlNode->FirstChildElement("JoystickAxisBinder");
while(xmlJoystickBinder)
{
Control::ControlChangingDirection dir = Control::STOP;
if(std::string(xmlJoystickBinder->Attribute("direction")) == "INCREASE")
{
dir = Control::INCREASE;
}
else if(std::string(xmlJoystickBinder->Attribute("direction")) == "DECREASE")
{
dir = Control::DECREASE;
}
addJoystickAxisBinding(mControls.back(), FromString<int>(xmlJoystickBinder->Attribute("deviceId")), FromString<int>(xmlJoystickBinder->Attribute("axis")), dir);
xmlJoystickBinder = xmlJoystickBinder->NextSiblingElement("JoystickAxisBinder");
}
}
void InputControlSystem::loadJoystickButtonBinders(TiXmlElement* xmlControlNode)
{
TiXmlElement* xmlJoystickButtonBinder = xmlControlNode->FirstChildElement("JoystickButtonBinder");
while(xmlJoystickButtonBinder)
{
Control::ControlChangingDirection dir = Control::STOP;
if(std::string(xmlJoystickButtonBinder->Attribute("direction")) == "INCREASE")
{
dir = Control::INCREASE;
}
else if(std::string(xmlJoystickButtonBinder->Attribute("direction")) == "DECREASE")
{
dir = Control::DECREASE;
}
addJoystickButtonBinding(mControls.back(), FromString<int>(xmlJoystickButtonBinder->Attribute("deviceId")), FromString<int>(xmlJoystickButtonBinder->Attribute("button")), dir);
xmlJoystickButtonBinder = xmlJoystickButtonBinder->NextSiblingElement("JoystickButtonBinder");
}
}
// add bindings
void InputControlSystem::addJoystickAxisBinding(Control* control, int deviceID, int axis, Control::ControlChangingDirection direction)
{
if (std::find(mJoystickIDList.begin(), mJoystickIDList.end(), deviceID) == mJoystickIDList.end())
mJoystickIDList.push_back(deviceID);
ICS_LOG("\tAdding AxisBinder [axis="
xmlJoystickButtonBinder = xmlJoystickButtonBinder->NextSiblingElement("JoystickButtonBinder");
}
}
// add bindings
void InputControlSystem::addJoystickAxisBinding(Control* control, int deviceID, int axis, Control::ControlChangingDirection direction)
{
if (std::find(mJoystickIDList.begin(), mJoystickIDList.end(), deviceID) == mJoystickIDList.end())
mJoystickIDList.push_back(deviceID);
ICS_LOG("\tAdding AxisBinder [axis="
+ ToString<int>(axis) + ", deviceID="
+ ToString<int>(deviceID) + ", direction="
+ ToString<int>(deviceID) + ", direction="
+ ToString<int>(direction) + "]");
control->setValue(0.5f); //all joystick axis start at .5, so do that
ControlAxisBinderItem controlAxisBinderItem;
controlAxisBinderItem.control = control;
controlAxisBinderItem.direction = direction;
mControlsJoystickAxisBinderMap[deviceID][axis] = controlAxisBinderItem;
}
void InputControlSystem::addJoystickButtonBinding(Control* control, int deviceID, unsigned int button, Control::ControlChangingDirection direction)
{
if (std::find(mJoystickIDList.begin(), mJoystickIDList.end(), deviceID) == mJoystickIDList.end())
mJoystickIDList.push_back(deviceID); // Hack: add the device to the list so bindings are saved in save() even when joystick is not connected
ICS_LOG("\tAdding JoystickButtonBinder [button="
control->setValue(0.5f); //all joystick axis start at .5, so do that
ControlAxisBinderItem controlAxisBinderItem;
controlAxisBinderItem.control = control;
controlAxisBinderItem.direction = direction;
mControlsJoystickAxisBinderMap[deviceID][axis] = controlAxisBinderItem;
}
void InputControlSystem::addJoystickButtonBinding(Control* control, int deviceID, unsigned int button, Control::ControlChangingDirection direction)
{
if (std::find(mJoystickIDList.begin(), mJoystickIDList.end(), deviceID) == mJoystickIDList.end())
mJoystickIDList.push_back(deviceID); // Hack: add the device to the list so bindings are saved in save() even when joystick is not connected
ICS_LOG("\tAdding JoystickButtonBinder [button="
+ ToString<int>(button) + ", deviceID="
+ ToString<int>(deviceID) + ", direction="
+ ToString<int>(direction) + "]");
ControlButtonBinderItem controlJoystickButtonBinderItem;
controlJoystickButtonBinderItem.direction = direction;
controlJoystickButtonBinderItem.control = control;
mControlsJoystickButtonBinderMap[deviceID][button] = controlJoystickButtonBinderItem;
}
bool InputControlSystem::isJoystickButtonBound(int deviceID, unsigned int button) const
{
JoystickButtonBinderMapType::const_iterator found = mControlsJoystickButtonBinderMap.find(deviceID);
if (found == mControlsJoystickButtonBinderMap.end())
return false;
return (found->second.find(button) != found->second.end());
}
bool InputControlSystem::isJoystickAxisBound(int deviceID, unsigned int axis) const
{
JoystickAxisBinderMapType::const_iterator found = mControlsJoystickAxisBinderMap.find(deviceID);
if (found == mControlsJoystickAxisBinderMap.end())
return false;
return (found->second.find(axis) != found->second.end());
}
// get bindings
int InputControlSystem::getJoystickAxisBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction)
+ ToString<int>(deviceID) + ", direction="
+ ToString<int>(direction) + "]");
ControlButtonBinderItem controlJoystickButtonBinderItem;
controlJoystickButtonBinderItem.direction = direction;
controlJoystickButtonBinderItem.control = control;
mControlsJoystickButtonBinderMap[deviceID][button] = controlJoystickButtonBinderItem;
}
bool InputControlSystem::isJoystickButtonBound(int deviceID, unsigned int button) const
{
JoystickButtonBinderMapType::const_iterator found = mControlsJoystickButtonBinderMap.find(deviceID);
if (found == mControlsJoystickButtonBinderMap.end())
return false;
return (found->second.find(button) != found->second.end());
}
bool InputControlSystem::isJoystickAxisBound(int deviceID, unsigned int axis) const
{
JoystickAxisBinderMapType::const_iterator found = mControlsJoystickAxisBinderMap.find(deviceID);
if (found == mControlsJoystickAxisBinderMap.end())
return false;
return (found->second.find(axis) != found->second.end());
}
// get bindings
int InputControlSystem::getJoystickAxisBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction)
{
if(mControlsJoystickAxisBinderMap.find(deviceID) != mControlsJoystickAxisBinderMap.end())
{
ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceID].begin();
while(it != mControlsJoystickAxisBinderMap[deviceID].end())
{
if(it->first >= 0 && it->second.control == control && it->second.direction == direction)
{
return it->first;
}
++it;
{
ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceID].begin();
while(it != mControlsJoystickAxisBinderMap[deviceID].end())
{
if(it->first >= 0 && it->second.control == control && it->second.direction == direction)
{
return it->first;
}
++it;
}
}
return /*NamedAxis::*/UNASSIGNED;
}
unsigned int InputControlSystem::getJoystickButtonBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction)
}
return /*NamedAxis::*/UNASSIGNED;
}
unsigned int InputControlSystem::getJoystickButtonBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction)
{
if(mControlsJoystickButtonBinderMap.find(deviceID) != mControlsJoystickButtonBinderMap.end())
{
ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceID].begin();
while(it != mControlsJoystickButtonBinderMap[deviceID].end())
{
if(it->second.control == control && it->second.direction == direction)
{
return it->first;
}
++it;
{
ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceID].begin();
while(it != mControlsJoystickButtonBinderMap[deviceID].end())
{
if(it->second.control == control && it->second.direction == direction)
{
return it->first;
}
++it;
}
}
return ICS_MAX_DEVICE_BUTTONS;
}
// remove bindings
void InputControlSystem::removeJoystickAxisBinding(int deviceID, int axis)
}
return ICS_MAX_DEVICE_BUTTONS;
}
// remove bindings
void InputControlSystem::removeJoystickAxisBinding(int deviceID, int axis)
{
if(mControlsJoystickAxisBinderMap.find(deviceID) != mControlsJoystickAxisBinderMap.end())
{
ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceID].find(axis);
if(it != mControlsJoystickAxisBinderMap[deviceID].end())
{
mControlsJoystickAxisBinderMap[deviceID].erase(it);
{
ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceID].find(axis);
if(it != mControlsJoystickAxisBinderMap[deviceID].end())
{
mControlsJoystickAxisBinderMap[deviceID].erase(it);
}
}
}
void InputControlSystem::removeJoystickButtonBinding(int deviceID, unsigned int button)
}
}
void InputControlSystem::removeJoystickButtonBinding(int deviceID, unsigned int button)
{
if(mControlsJoystickButtonBinderMap.find(deviceID) != mControlsJoystickButtonBinderMap.end())
{
ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceID].find(button);
if(it != mControlsJoystickButtonBinderMap[deviceID].end())
{
mControlsJoystickButtonBinderMap[deviceID].erase(it);
{
ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceID].find(button);
if(it != mControlsJoystickButtonBinderMap[deviceID].end())
{
mControlsJoystickButtonBinderMap[deviceID].erase(it);
}
}
}
// joyStick listeners
void InputControlSystem::buttonPressed(int deviceID, const SDL_ControllerButtonEvent &evt)
{
if(mActive)
{
if(!mDetectingBindingControl)
}
}
// joyStick listeners
void InputControlSystem::buttonPressed(int deviceID, const SDL_ControllerButtonEvent &evt)
{
if(mActive)
{
if(!mDetectingBindingControl)
{
if(mControlsJoystickButtonBinderMap.find(deviceID) != mControlsJoystickButtonBinderMap.end())
{
ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[deviceID].find(evt.button);
if(it != mControlsJoystickButtonBinderMap[deviceID].end())
{
it->second.control->setIgnoreAutoReverse(false);
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
{
it->second.control->setChangingDirection(it->second.direction);
}
else
{
if(it->second.control->getValue() == 1)
{
it->second.control->setChangingDirection(Control::DECREASE);
}
else if(it->second.control->getValue() == 0)
{
it->second.control->setChangingDirection(Control::INCREASE);
}
}
{
ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[deviceID].find(evt.button);
if(it != mControlsJoystickButtonBinderMap[deviceID].end())
{
it->second.control->setIgnoreAutoReverse(false);
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
{
it->second.control->setChangingDirection(it->second.direction);
}
else
{
if(it->second.control->getValue() == 1)
{
it->second.control->setChangingDirection(Control::DECREASE);
}
else if(it->second.control->getValue() == 0)
{
it->second.control->setChangingDirection(Control::INCREASE);
}
}
}
}
}
}
}
void InputControlSystem::buttonReleased(int deviceID, const SDL_ControllerButtonEvent &evt)
{
if(mActive)
}
}
}
}
void InputControlSystem::buttonReleased(int deviceID, const SDL_ControllerButtonEvent &evt)
{
if(mActive)
{
if(!mDetectingBindingControl)
{
if(mControlsJoystickButtonBinderMap.find(deviceID) != mControlsJoystickButtonBinderMap.end())
{
ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[deviceID].find(evt.button);
if(it != mControlsJoystickButtonBinderMap[deviceID].end())
{
it->second.control->setChangingDirection(Control::STOP);
{
ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[deviceID].find(evt.button);
if(it != mControlsJoystickButtonBinderMap[deviceID].end())
{
it->second.control->setChangingDirection(Control::STOP);
}
}
}
else if(mDetectingBindingListener)
{
mDetectingBindingListener->joystickButtonBindingDetected(this, deviceID,
mDetectingBindingControl, evt.button, mDetectingBindingDirection);
}
}
}
void InputControlSystem::axisMoved(int deviceID, const SDL_ControllerAxisEvent &evt)
{
if(mActive)
{
if(!mDetectingBindingControl)
else if(mDetectingBindingListener)
{
mDetectingBindingListener->joystickButtonBindingDetected(this, deviceID,
mDetectingBindingControl, evt.button, mDetectingBindingDirection);
}
}
}
void InputControlSystem::axisMoved(int deviceID, const SDL_ControllerAxisEvent &evt)
{
if(mActive)
{
if(!mDetectingBindingControl)
{
if(mControlsJoystickAxisBinderMap.find(deviceID) != mControlsJoystickAxisBinderMap.end())
{
ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[deviceID][evt.axis]; // joystic axis start at 0 index
Control* ctrl = joystickBinderItem.control;
if(ctrl)
{
ctrl->setIgnoreAutoReverse(true);
float axisRange = SDL_JOY_AXIS_MAX - SDL_JOY_AXIS_MIN;
{
ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[deviceID][evt.axis]; // joystic axis start at 0 index
Control* ctrl = joystickBinderItem.control;
if(ctrl)
{
ctrl->setIgnoreAutoReverse(true);
float axisRange = SDL_JOY_AXIS_MAX - SDL_JOY_AXIS_MIN;
float valDisplaced = (float)(evt.value - SDL_JOY_AXIS_MIN);
float percent = valDisplaced / axisRange * (1+mDeadZone*2) - mDeadZone; //Assures all values, 0 through 1, are seen
if(percent > .5-mDeadZone && percent < .5+mDeadZone) //close enough to center
@ -268,57 +268,57 @@ namespace ICS
else if(percent > .5)
percent -= mDeadZone;
else
percent += mDeadZone;
if(joystickBinderItem.direction == Control::INCREASE)
{
ctrl->setValue( percent );
}
else if(joystickBinderItem.direction == Control::DECREASE)
{
ctrl->setValue( 1 - ( percent ) );
}
percent += mDeadZone;
if(joystickBinderItem.direction == Control::INCREASE)
{
ctrl->setValue( percent );
}
else if(joystickBinderItem.direction == Control::DECREASE)
{
ctrl->setValue( 1 - ( percent ) );
}
}
}
}
else if(mDetectingBindingListener)
{
//ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[ evt.which ][ axis ]; // joystic axis start at 0 index
//Control* ctrl = joystickBinderItem.control;
//if(ctrl && ctrl->isAxisBindable())
if(mDetectingBindingControl->isAxisBindable())
{
if( abs( evt.value ) > ICS_JOYSTICK_AXIS_BINDING_MARGIN)
{
mDetectingBindingListener->joystickAxisBindingDetected(this, deviceID,
mDetectingBindingControl, evt.axis, mDetectingBindingDirection);
}
}
}
}
}
}
else if(mDetectingBindingListener)
{
//ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[ evt.which ][ axis ]; // joystic axis start at 0 index
//Control* ctrl = joystickBinderItem.control;
//if(ctrl && ctrl->isAxisBindable())
if(mDetectingBindingControl->isAxisBindable())
{
if( abs( evt.value ) > ICS_JOYSTICK_AXIS_BINDING_MARGIN)
{
mDetectingBindingListener->joystickAxisBindingDetected(this, deviceID,
mDetectingBindingControl, evt.axis, mDetectingBindingDirection);
}
}
}
}
}
void InputControlSystem::controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &args)
{
void InputControlSystem::controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &args)
{
ICS_LOG("Adding joystick (index: " + ToString<int>(args.which) + ")");
SDL_GameController* cntrl = SDL_GameControllerOpen(args.which);
int instanceID = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(cntrl));
if(std::find(mJoystickIDList.begin(), mJoystickIDList.end(), deviceID)==mJoystickIDList.end())
{
for(int j = 0 ; j < ICS_MAX_JOYSTICK_AXIS ; j++)
{
if(mControlsJoystickAxisBinderMap[deviceID].find(j) == mControlsJoystickAxisBinderMap[deviceID].end())
{
ControlAxisBinderItem controlJoystickBinderItem;
controlJoystickBinderItem.direction = Control::STOP;
controlJoystickBinderItem.control = NULL;
mControlsJoystickAxisBinderMap[deviceID][j] = controlJoystickBinderItem;
}
{
for(int j = 0 ; j < ICS_MAX_JOYSTICK_AXIS ; j++)
{
if(mControlsJoystickAxisBinderMap[deviceID].find(j) == mControlsJoystickAxisBinderMap[deviceID].end())
{
ControlAxisBinderItem controlJoystickBinderItem;
controlJoystickBinderItem.direction = Control::STOP;
controlJoystickBinderItem.control = NULL;
mControlsJoystickAxisBinderMap[deviceID][j] = controlJoystickBinderItem;
}
}
mJoystickIDList.push_front(deviceID);
}
mJoystickInstanceMap[instanceID] = cntrl;
mJoystickInstanceMap[instanceID] = cntrl;
}
void InputControlSystem::controllerRemoved(const SDL_ControllerDeviceEvent &args)
{
@ -328,38 +328,38 @@ namespace ICS
SDL_GameControllerClose(mJoystickInstanceMap.at(args.which));
mJoystickInstanceMap.erase(args.which);
}
}
// joystick auto bindings
void DetectingBindingListener::joystickAxisBindingDetected(InputControlSystem* ICS, int deviceID, Control* control, int axis, Control::ControlChangingDirection direction)
{
// if the joystick axis is used by another control, remove it
ICS->removeJoystickAxisBinding(deviceID, axis);
// if the control has an axis assigned, remove it
int oldAxis = ICS->getJoystickAxisBinding(control, deviceID, direction);
if(oldAxis != InputControlSystem::UNASSIGNED)
{
ICS->removeJoystickAxisBinding(deviceID, oldAxis);
}
ICS->addJoystickAxisBinding(control, deviceID, axis, direction);
ICS->cancelDetectingBindingState();
}
void DetectingBindingListener::joystickButtonBindingDetected(InputControlSystem* ICS, int deviceID, Control* control
, unsigned int button, Control::ControlChangingDirection direction)
{
// if the joystick button is used by another control, remove it
ICS->removeJoystickButtonBinding(deviceID, button);
// if the control has a joystick button assigned, remove it
unsigned int oldButton = ICS->getJoystickButtonBinding(control, deviceID, direction);
if(oldButton != ICS_MAX_DEVICE_BUTTONS)
{
ICS->removeJoystickButtonBinding(deviceID, oldButton);
}
ICS->addJoystickButtonBinding(control, deviceID, button, direction);
ICS->cancelDetectingBindingState();
}
}
}
// joystick auto bindings
void DetectingBindingListener::joystickAxisBindingDetected(InputControlSystem* ICS, int deviceID, Control* control, int axis, Control::ControlChangingDirection direction)
{
// if the joystick axis is used by another control, remove it
ICS->removeJoystickAxisBinding(deviceID, axis);
// if the control has an axis assigned, remove it
int oldAxis = ICS->getJoystickAxisBinding(control, deviceID, direction);
if(oldAxis != InputControlSystem::UNASSIGNED)
{
ICS->removeJoystickAxisBinding(deviceID, oldAxis);
}
ICS->addJoystickAxisBinding(control, deviceID, axis, direction);
ICS->cancelDetectingBindingState();
}
void DetectingBindingListener::joystickButtonBindingDetected(InputControlSystem* ICS, int deviceID, Control* control
, unsigned int button, Control::ControlChangingDirection direction)
{
// if the joystick button is used by another control, remove it
ICS->removeJoystickButtonBinding(deviceID, button);
// if the control has a joystick button assigned, remove it
unsigned int oldButton = ICS->getJoystickButtonBinding(control, deviceID, direction);
if(oldButton != ICS_MAX_DEVICE_BUTTONS)
{
ICS->removeJoystickButtonBinding(deviceID, oldButton);
}
ICS->addJoystickButtonBinding(control, deviceID, button, direction);
ICS->cancelDetectingBindingState();
}
}

@ -1,157 +1,157 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSInputControlSystem.h"
namespace ICS
{
void InputControlSystem::loadKeyBinders(TiXmlElement* xmlControlNode)
{
TiXmlElement* xmlKeyBinder = xmlControlNode->FirstChildElement("KeyBinder");
while(xmlKeyBinder)
{
Control::ControlChangingDirection dir = Control::STOP;
if(std::string(xmlKeyBinder->Attribute("direction")) == "INCREASE")
{
dir = Control::INCREASE;
}
else if(std::string(xmlKeyBinder->Attribute("direction")) == "DECREASE")
{
dir = Control::DECREASE;
}
addKeyBinding(mControls.back(), SDL_Scancode(FromString<int>(xmlKeyBinder->Attribute("key"))), dir);
xmlKeyBinder = xmlKeyBinder->NextSiblingElement("KeyBinder");
}
}
void InputControlSystem::addKeyBinding(Control* control, SDL_Scancode key, Control::ControlChangingDirection direction)
{
ICS_LOG("\tAdding KeyBinder [key="
+ scancodeToString(key) + ", direction="
+ ToString<int>(direction) + "]");
ControlKeyBinderItem controlKeyBinderItem;
controlKeyBinderItem.control = control;
controlKeyBinderItem.direction = direction;
mControlsKeyBinderMap[ key ] = controlKeyBinderItem;
}
bool InputControlSystem::isKeyBound(SDL_Scancode key) const
{
return mControlsKeyBinderMap.find(key) != mControlsKeyBinderMap.end();
}
void InputControlSystem::removeKeyBinding(SDL_Scancode key)
{
ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.find(key);
if(it != mControlsKeyBinderMap.end())
{
mControlsKeyBinderMap.erase(it);
}
}
SDL_Scancode InputControlSystem::getKeyBinding(Control* control
, ICS::Control::ControlChangingDirection direction)
{
ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.begin();
while(it != mControlsKeyBinderMap.end())
{
if(it->second.control == control && it->second.direction == direction)
{
return it->first;
}
++it;
}
return SDL_SCANCODE_UNKNOWN;
}
void InputControlSystem::keyPressed(const SDL_KeyboardEvent &evt)
{
if(mActive)
{
if(!mDetectingBindingControl)
{
ControlsKeyBinderMapType::const_iterator it = mControlsKeyBinderMap.find(evt.keysym.scancode);
if(it != mControlsKeyBinderMap.end())
{
it->second.control->setIgnoreAutoReverse(false);
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
{
it->second.control->setChangingDirection(it->second.direction);
}
else
{
if(it->second.control->getValue() == 1)
{
it->second.control->setChangingDirection(Control::DECREASE);
}
else if(it->second.control->getValue() == 0)
{
it->second.control->setChangingDirection(Control::INCREASE);
}
}
}
}
else if(mDetectingBindingListener)
{
mDetectingBindingListener->keyBindingDetected(this,
mDetectingBindingControl, evt.keysym.scancode, mDetectingBindingDirection);
}
}
}
void InputControlSystem::keyReleased(const SDL_KeyboardEvent &evt)
{
if(mActive)
{
ControlsKeyBinderMapType::const_iterator it = mControlsKeyBinderMap.find(evt.keysym.scancode);
if(it != mControlsKeyBinderMap.end())
{
it->second.control->setChangingDirection(Control::STOP);
}
}
}
void DetectingBindingListener::keyBindingDetected(InputControlSystem* ICS, Control* control
, SDL_Scancode key, Control::ControlChangingDirection direction)
{
// if the key is used by another control, remove it
ICS->removeKeyBinding(key);
// if the control has a key assigned, remove it
SDL_Scancode oldKey = ICS->getKeyBinding(control, direction);
if(oldKey != SDL_SCANCODE_UNKNOWN)
{
ICS->removeKeyBinding(oldKey);
}
ICS->addKeyBinding(control, key, direction);
ICS->cancelDetectingBindingState();
}
}
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSInputControlSystem.h"
namespace ICS
{
void InputControlSystem::loadKeyBinders(TiXmlElement* xmlControlNode)
{
TiXmlElement* xmlKeyBinder = xmlControlNode->FirstChildElement("KeyBinder");
while(xmlKeyBinder)
{
Control::ControlChangingDirection dir = Control::STOP;
if(std::string(xmlKeyBinder->Attribute("direction")) == "INCREASE")
{
dir = Control::INCREASE;
}
else if(std::string(xmlKeyBinder->Attribute("direction")) == "DECREASE")
{
dir = Control::DECREASE;
}
addKeyBinding(mControls.back(), SDL_Scancode(FromString<int>(xmlKeyBinder->Attribute("key"))), dir);
xmlKeyBinder = xmlKeyBinder->NextSiblingElement("KeyBinder");
}
}
void InputControlSystem::addKeyBinding(Control* control, SDL_Scancode key, Control::ControlChangingDirection direction)
{
ICS_LOG("\tAdding KeyBinder [key="
+ scancodeToString(key) + ", direction="
+ ToString<int>(direction) + "]");
ControlKeyBinderItem controlKeyBinderItem;
controlKeyBinderItem.control = control;
controlKeyBinderItem.direction = direction;
mControlsKeyBinderMap[ key ] = controlKeyBinderItem;
}
bool InputControlSystem::isKeyBound(SDL_Scancode key) const
{
return mControlsKeyBinderMap.find(key) != mControlsKeyBinderMap.end();
}
void InputControlSystem::removeKeyBinding(SDL_Scancode key)
{
ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.find(key);
if(it != mControlsKeyBinderMap.end())
{
mControlsKeyBinderMap.erase(it);
}
}
SDL_Scancode InputControlSystem::getKeyBinding(Control* control
, ICS::Control::ControlChangingDirection direction)
{
ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.begin();
while(it != mControlsKeyBinderMap.end())
{
if(it->second.control == control && it->second.direction == direction)
{
return it->first;
}
++it;
}
return SDL_SCANCODE_UNKNOWN;
}
void InputControlSystem::keyPressed(const SDL_KeyboardEvent &evt)
{
if(mActive)
{
if(!mDetectingBindingControl)
{
ControlsKeyBinderMapType::const_iterator it = mControlsKeyBinderMap.find(evt.keysym.scancode);
if(it != mControlsKeyBinderMap.end())
{
it->second.control->setIgnoreAutoReverse(false);
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
{
it->second.control->setChangingDirection(it->second.direction);
}
else
{
if(it->second.control->getValue() == 1)
{
it->second.control->setChangingDirection(Control::DECREASE);
}
else if(it->second.control->getValue() == 0)
{
it->second.control->setChangingDirection(Control::INCREASE);
}
}
}
}
else if(mDetectingBindingListener)
{
mDetectingBindingListener->keyBindingDetected(this,
mDetectingBindingControl, evt.keysym.scancode, mDetectingBindingDirection);
}
}
}
void InputControlSystem::keyReleased(const SDL_KeyboardEvent &evt)
{
if(mActive)
{
ControlsKeyBinderMapType::const_iterator it = mControlsKeyBinderMap.find(evt.keysym.scancode);
if(it != mControlsKeyBinderMap.end())
{
it->second.control->setChangingDirection(Control::STOP);
}
}
}
void DetectingBindingListener::keyBindingDetected(InputControlSystem* ICS, Control* control
, SDL_Scancode key, Control::ControlChangingDirection direction)
{
// if the key is used by another control, remove it
ICS->removeKeyBinding(key);
// if the control has a key assigned, remove it
SDL_Scancode oldKey = ICS->getKeyBinding(control, direction);
if(oldKey != SDL_SCANCODE_UNKNOWN)
{
ICS->removeKeyBinding(oldKey);
}
ICS->addKeyBinding(control, key, direction);
ICS->cancelDetectingBindingState();
}
}

File diff suppressed because it is too large Load Diff

@ -1,27 +1,27 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSPrerequisites.h"
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
#include "ICSPrerequisites.h"

@ -1,110 +1,110 @@
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
//! @todo add mouse wheel support
#ifndef _InputControlSystem_Prerequisites_H_
#define _InputControlSystem_Prerequisites_H_
/// Include external headers
#include <sstream>
#include <fstream>
#include <vector>
#include <map>
#include <list>
#include <limits>
#include <algorithm> /* std::min and std::max for MSVC 2013 */
#include "tinyxml.h"
#include "SDL_keyboard.h"
#include "SDL_mouse.h"
#include "SDL_joystick.h"
#include "SDL_events.h"
/// Define the dll export qualifier if compiling for Windows
/*
#ifdef ICS_PLATFORM_WIN32
#ifdef ICS_LIB
#define DllExport __declspec (dllexport)
#else
#define DllExport __declspec (dllimport)
#endif
#else
#define DllExport
#endif
*/
#define DllExport
// Define some macros
#define ICS_DEPRECATED __declspec(deprecated("Deprecated. It will be removed in future versions."))
/// Version defines
#define ICS_VERSION_MAJOR 0
#define ICS_VERSION_MINOR 4
#define ICS_VERSION_PATCH 0
#define ICS_MAX_DEVICE_BUTTONS 30
namespace ICS
{
template <typename T>
bool StringIsNumber ( const std::string &Text )
{
std::stringstream ss(Text);
T result;
return (ss >> result) ? true : false;
}
// from http://www.cplusplus.com/forum/articles/9645/
template <typename T>
std::string ToString ( T value )
{
std::stringstream ss;
ss << value;
return ss.str();
}
// from http://www.cplusplus.com/forum/articles/9645/
template <typename T>
T FromString ( const std::string &Text )//Text not by const reference so that the function can be used with a
{ //character array as argument
std::stringstream ss(Text);
T result;
return (ss >> result) ? result : 0;
}
class InputControlSystem;
class Channel;
class ChannelListener;
class Control;
class ControlListener;
class DetectingBindingListener;
class InputControlSystemLog;
}
#endif
/* -------------------------------------------------------
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */
//! @todo add mouse wheel support
#ifndef _InputControlSystem_Prerequisites_H_
#define _InputControlSystem_Prerequisites_H_
/// Include external headers
#include <sstream>
#include <fstream>
#include <vector>
#include <map>
#include <list>
#include <limits>
#include <algorithm> /* std::min and std::max for MSVC 2013 */
#include "tinyxml.h"
#include "SDL_keyboard.h"
#include "SDL_mouse.h"
#include "SDL_joystick.h"
#include "SDL_events.h"
/// Define the dll export qualifier if compiling for Windows
/*
#ifdef ICS_PLATFORM_WIN32
#ifdef ICS_LIB
#define DllExport __declspec (dllexport)
#else
#define DllExport __declspec (dllimport)
#endif
#else
#define DllExport
#endif
*/
#define DllExport
// Define some macros
#define ICS_DEPRECATED __declspec(deprecated("Deprecated. It will be removed in future versions."))
/// Version defines
#define ICS_VERSION_MAJOR 0
#define ICS_VERSION_MINOR 4
#define ICS_VERSION_PATCH 0
#define ICS_MAX_DEVICE_BUTTONS 30
namespace ICS
{
template <typename T>
bool StringIsNumber ( const std::string &Text )
{
std::stringstream ss(Text);
T result;
return (ss >> result) ? true : false;
}
// from http://www.cplusplus.com/forum/articles/9645/
template <typename T>
std::string ToString ( T value )
{
std::stringstream ss;
ss << value;
return ss.str();
}
// from http://www.cplusplus.com/forum/articles/9645/
template <typename T>
T FromString ( const std::string &Text )//Text not by const reference so that the function can be used with a
{ //character array as argument
std::stringstream ss(Text);
T result;
return (ss >> result) ? result : 0;
}
class InputControlSystem;
class Channel;
class ChannelListener;
class Control;
class ControlListener;
class DetectingBindingListener;
class InputControlSystemLog;
}
#endif

@ -1,99 +1,99 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
#ifndef SOL_ASSERT_HPP
#define SOL_ASSERT_HPP
#include <sol/forward.hpp>
#if SOL_IS_ON(SOL2_CI_I_)
struct pre_main {
pre_main() {
#ifdef _MSC_VER
_set_abort_behavior(0, _WRITE_ABORT_MSG);
#endif
}
} inline sol2_ci_dont_lock_ci_please = {};
#endif // Prevent lockup when doing Continuous Integration
// clang-format off
#if SOL_IS_ON(SOL_USER_C_ASSERT_I_)
#define sol_c_assert(...) SOL_C_ASSERT(__VA_ARGS__)
#else
#if SOL_IS_ON(SOL_DEBUG_BUILD_I_)
#include <exception>
#include <iostream>
#include <cstdlib>
#define sol_c_assert(...) \
do { \
if (!(__VA_ARGS__)) { \
std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << std::endl; \
std::terminate(); \
} \
} while (false)
#else
#define sol_c_assert(...) \
do { \
if (false) { \
(void)(__VA_ARGS__); \
} \
} while (false)
#endif
#endif
#if SOL_IS_ON(SOL_USER_M_ASSERT_I_)
#define sol_m_assert(message, ...) SOL_M_ASSERT(message, __VA_ARGS__)
#else
#if SOL_IS_ON(SOL_DEBUG_BUILD_I_)
#include <exception>
#include <iostream>
#include <cstdlib>
#define sol_m_assert(message, ...) \
do { \
if (!(__VA_ARGS__)) { \
std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << ": " << message << std::endl; \
std::terminate(); \
} \
} while (false)
#else
#define sol_m_assert(message, ...) \
do { \
if (false) { \
(void)(__VA_ARGS__); \
(void)sizeof(message); \
} \
} while (false)
#endif
#endif
// clang-format on
#endif // SOL_ASSERT_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
#ifndef SOL_ASSERT_HPP
#define SOL_ASSERT_HPP
#include <sol/forward.hpp>
#if SOL_IS_ON(SOL2_CI_I_)
struct pre_main {
pre_main() {
#ifdef _MSC_VER
_set_abort_behavior(0, _WRITE_ABORT_MSG);
#endif
}
} inline sol2_ci_dont_lock_ci_please = {};
#endif // Prevent lockup when doing Continuous Integration
// clang-format off
#if SOL_IS_ON(SOL_USER_C_ASSERT_I_)
#define sol_c_assert(...) SOL_C_ASSERT(__VA_ARGS__)
#else
#if SOL_IS_ON(SOL_DEBUG_BUILD_I_)
#include <exception>
#include <iostream>
#include <cstdlib>
#define sol_c_assert(...) \
do { \
if (!(__VA_ARGS__)) { \
std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << std::endl; \
std::terminate(); \
} \
} while (false)
#else
#define sol_c_assert(...) \
do { \
if (false) { \
(void)(__VA_ARGS__); \
} \
} while (false)
#endif
#endif
#if SOL_IS_ON(SOL_USER_M_ASSERT_I_)
#define sol_m_assert(message, ...) SOL_M_ASSERT(message, __VA_ARGS__)
#else
#if SOL_IS_ON(SOL_DEBUG_BUILD_I_)
#include <exception>
#include <iostream>
#include <cstdlib>
#define sol_m_assert(message, ...) \
do { \
if (!(__VA_ARGS__)) { \
std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << ": " << message << std::endl; \
std::terminate(); \
} \
} while (false)
#else
#define sol_m_assert(message, ...) \
do { \
if (false) { \
(void)(__VA_ARGS__); \
(void)sizeof(message); \
} \
} while (false)
#endif
#endif
// clang-format on
#endif // SOL_ASSERT_HPP

@ -1,123 +1,123 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_BASE_TRAITS_HPP
#define SOL_BASE_TRAITS_HPP
#include <type_traits>
namespace sol {
namespace detail {
struct unchecked_t { };
const unchecked_t unchecked = unchecked_t {};
} // namespace detail
namespace meta {
using sfinae_yes_t = std::true_type;
using sfinae_no_t = std::false_type;
template <typename...>
using void_t = void;
template <typename T>
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
template <typename T>
using unqualified_t = typename unqualified<T>::type;
namespace meta_detail {
template <typename T>
struct unqualified_non_alias : unqualified<T> { };
template <template <class...> class Test, class, class... Args>
struct is_detected : std::false_type { };
template <template <class...> class Test, class... Args>
struct is_detected<Test, void_t<Test<Args...>>, Args...> : std::true_type { };
} // namespace meta_detail
template <template <class...> class Trait, class... Args>
using is_detected = typename meta_detail::is_detected<Trait, void, Args...>::type;
template <template <class...> class Trait, class... Args>
constexpr inline bool is_detected_v = is_detected<Trait, Args...>::value;
template <std::size_t I>
using index_value = std::integral_constant<std::size_t, I>;
template <bool>
struct conditional {
template <typename T, typename U>
using type = T;
};
template <>
struct conditional<false> {
template <typename T, typename U>
using type = U;
};
template <bool B, typename T, typename U>
using conditional_t = typename conditional<B>::template type<T, U>;
namespace meta_detail {
template <typename T, template <typename...> class Templ>
struct is_specialization_of : std::false_type { };
template <typename... T, template <typename...> class Templ>
struct is_specialization_of<Templ<T...>, Templ> : std::true_type { };
} // namespace meta_detail
template <typename T, template <typename...> class Templ>
using is_specialization_of = meta_detail::is_specialization_of<std::remove_cv_t<T>, Templ>;
template <typename T, template <typename...> class Templ>
inline constexpr bool is_specialization_of_v = is_specialization_of<std::remove_cv_t<T>, Templ>::value;
template <typename T>
struct identity {
typedef T type;
};
template <typename T>
using identity_t = typename identity<T>::type;
template <typename T>
using is_builtin_type = std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value>;
namespace meta_detail {
template <typename T, typename = void>
struct has_internal_marker_impl : std::false_type { };
template <typename T>
struct has_internal_marker_impl<T, void_t<typename T::SOL_INTERNAL_UNSPECIALIZED_MARKER_>> : std::true_type { };
template <typename T>
using has_internal_marker = has_internal_marker_impl<T>;
template <typename T>
constexpr inline bool has_internal_marker_v = has_internal_marker<T>::value;
} // namespace meta_detail
} // namespace meta
} // namespace sol
#endif // SOL_BASE_TRAITS_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_BASE_TRAITS_HPP
#define SOL_BASE_TRAITS_HPP
#include <type_traits>
namespace sol {
namespace detail {
struct unchecked_t { };
const unchecked_t unchecked = unchecked_t {};
} // namespace detail
namespace meta {
using sfinae_yes_t = std::true_type;
using sfinae_no_t = std::false_type;
template <typename...>
using void_t = void;
template <typename T>
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
template <typename T>
using unqualified_t = typename unqualified<T>::type;
namespace meta_detail {
template <typename T>
struct unqualified_non_alias : unqualified<T> { };
template <template <class...> class Test, class, class... Args>
struct is_detected : std::false_type { };
template <template <class...> class Test, class... Args>
struct is_detected<Test, void_t<Test<Args...>>, Args...> : std::true_type { };
} // namespace meta_detail
template <template <class...> class Trait, class... Args>
using is_detected = typename meta_detail::is_detected<Trait, void, Args...>::type;
template <template <class...> class Trait, class... Args>
constexpr inline bool is_detected_v = is_detected<Trait, Args...>::value;
template <std::size_t I>
using index_value = std::integral_constant<std::size_t, I>;
template <bool>
struct conditional {
template <typename T, typename U>
using type = T;
};
template <>
struct conditional<false> {
template <typename T, typename U>
using type = U;
};
template <bool B, typename T, typename U>
using conditional_t = typename conditional<B>::template type<T, U>;
namespace meta_detail {
template <typename T, template <typename...> class Templ>
struct is_specialization_of : std::false_type { };
template <typename... T, template <typename...> class Templ>
struct is_specialization_of<Templ<T...>, Templ> : std::true_type { };
} // namespace meta_detail
template <typename T, template <typename...> class Templ>
using is_specialization_of = meta_detail::is_specialization_of<std::remove_cv_t<T>, Templ>;
template <typename T, template <typename...> class Templ>
inline constexpr bool is_specialization_of_v = is_specialization_of<std::remove_cv_t<T>, Templ>::value;
template <typename T>
struct identity {
typedef T type;
};
template <typename T>
using identity_t = typename identity<T>::type;
template <typename T>
using is_builtin_type = std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value>;
namespace meta_detail {
template <typename T, typename = void>
struct has_internal_marker_impl : std::false_type { };
template <typename T>
struct has_internal_marker_impl<T, void_t<typename T::SOL_INTERNAL_UNSPECIALIZED_MARKER_>> : std::true_type { };
template <typename T>
using has_internal_marker = has_internal_marker_impl<T>;
template <typename T>
constexpr inline bool has_internal_marker_v = has_internal_marker<T>::value;
} // namespace meta_detail
} // namespace meta
} // namespace sol
#endif // SOL_BASE_TRAITS_HPP

@ -1,121 +1,121 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_BYTECODE_HPP
#define SOL_BYTECODE_HPP
#include <sol/compatibility.hpp>
#include <sol/string_view.hpp>
#include <vector>
#include <cstdint>
#include <cstddef>
namespace sol {
template <typename Allocator = std::allocator<std::byte>>
class basic_bytecode : private std::vector<std::byte, Allocator> {
private:
using base_t = std::vector<std::byte, Allocator>;
public:
using typename base_t::allocator_type;
using typename base_t::const_iterator;
using typename base_t::const_pointer;
using typename base_t::const_reference;
using typename base_t::const_reverse_iterator;
using typename base_t::difference_type;
using typename base_t::iterator;
using typename base_t::pointer;
using typename base_t::reference;
using typename base_t::reverse_iterator;
using typename base_t::size_type;
using typename base_t::value_type;
using base_t::base_t;
using base_t::operator=;
using base_t::data;
using base_t::empty;
using base_t::max_size;
using base_t::size;
using base_t::at;
using base_t::operator[];
using base_t::back;
using base_t::front;
using base_t::begin;
using base_t::cbegin;
using base_t::cend;
using base_t::end;
using base_t::crbegin;
using base_t::crend;
using base_t::rbegin;
using base_t::rend;
using base_t::get_allocator;
using base_t::swap;
using base_t::clear;
using base_t::emplace;
using base_t::emplace_back;
using base_t::erase;
using base_t::insert;
using base_t::pop_back;
using base_t::push_back;
using base_t::reserve;
using base_t::resize;
using base_t::shrink_to_fit;
string_view as_string_view() const {
return string_view(reinterpret_cast<const char*>(this->data()), this->size());
}
};
template <typename Container>
inline int basic_insert_dump_writer(lua_State*, const void* memory, size_t memory_size, void* userdata_pointer) {
using storage_t = Container;
const std::byte* p_code = static_cast<const std::byte*>(memory);
storage_t& bc = *static_cast<storage_t*>(userdata_pointer);
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
bc.insert(bc.cend(), p_code, p_code + memory_size);
#else
try {
bc.insert(bc.cend(), p_code, p_code + memory_size);
}
catch (...) {
return -1;
}
#endif
return 0;
}
using bytecode = basic_bytecode<>;
constexpr inline auto bytecode_dump_writer = &basic_insert_dump_writer<bytecode>;
} // namespace sol
#endif // SOL_BYTECODE_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_BYTECODE_HPP
#define SOL_BYTECODE_HPP
#include <sol/compatibility.hpp>
#include <sol/string_view.hpp>
#include <vector>
#include <cstdint>
#include <cstddef>
namespace sol {
template <typename Allocator = std::allocator<std::byte>>
class basic_bytecode : private std::vector<std::byte, Allocator> {
private:
using base_t = std::vector<std::byte, Allocator>;
public:
using typename base_t::allocator_type;
using typename base_t::const_iterator;
using typename base_t::const_pointer;
using typename base_t::const_reference;
using typename base_t::const_reverse_iterator;
using typename base_t::difference_type;
using typename base_t::iterator;
using typename base_t::pointer;
using typename base_t::reference;
using typename base_t::reverse_iterator;
using typename base_t::size_type;
using typename base_t::value_type;
using base_t::base_t;
using base_t::operator=;
using base_t::data;
using base_t::empty;
using base_t::max_size;
using base_t::size;
using base_t::at;
using base_t::operator[];
using base_t::back;
using base_t::front;
using base_t::begin;
using base_t::cbegin;
using base_t::cend;
using base_t::end;
using base_t::crbegin;
using base_t::crend;
using base_t::rbegin;
using base_t::rend;
using base_t::get_allocator;
using base_t::swap;
using base_t::clear;
using base_t::emplace;
using base_t::emplace_back;
using base_t::erase;
using base_t::insert;
using base_t::pop_back;
using base_t::push_back;
using base_t::reserve;
using base_t::resize;
using base_t::shrink_to_fit;
string_view as_string_view() const {
return string_view(reinterpret_cast<const char*>(this->data()), this->size());
}
};
template <typename Container>
inline int basic_insert_dump_writer(lua_State*, const void* memory, size_t memory_size, void* userdata_pointer) {
using storage_t = Container;
const std::byte* p_code = static_cast<const std::byte*>(memory);
storage_t& bc = *static_cast<storage_t*>(userdata_pointer);
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
bc.insert(bc.cend(), p_code, p_code + memory_size);
#else
try {
bc.insert(bc.cend(), p_code, p_code + memory_size);
}
catch (...) {
return -1;
}
#endif
return 0;
}
using bytecode = basic_bytecode<>;
constexpr inline auto bytecode_dump_writer = &basic_insert_dump_writer<bytecode>;
} // namespace sol
#endif // SOL_BYTECODE_HPP

File diff suppressed because it is too large Load Diff

@ -1,424 +1,424 @@
#ifndef KEPLER_PROJECT_COMPAT53_H_
#define KEPLER_PROJECT_COMPAT53_H_
#include <stddef.h>
#include <limits.h>
#include <string.h>
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
extern "C" {
#endif
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
}
#endif
#ifndef COMPAT53_PREFIX
/* we chose this name because many other lua bindings / libs have
* their own compatibility layer, and that use the compat53 declaration
* frequently, causing all kinds of linker / compiler issues
*/
# define COMPAT53_PREFIX kp_compat53
#endif // COMPAT53_PREFIX
#ifndef COMPAT53_API
# if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE
# if defined(__GNUC__) || defined(__clang__)
# define COMPAT53_API __attribute__((__unused__)) static inline
# else
# define COMPAT53_API static inline
# endif /* Clang/GCC */
# else /* COMPAT53_INCLUDE_SOURCE */
/* we are not including source, so everything is extern */
# define COMPAT53_API extern
# endif /* COMPAT53_INCLUDE_SOURCE */
#endif /* COMPAT53_PREFIX */
#define COMPAT53_CONCAT_HELPER(a, b) a##b
#define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b)
/* declarations for Lua 5.1 */
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
/* XXX not implemented:
* lua_arith (new operators)
* lua_upvalueid
* lua_upvaluejoin
* lua_version
* lua_yieldk
*/
#ifndef LUA_OK
# define LUA_OK 0
#endif
#ifndef LUA_OPADD
# define LUA_OPADD 0
#endif
#ifndef LUA_OPSUB
# define LUA_OPSUB 1
#endif
#ifndef LUA_OPMUL
# define LUA_OPMUL 2
#endif
#ifndef LUA_OPDIV
# define LUA_OPDIV 3
#endif
#ifndef LUA_OPMOD
# define LUA_OPMOD 4
#endif
#ifndef LUA_OPPOW
# define LUA_OPPOW 5
#endif
#ifndef LUA_OPUNM
# define LUA_OPUNM 6
#endif
#ifndef LUA_OPEQ
# define LUA_OPEQ 0
#endif
#ifndef LUA_OPLT
# define LUA_OPLT 1
#endif
#ifndef LUA_OPLE
# define LUA_OPLE 2
#endif
/* LuaJIT/Lua 5.1 does not have the updated
* error codes for thread status/function returns (but some patched versions do)
* define it only if it's not found
*/
#if !defined(LUA_ERRGCMM)
/* Use + 2 because in some versions of Lua (Lua 5.1)
* LUA_ERRFILE is defined as (LUA_ERRERR+1)
* so we need to avoid it (LuaJIT might have something at this
* integer value too)
*/
# define LUA_ERRGCMM (LUA_ERRERR + 2)
#endif /* LUA_ERRGCMM define */
#if !defined(MOONJIT_VERSION)
typedef size_t lua_Unsigned;
#endif
typedef struct luaL_Buffer_53 {
luaL_Buffer b; /* make incorrect code crash! */
char *ptr;
size_t nelems;
size_t capacity;
lua_State *L2;
} luaL_Buffer_53;
#define luaL_Buffer luaL_Buffer_53
/* In PUC-Rio 5.1, userdata is a simple FILE*
* In LuaJIT, it's a struct where the first member is a FILE*
* We can't support the `closef` member
*/
typedef struct luaL_Stream {
FILE *f;
} luaL_Stream;
#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
COMPAT53_API int lua_absindex(lua_State *L, int i);
#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith)
COMPAT53_API void lua_arith(lua_State *L, int op);
#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare)
COMPAT53_API int lua_compare(lua_State *L, int idx1, int idx2, int op);
#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy)
COMPAT53_API void lua_copy(lua_State *L, int from, int to);
#define lua_getuservalue(L, i) \
(lua_getfenv((L), (i)), lua_type((L), -1))
#define lua_setuservalue(L, i) \
(luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i)))
#define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len)
COMPAT53_API void lua_len(lua_State *L, int i);
#define lua_pushstring(L, s) \
(lua_pushstring((L), (s)), lua_tostring((L), -1))
#define lua_pushlstring(L, s, len) \
((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1))
#ifndef luaL_newlibtable
# define luaL_newlibtable(L, l) \
(lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1))
#endif
#ifndef luaL_newlib
# define luaL_newlib(L, l) \
(luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l)))
#endif
#ifndef lua_pushglobaltable
# define lua_pushglobaltable(L) \
lua_pushvalue((L), LUA_GLOBALSINDEX)
#endif
#define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp)
COMPAT53_API int lua_rawgetp(lua_State *L, int i, const void *p);
#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp)
COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p);
#define lua_rawlen(L, i) lua_objlen((L), (i))
#define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL)
#define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx)
COMPAT53_API lua_Number lua_tonumberx(lua_State *L, int i, int *isnum);
#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
COMPAT53_API void luaL_checkversion(lua_State *L);
#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
COMPAT53_API int lua_load(lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode);
#define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex)
COMPAT53_API int luaL_loadfilex(lua_State *L, const char *filename, const char *mode);
#define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx)
COMPAT53_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
#define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53)
COMPAT53_API void luaL_checkstack(lua_State *L, int sp, const char *msg);
#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable)
COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char *name);
#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len)
COMPAT53_API lua_Integer luaL_len(lua_State *L, int i);
#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs)
COMPAT53_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup);
#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable)
COMPAT53_API void luaL_setmetatable(lua_State *L, const char *tname);
#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata)
COMPAT53_API void *luaL_testudata(lua_State *L, int i, const char *tname);
#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback)
COMPAT53_API void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level);
#define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult)
COMPAT53_API int luaL_fileresult(lua_State *L, int stat, const char *fname);
#define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult)
COMPAT53_API int luaL_execresult(lua_State *L, int stat);
#define lua_callk(L, na, nr, ctx, cont) \
((void)(ctx), (void)(cont), lua_call((L), (na), (nr)))
#define lua_pcallk(L, na, nr, err, ctx, cont) \
((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err)))
#define lua_resume(L, from, nargs) \
((void)(from), lua_resume((L), (nargs)))
#define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53)
COMPAT53_API void luaL_buffinit(lua_State *L, luaL_Buffer_53 *B);
#define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53)
COMPAT53_API char *luaL_prepbuffsize(luaL_Buffer_53 *B, size_t s);
#define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53)
COMPAT53_API void luaL_addlstring(luaL_Buffer_53 *B, const char *s, size_t l);
#define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53)
COMPAT53_API void luaL_addvalue(luaL_Buffer_53 *B);
#define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53)
COMPAT53_API void luaL_pushresult(luaL_Buffer_53 *B);
#undef luaL_buffinitsize
#define luaL_buffinitsize(L, B, s) \
(luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s)))
#undef luaL_prepbuffer
#define luaL_prepbuffer(B) \
luaL_prepbuffsize((B), LUAL_BUFFERSIZE)
#undef luaL_addchar
#define luaL_addchar(B, c) \
((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \
((B)->ptr[(B)->nelems++] = (c)))
#undef luaL_addsize
#define luaL_addsize(B, s) \
((B)->nelems += (s))
#undef luaL_addstring
#define luaL_addstring(B, s) \
luaL_addlstring((B), (s), strlen((s)))
#undef luaL_pushresultsize
#define luaL_pushresultsize(B, s) \
(luaL_addsize((B), (s)), luaL_pushresult((B)))
#if defined(LUA_COMPAT_APIINTCASTS)
#define lua_pushunsigned(L, n) \
lua_pushinteger((L), (lua_Integer)(n))
#define lua_tounsignedx(L, i, is) \
((lua_Unsigned)lua_tointegerx((L), (i), (is)))
#define lua_tounsigned(L, i) \
lua_tounsignedx((L), (i), NULL)
#define luaL_checkunsigned(L, a) \
((lua_Unsigned)luaL_checkinteger((L), (a)))
#define luaL_optunsigned(L, a, d) \
((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d)))
#endif
#endif /* Lua 5.1 only */
/* declarations for Lua 5.1 and 5.2 */
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
typedef int lua_KContext;
typedef int(*lua_KFunction)(lua_State *L, int status, lua_KContext ctx);
#define lua_dump(L, w, d, s) \
((void)(s), lua_dump((L), (w), (d)))
#define lua_getfield(L, i, k) \
(lua_getfield((L), (i), (k)), lua_type((L), -1))
#define lua_gettable(L, i) \
(lua_gettable((L), (i)), lua_type((L), -1))
#define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti)
COMPAT53_API int lua_geti(lua_State *L, int index, lua_Integer i);
#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger)
COMPAT53_API int lua_isinteger(lua_State *L, int index);
#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53)
COMPAT53_API lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum);
#define lua_numbertointeger(n, p) \
((*(p) = (lua_Integer)(n)), 1)
#define lua_rawget(L, i) \
(lua_rawget((L), (i)), lua_type((L), -1))
#define lua_rawgeti(L, i, n) \
(lua_rawgeti((L), (i), (n)), lua_type((L), -1))
#define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate)
COMPAT53_API void lua_rotate(lua_State *L, int idx, int n);
#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti)
COMPAT53_API void lua_seti(lua_State *L, int index, lua_Integer i);
#define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber)
COMPAT53_API size_t lua_stringtonumber(lua_State *L, const char *s);
#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring)
COMPAT53_API const char *luaL_tolstring(lua_State *L, int idx, size_t *len);
#define luaL_getmetafield(L, o, e) \
(luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL)
#define luaL_newmetatable(L, tn) \
(luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0)
#define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53)
COMPAT53_API void luaL_requiref(lua_State *L, const char *modname,
lua_CFunction openf, int glb);
#endif /* Lua 5.1 and Lua 5.2 */
/* declarations for Lua 5.2 */
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502
/* XXX not implemented:
* lua_isyieldable
* lua_getextraspace
* lua_arith (new operators)
* lua_pushfstring (new formats)
*/
#define lua_getglobal(L, n) \
(lua_getglobal((L), (n)), lua_type((L), -1))
#define lua_getuservalue(L, i) \
(lua_getuservalue((L), (i)), lua_type((L), -1))
#define lua_pushlstring(L, s, len) \
(((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len)))
#define lua_rawgetp(L, i, p) \
(lua_rawgetp((L), (i), (p)), lua_type((L), -1))
#define LUA_KFUNCTION(_name) \
static int (_name)(lua_State *L, int status, lua_KContext ctx); \
static int (_name ## _52)(lua_State *L) { \
lua_KContext ctx; \
int status = lua_getctx(L, &ctx); \
return (_name)(L, status, ctx); \
} \
static int (_name)(lua_State *L, int status, lua_KContext ctx)
#define lua_pcallk(L, na, nr, err, ctx, cont) \
lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52)
#define lua_callk(L, na, nr, ctx, cont) \
lua_callk((L), (na), (nr), (ctx), cont ## _52)
#define lua_yieldk(L, nr, ctx, cont) \
lua_yieldk((L), (nr), (ctx), cont ## _52)
#ifdef lua_call
# undef lua_call
# define lua_call(L, na, nr) \
(lua_callk)((L), (na), (nr), 0, NULL)
#endif
#ifdef lua_pcall
# undef lua_pcall
# define lua_pcall(L, na, nr, err) \
(lua_pcallk)((L), (na), (nr), (err), 0, NULL)
#endif
#ifdef lua_yield
# undef lua_yield
# define lua_yield(L, nr) \
(lua_yieldk)((L), (nr), 0, NULL)
#endif
#endif /* Lua 5.2 only */
/* other Lua versions */
#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504
# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, or 5.4)"
#endif /* other Lua versions except 5.1, 5.2, 5.3, and 5.4 */
/* helper macro for defining continuation functions (for every version
* *except* Lua 5.2) */
#ifndef LUA_KFUNCTION
#define LUA_KFUNCTION(_name) \
static int (_name)(lua_State *L, int status, lua_KContext ctx)
#endif
#if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE == 1
# include "compat-5.3.c.h"
#endif
#endif /* KEPLER_PROJECT_COMPAT53_H_ */
#ifndef KEPLER_PROJECT_COMPAT53_H_
#define KEPLER_PROJECT_COMPAT53_H_
#include <stddef.h>
#include <limits.h>
#include <string.h>
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
extern "C" {
#endif
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
}
#endif
#ifndef COMPAT53_PREFIX
/* we chose this name because many other lua bindings / libs have
* their own compatibility layer, and that use the compat53 declaration
* frequently, causing all kinds of linker / compiler issues
*/
# define COMPAT53_PREFIX kp_compat53
#endif // COMPAT53_PREFIX
#ifndef COMPAT53_API
# if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE
# if defined(__GNUC__) || defined(__clang__)
# define COMPAT53_API __attribute__((__unused__)) static inline
# else
# define COMPAT53_API static inline
# endif /* Clang/GCC */
# else /* COMPAT53_INCLUDE_SOURCE */
/* we are not including source, so everything is extern */
# define COMPAT53_API extern
# endif /* COMPAT53_INCLUDE_SOURCE */
#endif /* COMPAT53_PREFIX */
#define COMPAT53_CONCAT_HELPER(a, b) a##b
#define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b)
/* declarations for Lua 5.1 */
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
/* XXX not implemented:
* lua_arith (new operators)
* lua_upvalueid
* lua_upvaluejoin
* lua_version
* lua_yieldk
*/
#ifndef LUA_OK
# define LUA_OK 0
#endif
#ifndef LUA_OPADD
# define LUA_OPADD 0
#endif
#ifndef LUA_OPSUB
# define LUA_OPSUB 1
#endif
#ifndef LUA_OPMUL
# define LUA_OPMUL 2
#endif
#ifndef LUA_OPDIV
# define LUA_OPDIV 3
#endif
#ifndef LUA_OPMOD
# define LUA_OPMOD 4
#endif
#ifndef LUA_OPPOW
# define LUA_OPPOW 5
#endif
#ifndef LUA_OPUNM
# define LUA_OPUNM 6
#endif
#ifndef LUA_OPEQ
# define LUA_OPEQ 0
#endif
#ifndef LUA_OPLT
# define LUA_OPLT 1
#endif
#ifndef LUA_OPLE
# define LUA_OPLE 2
#endif
/* LuaJIT/Lua 5.1 does not have the updated
* error codes for thread status/function returns (but some patched versions do)
* define it only if it's not found
*/
#if !defined(LUA_ERRGCMM)
/* Use + 2 because in some versions of Lua (Lua 5.1)
* LUA_ERRFILE is defined as (LUA_ERRERR+1)
* so we need to avoid it (LuaJIT might have something at this
* integer value too)
*/
# define LUA_ERRGCMM (LUA_ERRERR + 2)
#endif /* LUA_ERRGCMM define */
#if !defined(MOONJIT_VERSION)
typedef size_t lua_Unsigned;
#endif
typedef struct luaL_Buffer_53 {
luaL_Buffer b; /* make incorrect code crash! */
char *ptr;
size_t nelems;
size_t capacity;
lua_State *L2;
} luaL_Buffer_53;
#define luaL_Buffer luaL_Buffer_53
/* In PUC-Rio 5.1, userdata is a simple FILE*
* In LuaJIT, it's a struct where the first member is a FILE*
* We can't support the `closef` member
*/
typedef struct luaL_Stream {
FILE *f;
} luaL_Stream;
#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
COMPAT53_API int lua_absindex(lua_State *L, int i);
#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith)
COMPAT53_API void lua_arith(lua_State *L, int op);
#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare)
COMPAT53_API int lua_compare(lua_State *L, int idx1, int idx2, int op);
#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy)
COMPAT53_API void lua_copy(lua_State *L, int from, int to);
#define lua_getuservalue(L, i) \
(lua_getfenv((L), (i)), lua_type((L), -1))
#define lua_setuservalue(L, i) \
(luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i)))
#define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len)
COMPAT53_API void lua_len(lua_State *L, int i);
#define lua_pushstring(L, s) \
(lua_pushstring((L), (s)), lua_tostring((L), -1))
#define lua_pushlstring(L, s, len) \
((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1))
#ifndef luaL_newlibtable
# define luaL_newlibtable(L, l) \
(lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1))
#endif
#ifndef luaL_newlib
# define luaL_newlib(L, l) \
(luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l)))
#endif
#ifndef lua_pushglobaltable
# define lua_pushglobaltable(L) \
lua_pushvalue((L), LUA_GLOBALSINDEX)
#endif
#define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp)
COMPAT53_API int lua_rawgetp(lua_State *L, int i, const void *p);
#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp)
COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p);
#define lua_rawlen(L, i) lua_objlen((L), (i))
#define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL)
#define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx)
COMPAT53_API lua_Number lua_tonumberx(lua_State *L, int i, int *isnum);
#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
COMPAT53_API void luaL_checkversion(lua_State *L);
#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
COMPAT53_API int lua_load(lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode);
#define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex)
COMPAT53_API int luaL_loadfilex(lua_State *L, const char *filename, const char *mode);
#define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx)
COMPAT53_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
#define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53)
COMPAT53_API void luaL_checkstack(lua_State *L, int sp, const char *msg);
#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable)
COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char *name);
#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len)
COMPAT53_API lua_Integer luaL_len(lua_State *L, int i);
#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs)
COMPAT53_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup);
#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable)
COMPAT53_API void luaL_setmetatable(lua_State *L, const char *tname);
#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata)
COMPAT53_API void *luaL_testudata(lua_State *L, int i, const char *tname);
#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback)
COMPAT53_API void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level);
#define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult)
COMPAT53_API int luaL_fileresult(lua_State *L, int stat, const char *fname);
#define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult)
COMPAT53_API int luaL_execresult(lua_State *L, int stat);
#define lua_callk(L, na, nr, ctx, cont) \
((void)(ctx), (void)(cont), lua_call((L), (na), (nr)))
#define lua_pcallk(L, na, nr, err, ctx, cont) \
((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err)))
#define lua_resume(L, from, nargs) \
((void)(from), lua_resume((L), (nargs)))
#define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53)
COMPAT53_API void luaL_buffinit(lua_State *L, luaL_Buffer_53 *B);
#define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53)
COMPAT53_API char *luaL_prepbuffsize(luaL_Buffer_53 *B, size_t s);
#define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53)
COMPAT53_API void luaL_addlstring(luaL_Buffer_53 *B, const char *s, size_t l);
#define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53)
COMPAT53_API void luaL_addvalue(luaL_Buffer_53 *B);
#define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53)
COMPAT53_API void luaL_pushresult(luaL_Buffer_53 *B);
#undef luaL_buffinitsize
#define luaL_buffinitsize(L, B, s) \
(luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s)))
#undef luaL_prepbuffer
#define luaL_prepbuffer(B) \
luaL_prepbuffsize((B), LUAL_BUFFERSIZE)
#undef luaL_addchar
#define luaL_addchar(B, c) \
((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \
((B)->ptr[(B)->nelems++] = (c)))
#undef luaL_addsize
#define luaL_addsize(B, s) \
((B)->nelems += (s))
#undef luaL_addstring
#define luaL_addstring(B, s) \
luaL_addlstring((B), (s), strlen((s)))
#undef luaL_pushresultsize
#define luaL_pushresultsize(B, s) \
(luaL_addsize((B), (s)), luaL_pushresult((B)))
#if defined(LUA_COMPAT_APIINTCASTS)
#define lua_pushunsigned(L, n) \
lua_pushinteger((L), (lua_Integer)(n))
#define lua_tounsignedx(L, i, is) \
((lua_Unsigned)lua_tointegerx((L), (i), (is)))
#define lua_tounsigned(L, i) \
lua_tounsignedx((L), (i), NULL)
#define luaL_checkunsigned(L, a) \
((lua_Unsigned)luaL_checkinteger((L), (a)))
#define luaL_optunsigned(L, a, d) \
((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d)))
#endif
#endif /* Lua 5.1 only */
/* declarations for Lua 5.1 and 5.2 */
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
typedef int lua_KContext;
typedef int(*lua_KFunction)(lua_State *L, int status, lua_KContext ctx);
#define lua_dump(L, w, d, s) \
((void)(s), lua_dump((L), (w), (d)))
#define lua_getfield(L, i, k) \
(lua_getfield((L), (i), (k)), lua_type((L), -1))
#define lua_gettable(L, i) \
(lua_gettable((L), (i)), lua_type((L), -1))
#define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti)
COMPAT53_API int lua_geti(lua_State *L, int index, lua_Integer i);
#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger)
COMPAT53_API int lua_isinteger(lua_State *L, int index);
#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53)
COMPAT53_API lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum);
#define lua_numbertointeger(n, p) \
((*(p) = (lua_Integer)(n)), 1)
#define lua_rawget(L, i) \
(lua_rawget((L), (i)), lua_type((L), -1))
#define lua_rawgeti(L, i, n) \
(lua_rawgeti((L), (i), (n)), lua_type((L), -1))
#define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate)
COMPAT53_API void lua_rotate(lua_State *L, int idx, int n);
#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti)
COMPAT53_API void lua_seti(lua_State *L, int index, lua_Integer i);
#define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber)
COMPAT53_API size_t lua_stringtonumber(lua_State *L, const char *s);
#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring)
COMPAT53_API const char *luaL_tolstring(lua_State *L, int idx, size_t *len);
#define luaL_getmetafield(L, o, e) \
(luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL)
#define luaL_newmetatable(L, tn) \
(luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0)
#define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53)
COMPAT53_API void luaL_requiref(lua_State *L, const char *modname,
lua_CFunction openf, int glb);
#endif /* Lua 5.1 and Lua 5.2 */
/* declarations for Lua 5.2 */
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502
/* XXX not implemented:
* lua_isyieldable
* lua_getextraspace
* lua_arith (new operators)
* lua_pushfstring (new formats)
*/
#define lua_getglobal(L, n) \
(lua_getglobal((L), (n)), lua_type((L), -1))
#define lua_getuservalue(L, i) \
(lua_getuservalue((L), (i)), lua_type((L), -1))
#define lua_pushlstring(L, s, len) \
(((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len)))
#define lua_rawgetp(L, i, p) \
(lua_rawgetp((L), (i), (p)), lua_type((L), -1))
#define LUA_KFUNCTION(_name) \
static int (_name)(lua_State *L, int status, lua_KContext ctx); \
static int (_name ## _52)(lua_State *L) { \
lua_KContext ctx; \
int status = lua_getctx(L, &ctx); \
return (_name)(L, status, ctx); \
} \
static int (_name)(lua_State *L, int status, lua_KContext ctx)
#define lua_pcallk(L, na, nr, err, ctx, cont) \
lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52)
#define lua_callk(L, na, nr, ctx, cont) \
lua_callk((L), (na), (nr), (ctx), cont ## _52)
#define lua_yieldk(L, nr, ctx, cont) \
lua_yieldk((L), (nr), (ctx), cont ## _52)
#ifdef lua_call
# undef lua_call
# define lua_call(L, na, nr) \
(lua_callk)((L), (na), (nr), 0, NULL)
#endif
#ifdef lua_pcall
# undef lua_pcall
# define lua_pcall(L, na, nr, err) \
(lua_pcallk)((L), (na), (nr), (err), 0, NULL)
#endif
#ifdef lua_yield
# undef lua_yield
# define lua_yield(L, nr) \
(lua_yieldk)((L), (nr), 0, NULL)
#endif
#endif /* Lua 5.2 only */
/* other Lua versions */
#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504
# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, or 5.4)"
#endif /* other Lua versions except 5.1, 5.2, 5.3, and 5.4 */
/* helper macro for defining continuation functions (for every version
* *except* Lua 5.2) */
#ifndef LUA_KFUNCTION
#define LUA_KFUNCTION(_name) \
static int (_name)(lua_State *L, int status, lua_KContext ctx)
#endif
#if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE == 1
# include "compat-5.3.c.h"
#endif
#endif /* KEPLER_PROJECT_COMPAT53_H_ */

@ -1,25 +1,25 @@
#ifndef NOT_KEPLER_PROJECT_COMPAT54_H_
#define NOT_KEPLER_PROJECT_COMPAT54_H_
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
extern "C" {
#endif
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
}
#endif
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 504
#if !defined(LUA_ERRGCMM)
/* So Lua 5.4 actually removes this, which breaks sol2...
man, this API is quite unstable...!
*/
# define LUA_ERRGCMM (LUA_ERRERR + 2)
#endif /* LUA_ERRGCMM define */
#endif // Lua 5.4 only
#ifndef NOT_KEPLER_PROJECT_COMPAT54_H_
#define NOT_KEPLER_PROJECT_COMPAT54_H_
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
extern "C" {
#endif
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
}
#endif
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 504
#if !defined(LUA_ERRGCMM)
/* So Lua 5.4 actually removes this, which breaks sol2...
man, this API is quite unstable...!
*/
# define LUA_ERRGCMM (LUA_ERRERR + 2)
#endif /* LUA_ERRGCMM define */
#endif // Lua 5.4 only
#endif // NOT_KEPLER_PROJECT_COMPAT54_H_

@ -1,52 +1,52 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_DEBUG_HPP
#define SOL_DEBUG_HPP
#include <sol/stack.hpp>
#include <iostream>
namespace sol { namespace detail { namespace debug {
inline std::string dump_types(lua_State* L) {
std::string visual;
std::size_t size = lua_gettop(L) + 1;
for (std::size_t i = 1; i < size; ++i) {
if (i != 1) {
visual += " | ";
}
visual += type_name(L, stack::get<type>(L, static_cast<int>(i)));
}
return visual;
}
inline void print_stack(lua_State* L) {
std::cout << dump_types(L) << std::endl;
}
inline void print_section(const std::string& message, lua_State* L) {
std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl;
}
}}} // namespace sol::detail::debug
#endif // SOL_DEBUG_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_DEBUG_HPP
#define SOL_DEBUG_HPP
#include <sol/stack.hpp>
#include <iostream>
namespace sol { namespace detail { namespace debug {
inline std::string dump_types(lua_State* L) {
std::string visual;
std::size_t size = lua_gettop(L) + 1;
for (std::size_t i = 1; i < size; ++i) {
if (i != 1) {
visual += " | ";
}
visual += type_name(L, stack::get<type>(L, static_cast<int>(i)));
}
return visual;
}
inline void print_stack(lua_State* L) {
std::cout << dump_types(L) << std::endl;
}
inline void print_section(const std::string& message, lua_State* L) {
std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl;
}
}}} // namespace sol::detail::debug
#endif // SOL_DEBUG_HPP

@ -1,44 +1,44 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_DEPRECATE_HPP
#define SOL_DEPRECATE_HPP
#ifndef SOL_DEPRECATED
#ifdef _MSC_VER
#define SOL_DEPRECATED __declspec(deprecated)
#elif __GNUC__
#define SOL_DEPRECATED __attribute__((deprecated))
#else
#define SOL_DEPRECATED [[deprecated]]
#endif // compilers
#endif // SOL_DEPRECATED
namespace sol { namespace detail {
template <typename T>
struct SOL_DEPRECATED deprecate_type {
using type = T;
};
}} // namespace sol::detail
#endif // SOL_DEPRECATE_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_DEPRECATE_HPP
#define SOL_DEPRECATE_HPP
#ifndef SOL_DEPRECATED
#ifdef _MSC_VER
#define SOL_DEPRECATED __declspec(deprecated)
#elif __GNUC__
#define SOL_DEPRECATED __attribute__((deprecated))
#else
#define SOL_DEPRECATED [[deprecated]]
#endif // compilers
#endif // SOL_DEPRECATED
namespace sol { namespace detail {
template <typename T>
struct SOL_DEPRECATED deprecate_type {
using type = T;
};
}} // namespace sol::detail
#endif // SOL_DEPRECATE_HPP

@ -1,232 +1,232 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
#ifndef SOL_DETAIL_BUILD_VERSION_HPP
#define SOL_DETAIL_BUILD_VERSION_HPP
#include <sol/version.hpp>
// clang-format off
#if defined(SOL_DLL)
#if (SOL_DLL != 0)
#define SOL_DLL_I_ SOL_ON
#else
#define SOL_DLL_I_ SOL_OFF
#endif
#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_) && (defined(DLL_) || defined(_DLL))
#define SOL_DLL_I_ SOL_DEFAULT_ON
#else
#define SOL_DLL_I_ SOL_DEFAULT_OFF
#endif // DLL definition
#if defined(SOL_HEADER_ONLY)
#if (SOL_HEADER_ONLY != 0)
#define SOL_HEADER_ONLY_I_ SOL_ON
#else
#define SOL_HEADER_ONLY_I_ SOL_OFF
#endif
#else
#define SOL_HEADER_ONLY_I_ SOL_DEFAULT_OFF
#endif // Header only library
#if defined(SOL_BUILD)
#if (SOL_BUILD != 0)
#define SOL_BUILD_I_ SOL_ON
#else
#define SOL_BUILD_I_ SOL_OFF
#endif
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_BUILD_I_ SOL_DEFAULT_OFF
#else
#define SOL_BUILD_I_ SOL_DEFAULT_ON
#endif
#if defined(SOL_UNITY_BUILD)
#if (SOL_UNITY_BUILD != 0)
#define SOL_UNITY_BUILD_I_ SOL_ON
#else
#define SOL_UNITY_BUILD_I_ SOL_OFF
#endif
#else
#define SOL_UNITY_BUILD_I_ SOL_DEFAULT_OFF
#endif // Header only library
#if defined(SOL_C_FUNCTION_LINKAGE)
#define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE
#else
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_)
// C++
#define SOL_C_FUNCTION_LINKAGE_I_ extern "C"
#else
// normal
#define SOL_C_FUNCTION_LINKAGE_I_
#endif // C++ or not
#endif // Linkage specification for C functions
#if defined(SOL_API_LINKAGE)
#define SOL_API_LINKAGE_I_ SOL_API_LINKAGE
#else
#if SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) || SOL_IS_ON(SOL_PLATFORM_WINDOWS_I_) || SOL_IS_ON(SOL_PLATFORM_CYGWIN_I_)
// MSVC Compiler; or, Windows, or Cygwin platforms
#if SOL_IS_ON(SOL_BUILD_I_)
// Building the library
#if SOL_IS_ON(SOL_COMPILER_GCC_I_)
// Using GCC
#define SOL_API_LINKAGE_I_ __attribute__((dllexport))
#else
// Using Clang, MSVC, etc...
#define SOL_API_LINKAGE_I_ __declspec(dllexport)
#endif
#else
#if SOL_IS_ON(SOL_COMPILER_GCC_I_)
#define SOL_API_LINKAGE_I_ __attribute__((dllimport))
#else
#define SOL_API_LINKAGE_I_ __declspec(dllimport)
#endif
#endif
#else
// extern if building normally on non-MSVC
#define SOL_API_LINKAGE_I_ extern
#endif
#elif SOL_IS_ON(SOL_UNITY_BUILD_I_)
// Built-in library, like how stb typical works
#if SOL_IS_ON(SOL_HEADER_ONLY_I_)
// Header only, so functions are defined "inline"
#define SOL_API_LINKAGE_I_ inline
#else
// Not header only, so seperately compiled files
#define SOL_API_LINKAGE_I_ extern
#endif
#else
// Normal static library
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_)
#define SOL_API_LINKAGE_I_
#else
#define SOL_API_LINKAGE_I_ extern
#endif
#endif // DLL or not
#endif // Build definitions
#if defined(SOL_PUBLIC_FUNC_DECL)
#define SOL_PUBLIC_FUNC_DECL_I_ SOL_PUBLIC_FUNC_DECL
#else
#define SOL_PUBLIC_FUNC_DECL_I_ SOL_API_LINKAGE_I_
#endif
#if defined(SOL_INTERNAL_FUNC_DECL_)
#define SOL_INTERNAL_FUNC_DECL_I_ SOL_INTERNAL_FUNC_DECL_
#else
#define SOL_INTERNAL_FUNC_DECL_I_ SOL_API_LINKAGE_I_
#endif
#if defined(SOL_PUBLIC_FUNC_DEF)
#define SOL_PUBLIC_FUNC_DEF_I_ SOL_PUBLIC_FUNC_DEF
#else
#define SOL_PUBLIC_FUNC_DEF_I_ SOL_API_LINKAGE_I_
#endif
#if defined(SOL_INTERNAL_FUNC_DEF)
#define SOL_INTERNAL_FUNC_DEF_I_ SOL_INTERNAL_FUNC_DEF
#else
#define SOL_INTERNAL_FUNC_DEF_I_ SOL_API_LINKAGE_I_
#endif
#if defined(SOL_FUNC_DECL)
#define SOL_FUNC_DECL_I_ SOL_FUNC_DECL
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_FUNC_DECL_I_
#elif SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
#if SOL_IS_ON(SOL_BUILD_I_)
#define SOL_FUNC_DECL_I_ extern __declspec(dllexport)
#else
#define SOL_FUNC_DECL_I_ extern __declspec(dllimport)
#endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default")))
#else
#define SOL_FUNC_DECL_I_ extern
#endif
#endif
#if defined(SOL_FUNC_DEFN)
#define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_FUNC_DEFN_I_ inline
#elif SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
#if SOL_IS_ON(SOL_BUILD_I_)
#define SOL_FUNC_DEFN_I_ __declspec(dllexport)
#else
#define SOL_FUNC_DEFN_I_ __declspec(dllimport)
#endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define SOL_FUNC_DEFN_I_ __attribute__((visibility("default")))
#else
#define SOL_FUNC_DEFN_I_
#endif
#endif
#if defined(SOL_HIDDEN_FUNC_DECL)
#define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_HIDDEN_FUNC_DECL_I_
#elif SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
#if SOL_IS_ON(SOL_BUILD_I_)
#define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport)
#else
#define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport)
#endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default")))
#else
#define SOL_HIDDEN_FUNC_DECL_I_ extern
#endif
#endif
#if defined(SOL_HIDDEN_FUNC_DEFN)
#define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_HIDDEN_FUNC_DEFN_I_ inline
#elif SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
#if SOL_IS_ON(SOL_BUILD_I_)
#define SOL_HIDDEN_FUNC_DEFN_I_
#else
#define SOL_HIDDEN_FUNC_DEFN_I_
#endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden")))
#else
#define SOL_HIDDEN_FUNC_DEFN_I_
#endif
#endif
// clang-format on
#endif // SOL_DETAIL_BUILD_VERSION_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
#ifndef SOL_DETAIL_BUILD_VERSION_HPP
#define SOL_DETAIL_BUILD_VERSION_HPP
#include <sol/version.hpp>
// clang-format off
#if defined(SOL_DLL)
#if (SOL_DLL != 0)
#define SOL_DLL_I_ SOL_ON
#else
#define SOL_DLL_I_ SOL_OFF
#endif
#elif SOL_IS_ON(SOL_COMPILER_VCXX_I_) && (defined(DLL_) || defined(_DLL))
#define SOL_DLL_I_ SOL_DEFAULT_ON
#else
#define SOL_DLL_I_ SOL_DEFAULT_OFF
#endif // DLL definition
#if defined(SOL_HEADER_ONLY)
#if (SOL_HEADER_ONLY != 0)
#define SOL_HEADER_ONLY_I_ SOL_ON
#else
#define SOL_HEADER_ONLY_I_ SOL_OFF
#endif
#else
#define SOL_HEADER_ONLY_I_ SOL_DEFAULT_OFF
#endif // Header only library
#if defined(SOL_BUILD)
#if (SOL_BUILD != 0)
#define SOL_BUILD_I_ SOL_ON
#else
#define SOL_BUILD_I_ SOL_OFF
#endif
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_BUILD_I_ SOL_DEFAULT_OFF
#else
#define SOL_BUILD_I_ SOL_DEFAULT_ON
#endif
#if defined(SOL_UNITY_BUILD)
#if (SOL_UNITY_BUILD != 0)
#define SOL_UNITY_BUILD_I_ SOL_ON
#else
#define SOL_UNITY_BUILD_I_ SOL_OFF
#endif
#else
#define SOL_UNITY_BUILD_I_ SOL_DEFAULT_OFF
#endif // Header only library
#if defined(SOL_C_FUNCTION_LINKAGE)
#define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE
#else
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_)
// C++
#define SOL_C_FUNCTION_LINKAGE_I_ extern "C"
#else
// normal
#define SOL_C_FUNCTION_LINKAGE_I_
#endif // C++ or not
#endif // Linkage specification for C functions
#if defined(SOL_API_LINKAGE)
#define SOL_API_LINKAGE_I_ SOL_API_LINKAGE
#else
#if SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_) || SOL_IS_ON(SOL_PLATFORM_WINDOWS_I_) || SOL_IS_ON(SOL_PLATFORM_CYGWIN_I_)
// MSVC Compiler; or, Windows, or Cygwin platforms
#if SOL_IS_ON(SOL_BUILD_I_)
// Building the library
#if SOL_IS_ON(SOL_COMPILER_GCC_I_)
// Using GCC
#define SOL_API_LINKAGE_I_ __attribute__((dllexport))
#else
// Using Clang, MSVC, etc...
#define SOL_API_LINKAGE_I_ __declspec(dllexport)
#endif
#else
#if SOL_IS_ON(SOL_COMPILER_GCC_I_)
#define SOL_API_LINKAGE_I_ __attribute__((dllimport))
#else
#define SOL_API_LINKAGE_I_ __declspec(dllimport)
#endif
#endif
#else
// extern if building normally on non-MSVC
#define SOL_API_LINKAGE_I_ extern
#endif
#elif SOL_IS_ON(SOL_UNITY_BUILD_I_)
// Built-in library, like how stb typical works
#if SOL_IS_ON(SOL_HEADER_ONLY_I_)
// Header only, so functions are defined "inline"
#define SOL_API_LINKAGE_I_ inline
#else
// Not header only, so seperately compiled files
#define SOL_API_LINKAGE_I_ extern
#endif
#else
// Normal static library
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_)
#define SOL_API_LINKAGE_I_
#else
#define SOL_API_LINKAGE_I_ extern
#endif
#endif // DLL or not
#endif // Build definitions
#if defined(SOL_PUBLIC_FUNC_DECL)
#define SOL_PUBLIC_FUNC_DECL_I_ SOL_PUBLIC_FUNC_DECL
#else
#define SOL_PUBLIC_FUNC_DECL_I_ SOL_API_LINKAGE_I_
#endif
#if defined(SOL_INTERNAL_FUNC_DECL_)
#define SOL_INTERNAL_FUNC_DECL_I_ SOL_INTERNAL_FUNC_DECL_
#else
#define SOL_INTERNAL_FUNC_DECL_I_ SOL_API_LINKAGE_I_
#endif
#if defined(SOL_PUBLIC_FUNC_DEF)
#define SOL_PUBLIC_FUNC_DEF_I_ SOL_PUBLIC_FUNC_DEF
#else
#define SOL_PUBLIC_FUNC_DEF_I_ SOL_API_LINKAGE_I_
#endif
#if defined(SOL_INTERNAL_FUNC_DEF)
#define SOL_INTERNAL_FUNC_DEF_I_ SOL_INTERNAL_FUNC_DEF
#else
#define SOL_INTERNAL_FUNC_DEF_I_ SOL_API_LINKAGE_I_
#endif
#if defined(SOL_FUNC_DECL)
#define SOL_FUNC_DECL_I_ SOL_FUNC_DECL
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_FUNC_DECL_I_
#elif SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
#if SOL_IS_ON(SOL_BUILD_I_)
#define SOL_FUNC_DECL_I_ extern __declspec(dllexport)
#else
#define SOL_FUNC_DECL_I_ extern __declspec(dllimport)
#endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default")))
#else
#define SOL_FUNC_DECL_I_ extern
#endif
#endif
#if defined(SOL_FUNC_DEFN)
#define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_FUNC_DEFN_I_ inline
#elif SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
#if SOL_IS_ON(SOL_BUILD_I_)
#define SOL_FUNC_DEFN_I_ __declspec(dllexport)
#else
#define SOL_FUNC_DEFN_I_ __declspec(dllimport)
#endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define SOL_FUNC_DEFN_I_ __attribute__((visibility("default")))
#else
#define SOL_FUNC_DEFN_I_
#endif
#endif
#if defined(SOL_HIDDEN_FUNC_DECL)
#define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_HIDDEN_FUNC_DECL_I_
#elif SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
#if SOL_IS_ON(SOL_BUILD_I_)
#define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport)
#else
#define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport)
#endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default")))
#else
#define SOL_HIDDEN_FUNC_DECL_I_ extern
#endif
#endif
#if defined(SOL_HIDDEN_FUNC_DEFN)
#define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN
#elif SOL_IS_ON(SOL_HEADER_ONLY_I_)
#define SOL_HIDDEN_FUNC_DEFN_I_ inline
#elif SOL_IS_ON(SOL_DLL_I_)
#if SOL_IS_ON(SOL_COMPILER_VCXX_I_)
#if SOL_IS_ON(SOL_BUILD_I_)
#define SOL_HIDDEN_FUNC_DEFN_I_
#else
#define SOL_HIDDEN_FUNC_DEFN_I_
#endif
#elif SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden")))
#else
#define SOL_HIDDEN_FUNC_DEFN_I_
#endif
#endif
// clang-format on
#endif // SOL_DETAIL_BUILD_VERSION_HPP

@ -1,77 +1,77 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_DUMP_HANDLER_HPP
#define SOL_DUMP_HANDLER_HPP
#include <sol/compatibility.hpp>
#include <cstdint>
#include <exception>
namespace sol {
class dump_error : public error {
private:
int m_ec;
public:
dump_error(int error_code_) : error("dump returned non-zero error of " + std::to_string(error_code_)), m_ec(error_code_) {
}
int error_code() const {
return m_ec;
}
};
inline int dump_pass_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) {
(void)L_;
(void)writer_function;
(void)userdata_pointer_;
(void)strip;
return result_code;
}
inline int dump_panic_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) {
(void)L_;
(void)writer_function;
(void)userdata_pointer_;
(void)strip;
return luaL_error(L_, "a non-zero error code (%d) was returned by the lua_Writer for the dump function", result_code);
}
inline int dump_throw_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) {
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
return dump_panic_on_error(L_, result_code, writer_function, userdata_pointer_, strip);
#else
(void)L_;
(void)writer_function;
(void)userdata_pointer_;
(void)strip;
throw dump_error(result_code);
#endif // no exceptions stuff
}
} // namespace sol
#endif // SOL_DUMP_HANDLER_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_DUMP_HANDLER_HPP
#define SOL_DUMP_HANDLER_HPP
#include <sol/compatibility.hpp>
#include <cstdint>
#include <exception>
namespace sol {
class dump_error : public error {
private:
int m_ec;
public:
dump_error(int error_code_) : error("dump returned non-zero error of " + std::to_string(error_code_)), m_ec(error_code_) {
}
int error_code() const {
return m_ec;
}
};
inline int dump_pass_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) {
(void)L_;
(void)writer_function;
(void)userdata_pointer_;
(void)strip;
return result_code;
}
inline int dump_panic_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) {
(void)L_;
(void)writer_function;
(void)userdata_pointer_;
(void)strip;
return luaL_error(L_, "a non-zero error code (%d) was returned by the lua_Writer for the dump function", result_code);
}
inline int dump_throw_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) {
#if SOL_IS_OFF(SOL_EXCEPTIONS_I_)
return dump_panic_on_error(L_, result_code, writer_function, userdata_pointer_, strip);
#else
(void)L_;
(void)writer_function;
(void)userdata_pointer_;
(void)strip;
throw dump_error(result_code);
#endif // no exceptions stuff
}
} // namespace sol
#endif // SOL_DUMP_HANDLER_HPP

@ -1,160 +1,160 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_EBCO_HPP
#define SOL_EBCO_HPP
#include <type_traits>
#include <utility>
namespace sol { namespace detail {
template <typename T, std::size_t tag = 0, typename = void>
struct ebco {
T m_value;
ebco() = default;
ebco(const ebco&) = default;
ebco(ebco&&) = default;
ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default;
ebco(const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : m_value(v) {};
ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : m_value(std::move(v)) {};
ebco& operator=(const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) {
m_value = v;
return *this;
}
ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) {
m_value = std::move(v);
return *this;
};
template <typename Arg, typename... Args,
typename = std::enable_if_t<
!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>>
ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>)
: m_value(std::forward<Arg>(arg), std::forward<Args>(args)...) {
}
T& value() & noexcept {
return m_value;
}
T const& value() const& noexcept {
return m_value;
}
T&& value() && noexcept {
return std::move(m_value);
}
};
template <typename T, std::size_t tag>
struct ebco<T, tag, std::enable_if_t<!std::is_reference_v<T> && std::is_class_v<T> && !std::is_final_v<T>>> : T {
ebco() = default;
ebco(const ebco&) = default;
ebco(ebco&&) = default;
ebco(const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : T(v) {};
ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : T(std::move(v)) {};
template <typename Arg, typename... Args,
typename = std::enable_if_t<
!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>>
ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>) : T(std::forward<Arg>(arg), std::forward<Args>(args)...) {
}
ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default;
ebco& operator=(const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) {
static_cast<T&>(*this) = v;
return *this;
}
ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) {
static_cast<T&>(*this) = std::move(v);
return *this;
};
T& value() & noexcept {
return static_cast<T&>(*this);
}
T const& value() const& noexcept {
return static_cast<T const&>(*this);
}
T&& value() && noexcept {
return std::move(static_cast<T&>(*this));
}
};
template <typename T, std::size_t tag>
struct ebco<T&, tag> {
private:
T* m_ref;
public:
ebco() = default;
ebco(const ebco&) = default;
ebco(ebco&&) = default;
ebco(T& v) noexcept : m_ref(std::addressof(v)) {};
ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default;
ebco& operator=(T& v) noexcept {
m_ref = std::addressof(v);
return *this;
}
T& value() const noexcept {
return *(const_cast<ebco<T&, tag>&>(*this).m_ref);
}
};
template <typename T, std::size_t tag>
struct ebco<T&&, tag> {
T&& ref;
ebco() = default;
ebco(const ebco&) = delete;
ebco(ebco&&) = default;
ebco(T&& v) noexcept : ref(v) {};
ebco& operator=(const ebco&) = delete;
ebco& operator=(ebco&&) = delete;
T& value() & noexcept {
return ref;
}
const T& value() const& noexcept {
return ref;
}
T&& value() && noexcept {
return std::move(ref);
}
};
}} // namespace sol::detail
#endif // SOL_EBCO_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_EBCO_HPP
#define SOL_EBCO_HPP
#include <type_traits>
#include <utility>
namespace sol { namespace detail {
template <typename T, std::size_t tag = 0, typename = void>
struct ebco {
T m_value;
ebco() = default;
ebco(const ebco&) = default;
ebco(ebco&&) = default;
ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default;
ebco(const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : m_value(v) {};
ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : m_value(std::move(v)) {};
ebco& operator=(const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) {
m_value = v;
return *this;
}
ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) {
m_value = std::move(v);
return *this;
};
template <typename Arg, typename... Args,
typename = std::enable_if_t<
!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>>
ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>)
: m_value(std::forward<Arg>(arg), std::forward<Args>(args)...) {
}
T& value() & noexcept {
return m_value;
}
T const& value() const& noexcept {
return m_value;
}
T&& value() && noexcept {
return std::move(m_value);
}
};
template <typename T, std::size_t tag>
struct ebco<T, tag, std::enable_if_t<!std::is_reference_v<T> && std::is_class_v<T> && !std::is_final_v<T>>> : T {
ebco() = default;
ebco(const ebco&) = default;
ebco(ebco&&) = default;
ebco(const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : T(v) {};
ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : T(std::move(v)) {};
template <typename Arg, typename... Args,
typename = std::enable_if_t<
!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>>
ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>) : T(std::forward<Arg>(arg), std::forward<Args>(args)...) {
}
ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default;
ebco& operator=(const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) {
static_cast<T&>(*this) = v;
return *this;
}
ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) {
static_cast<T&>(*this) = std::move(v);
return *this;
};
T& value() & noexcept {
return static_cast<T&>(*this);
}
T const& value() const& noexcept {
return static_cast<T const&>(*this);
}
T&& value() && noexcept {
return std::move(static_cast<T&>(*this));
}
};
template <typename T, std::size_t tag>
struct ebco<T&, tag> {
private:
T* m_ref;
public:
ebco() = default;
ebco(const ebco&) = default;
ebco(ebco&&) = default;
ebco(T& v) noexcept : m_ref(std::addressof(v)) {};
ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default;
ebco& operator=(T& v) noexcept {
m_ref = std::addressof(v);
return *this;
}
T& value() const noexcept {
return *(const_cast<ebco<T&, tag>&>(*this).m_ref);
}
};
template <typename T, std::size_t tag>
struct ebco<T&&, tag> {
T&& ref;
ebco() = default;
ebco(const ebco&) = delete;
ebco(ebco&&) = default;
ebco(T&& v) noexcept : ref(v) {};
ebco& operator=(const ebco&) = delete;
ebco& operator=(ebco&&) = delete;
T& value() & noexcept {
return ref;
}
const T& value() const& noexcept {
return ref;
}
T&& value() && noexcept {
return std::move(ref);
}
};
}} // namespace sol::detail
#endif // SOL_EBCO_HPP

@ -1,39 +1,39 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
// clang-format off
#if !defined(SOL_PROLOGUE_I_)
#error "[sol2] Library Prologue is missing from this translation unit."
#else
#undef SOL_PROLOGUE_I_
#endif
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_)
#undef _FWD
#undef _MOVE
#endif
// clang-format on
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
// clang-format off
#if !defined(SOL_PROLOGUE_I_)
#error "[sol2] Library Prologue is missing from this translation unit."
#else
#undef SOL_PROLOGUE_I_
#endif
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_)
#undef _FWD
#undef _MOVE
#endif
// clang-format on

@ -1,89 +1,89 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_ERROR_HPP
#define SOL_ERROR_HPP
#include <sol/compatibility.hpp>
#include <stdexcept>
#include <string>
#include <array>
namespace sol {
namespace detail {
struct direct_error_tag { };
const auto direct_error = direct_error_tag {};
struct error_result {
int results;
const char* format_string;
std::array<const char*, 4> argument_strings;
error_result() : results(0), format_string(nullptr) {
}
error_result(int results_) : results(results_), format_string(nullptr) {
}
error_result(const char* format_string_, const char* first_message_) : results(0), format_string(format_string_), argument_strings() {
argument_strings[0] = first_message_;
}
};
inline int handle_errors(lua_State* L, const error_result& er) {
if (er.format_string == nullptr) {
return er.results;
}
return luaL_error(L, er.format_string, er.argument_strings[0], er.argument_strings[1], er.argument_strings[2], er.argument_strings[3]);
}
} // namespace detail
class error : public std::runtime_error {
private:
// Because VC++ is upsetting, most of the time!
std::string what_reason;
public:
error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {
}
error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {
}
error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), what_reason(str) {
}
error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), what_reason(std::move(str)) {
}
error(const error& e) = default;
error(error&& e) = default;
error& operator=(const error& e) = default;
error& operator=(error&& e) = default;
virtual const char* what() const noexcept override {
return what_reason.c_str();
}
};
} // namespace sol
#endif // SOL_ERROR_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_ERROR_HPP
#define SOL_ERROR_HPP
#include <sol/compatibility.hpp>
#include <stdexcept>
#include <string>
#include <array>
namespace sol {
namespace detail {
struct direct_error_tag { };
const auto direct_error = direct_error_tag {};
struct error_result {
int results;
const char* format_string;
std::array<const char*, 4> argument_strings;
error_result() : results(0), format_string(nullptr) {
}
error_result(int results_) : results(results_), format_string(nullptr) {
}
error_result(const char* format_string_, const char* first_message_) : results(0), format_string(format_string_), argument_strings() {
argument_strings[0] = first_message_;
}
};
inline int handle_errors(lua_State* L, const error_result& er) {
if (er.format_string == nullptr) {
return er.results;
}
return luaL_error(L, er.format_string, er.argument_strings[0], er.argument_strings[1], er.argument_strings[2], er.argument_strings[3]);
}
} // namespace detail
class error : public std::runtime_error {
private:
// Because VC++ is upsetting, most of the time!
std::string what_reason;
public:
error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {
}
error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {
}
error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), what_reason(str) {
}
error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), what_reason(std::move(str)) {
}
error(const error& e) = default;
error(error&& e) = default;
error& operator=(const error& e) = default;
error& operator=(error&& e) = default;
virtual const char* what() const noexcept override {
return what_reason.c_str();
}
};
} // namespace sol
#endif // SOL_ERROR_HPP

@ -1,142 +1,142 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_FUNCTION_HPP
#define SOL_FUNCTION_HPP
#include <sol/stack.hpp>
#include <sol/unsafe_function.hpp>
#include <sol/protected_function.hpp>
#include <sol/bytecode.hpp>
#include <functional>
namespace sol {
template <typename... Ret, typename... Args>
decltype(auto) stack_proxy::call(Args&&... args) {
stack_function sf(this->lua_state(), this->stack_index());
return sf.template call<Ret...>(std::forward<Args>(args)...);
}
inline protected_function_result::protected_function_result(unsafe_function_result&& o) noexcept
: L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()), popcount(o.return_count()), err(o.status()) {
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
}
inline protected_function_result& protected_function_result::operator=(unsafe_function_result&& o) noexcept {
L = o.lua_state();
index = o.stack_index();
returncount = o.return_count();
popcount = o.return_count();
err = o.status();
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
return *this;
}
inline unsafe_function_result::unsafe_function_result(protected_function_result&& o) noexcept
: L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) {
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
}
inline unsafe_function_result& unsafe_function_result::operator=(protected_function_result&& o) noexcept {
L = o.lua_state();
index = o.stack_index();
returncount = o.return_count();
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
return *this;
}
namespace detail {
template <typename... R>
struct std_shim {
unsafe_function lua_func_;
std_shim(unsafe_function lua_func) : lua_func_(std::move(lua_func)) {
}
template <typename... Args>
meta::return_type_t<R...> operator()(Args&&... args) {
return lua_func_.call<R...>(std::forward<Args>(args)...);
}
};
template <>
struct std_shim<void> {
unsafe_function lua_func_;
std_shim(unsafe_function lua_func) : lua_func_(std::move(lua_func)) {
}
template <typename... Args>
void operator()(Args&&... args) {
lua_func_.call<void>(std::forward<Args>(args)...);
}
};
} // namespace detail
namespace stack {
template <typename Signature>
struct unqualified_getter<std::function<Signature>> {
typedef meta::bind_traits<Signature> fx_t;
typedef typename fx_t::args_list args_lists;
typedef meta::tuple_types<typename fx_t::return_type> return_types;
template <typename... R>
static std::function<Signature> get_std_func(types<R...>, lua_State* L, int index) {
detail::std_shim<R...> fx(unsafe_function(L, index));
return fx;
}
static std::function<Signature> get(lua_State* L, int index, record& tracking) {
tracking.use(1);
type t = type_of(L, index);
if (t == type::none || t == type::lua_nil) {
return nullptr;
}
return get_std_func(return_types(), L, index);
}
};
template <typename Allocator>
struct unqualified_getter<basic_bytecode<Allocator>> {
static basic_bytecode<Allocator> get(lua_State* L, int index, record& tracking) {
tracking.use(1);
stack_function sf(L, index);
return sf.dump(&dump_panic_on_error);
}
};
} // namespace stack
} // namespace sol
#endif // SOL_FUNCTION_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_FUNCTION_HPP
#define SOL_FUNCTION_HPP
#include <sol/stack.hpp>
#include <sol/unsafe_function.hpp>
#include <sol/protected_function.hpp>
#include <sol/bytecode.hpp>
#include <functional>
namespace sol {
template <typename... Ret, typename... Args>
decltype(auto) stack_proxy::call(Args&&... args) {
stack_function sf(this->lua_state(), this->stack_index());
return sf.template call<Ret...>(std::forward<Args>(args)...);
}
inline protected_function_result::protected_function_result(unsafe_function_result&& o) noexcept
: L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()), popcount(o.return_count()), err(o.status()) {
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
}
inline protected_function_result& protected_function_result::operator=(unsafe_function_result&& o) noexcept {
L = o.lua_state();
index = o.stack_index();
returncount = o.return_count();
popcount = o.return_count();
err = o.status();
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
return *this;
}
inline unsafe_function_result::unsafe_function_result(protected_function_result&& o) noexcept
: L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) {
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
}
inline unsafe_function_result& unsafe_function_result::operator=(protected_function_result&& o) noexcept {
L = o.lua_state();
index = o.stack_index();
returncount = o.return_count();
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
return *this;
}
namespace detail {
template <typename... R>
struct std_shim {
unsafe_function lua_func_;
std_shim(unsafe_function lua_func) : lua_func_(std::move(lua_func)) {
}
template <typename... Args>
meta::return_type_t<R...> operator()(Args&&... args) {
return lua_func_.call<R...>(std::forward<Args>(args)...);
}
};
template <>
struct std_shim<void> {
unsafe_function lua_func_;
std_shim(unsafe_function lua_func) : lua_func_(std::move(lua_func)) {
}
template <typename... Args>
void operator()(Args&&... args) {
lua_func_.call<void>(std::forward<Args>(args)...);
}
};
} // namespace detail
namespace stack {
template <typename Signature>
struct unqualified_getter<std::function<Signature>> {
typedef meta::bind_traits<Signature> fx_t;
typedef typename fx_t::args_list args_lists;
typedef meta::tuple_types<typename fx_t::return_type> return_types;
template <typename... R>
static std::function<Signature> get_std_func(types<R...>, lua_State* L, int index) {
detail::std_shim<R...> fx(unsafe_function(L, index));
return fx;
}
static std::function<Signature> get(lua_State* L, int index, record& tracking) {
tracking.use(1);
type t = type_of(L, index);
if (t == type::none || t == type::lua_nil) {
return nullptr;
}
return get_std_func(return_types(), L, index);
}
};
template <typename Allocator>
struct unqualified_getter<basic_bytecode<Allocator>> {
static basic_bytecode<Allocator> get(lua_State* L, int index, record& tracking) {
tracking.use(1);
stack_function sf(L, index);
return sf.dump(&dump_panic_on_error);
}
};
} // namespace stack
} // namespace sol
#endif // SOL_FUNCTION_HPP

@ -1,195 +1,195 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_INHERITANCE_HPP
#define SOL_INHERITANCE_HPP
#include <sol/types.hpp>
#include <sol/usertype_traits.hpp>
#include <sol/unique_usertype_traits.hpp>
namespace sol {
template <typename... Args>
struct base_list { };
template <typename... Args>
using bases = base_list<Args...>;
typedef bases<> base_classes_tag;
const auto base_classes = base_classes_tag();
template <typename... Args>
struct is_to_stringable<base_list<Args...>> : std::false_type { };
namespace detail {
inline decltype(auto) base_class_check_key() {
static const auto& key = "class_check";
return key;
}
inline decltype(auto) base_class_cast_key() {
static const auto& key = "class_cast";
return key;
}
inline decltype(auto) base_class_index_propogation_key() {
static const auto& key = u8"\xF0\x9F\x8C\xB2.index";
return key;
}
inline decltype(auto) base_class_new_index_propogation_key() {
static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index";
return key;
}
template <typename T>
struct inheritance {
typedef typename base<T>::type bases_t;
static bool type_check_bases(types<>, const string_view&) {
return false;
}
template <typename Base, typename... Args>
static bool type_check_bases(types<Base, Args...>, const string_view& ti) {
return ti == usertype_traits<Base>::qualified_name() || type_check_bases(types<Args...>(), ti);
}
static bool type_check(const string_view& ti) {
return ti == usertype_traits<T>::qualified_name() || type_check_bases(bases_t(), ti);
}
template <typename... Bases>
static bool type_check_with(const string_view& ti) {
return ti == usertype_traits<T>::qualified_name() || type_check_bases(types<Bases...>(), ti);
}
static void* type_cast_bases(types<>, T*, const string_view&) {
return nullptr;
}
template <typename Base, typename... Args>
static void* type_cast_bases(types<Base, Args...>, T* data, const string_view& ti) {
// Make sure to convert to T first, and then dynamic cast to the proper type
return ti != usertype_traits<Base>::qualified_name() ? type_cast_bases(types<Args...>(), data, ti)
: static_cast<void*>(static_cast<Base*>(data));
}
static void* type_cast(void* voiddata, const string_view& ti) {
T* data = static_cast<T*>(voiddata);
return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(bases_t(), data, ti) : data);
}
template <typename... Bases>
static void* type_cast_with(void* voiddata, const string_view& ti) {
T* data = static_cast<T*>(voiddata);
return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(types<Bases...>(), data, ti) : data);
}
template <typename U>
static bool type_unique_cast_bases(types<>, void*, void*, const string_view&) {
return 0;
}
template <typename U, typename Base, typename... Args>
static int type_unique_cast_bases(types<Base, Args...>, void* source_data, void* target_data, const string_view& ti) {
using uu_traits = unique_usertype_traits<U>;
using base_ptr = typename uu_traits::template rebind_actual_type<Base>;
string_view base_ti = usertype_traits<Base>::qualified_name();
if (base_ti == ti) {
if (target_data != nullptr) {
U* source = static_cast<U*>(source_data);
base_ptr* target = static_cast<base_ptr*>(target_data);
// perform proper derived -> base conversion
*target = *source;
}
return 2;
}
return type_unique_cast_bases<U>(types<Args...>(), source_data, target_data, ti);
}
template <typename U>
static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
if constexpr (is_actual_type_rebindable_for_v<U>) {
using rebound_actual_type = unique_usertype_rebind_actual_t<U>;
using maybe_bases_or_empty = meta::conditional_t<std::is_void_v<rebound_actual_type>, types<>, bases_t>;
string_view this_rebind_ti = usertype_traits<rebound_actual_type>::qualified_name();
if (rebind_ti != this_rebind_ti) {
// this is not even of the same unique type
return 0;
}
string_view this_ti = usertype_traits<T>::qualified_name();
if (ti == this_ti) {
// direct match, return 1
return 1;
}
return type_unique_cast_bases<U>(maybe_bases_or_empty(), source_data, target_data, ti);
}
else {
(void)rebind_ti;
string_view this_ti = usertype_traits<T>::qualified_name();
if (ti == this_ti) {
// direct match, return 1
return 1;
}
return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
}
}
template <typename U, typename... Bases>
static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
using uc_bases_t = types<Bases...>;
if constexpr (is_actual_type_rebindable_for_v<U>) {
using rebound_actual_type = unique_usertype_rebind_actual_t<U>;
using cond_bases_t = meta::conditional_t<std::is_void_v<rebound_actual_type>, types<>, uc_bases_t>;
string_view this_rebind_ti = usertype_traits<rebound_actual_type>::qualified_name();
if (rebind_ti != this_rebind_ti) {
// this is not even of the same unique type
return 0;
}
string_view this_ti = usertype_traits<T>::qualified_name();
if (ti == this_ti) {
// direct match, return 1
return 1;
}
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
}
else {
(void)rebind_ti;
string_view this_ti = usertype_traits<T>::qualified_name();
if (ti == this_ti) {
// direct match, return 1
return 1;
}
return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
}
}
};
using inheritance_check_function = decltype(&inheritance<void>::type_check);
using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
using inheritance_unique_cast_function = decltype(&inheritance<void>::type_unique_cast<void>);
} // namespace detail
} // namespace sol
#endif // SOL_INHERITANCE_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_INHERITANCE_HPP
#define SOL_INHERITANCE_HPP
#include <sol/types.hpp>
#include <sol/usertype_traits.hpp>
#include <sol/unique_usertype_traits.hpp>
namespace sol {
template <typename... Args>
struct base_list { };
template <typename... Args>
using bases = base_list<Args...>;
typedef bases<> base_classes_tag;
const auto base_classes = base_classes_tag();
template <typename... Args>
struct is_to_stringable<base_list<Args...>> : std::false_type { };
namespace detail {
inline decltype(auto) base_class_check_key() {
static const auto& key = "class_check";
return key;
}
inline decltype(auto) base_class_cast_key() {
static const auto& key = "class_cast";
return key;
}
inline decltype(auto) base_class_index_propogation_key() {
static const auto& key = u8"\xF0\x9F\x8C\xB2.index";
return key;
}
inline decltype(auto) base_class_new_index_propogation_key() {
static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index";
return key;
}
template <typename T>
struct inheritance {
typedef typename base<T>::type bases_t;
static bool type_check_bases(types<>, const string_view&) {
return false;
}
template <typename Base, typename... Args>
static bool type_check_bases(types<Base, Args...>, const string_view& ti) {
return ti == usertype_traits<Base>::qualified_name() || type_check_bases(types<Args...>(), ti);
}
static bool type_check(const string_view& ti) {
return ti == usertype_traits<T>::qualified_name() || type_check_bases(bases_t(), ti);
}
template <typename... Bases>
static bool type_check_with(const string_view& ti) {
return ti == usertype_traits<T>::qualified_name() || type_check_bases(types<Bases...>(), ti);
}
static void* type_cast_bases(types<>, T*, const string_view&) {
return nullptr;
}
template <typename Base, typename... Args>
static void* type_cast_bases(types<Base, Args...>, T* data, const string_view& ti) {
// Make sure to convert to T first, and then dynamic cast to the proper type
return ti != usertype_traits<Base>::qualified_name() ? type_cast_bases(types<Args...>(), data, ti)
: static_cast<void*>(static_cast<Base*>(data));
}
static void* type_cast(void* voiddata, const string_view& ti) {
T* data = static_cast<T*>(voiddata);
return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(bases_t(), data, ti) : data);
}
template <typename... Bases>
static void* type_cast_with(void* voiddata, const string_view& ti) {
T* data = static_cast<T*>(voiddata);
return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(types<Bases...>(), data, ti) : data);
}
template <typename U>
static bool type_unique_cast_bases(types<>, void*, void*, const string_view&) {
return 0;
}
template <typename U, typename Base, typename... Args>
static int type_unique_cast_bases(types<Base, Args...>, void* source_data, void* target_data, const string_view& ti) {
using uu_traits = unique_usertype_traits<U>;
using base_ptr = typename uu_traits::template rebind_actual_type<Base>;
string_view base_ti = usertype_traits<Base>::qualified_name();
if (base_ti == ti) {
if (target_data != nullptr) {
U* source = static_cast<U*>(source_data);
base_ptr* target = static_cast<base_ptr*>(target_data);
// perform proper derived -> base conversion
*target = *source;
}
return 2;
}
return type_unique_cast_bases<U>(types<Args...>(), source_data, target_data, ti);
}
template <typename U>
static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
if constexpr (is_actual_type_rebindable_for_v<U>) {
using rebound_actual_type = unique_usertype_rebind_actual_t<U>;
using maybe_bases_or_empty = meta::conditional_t<std::is_void_v<rebound_actual_type>, types<>, bases_t>;
string_view this_rebind_ti = usertype_traits<rebound_actual_type>::qualified_name();
if (rebind_ti != this_rebind_ti) {
// this is not even of the same unique type
return 0;
}
string_view this_ti = usertype_traits<T>::qualified_name();
if (ti == this_ti) {
// direct match, return 1
return 1;
}
return type_unique_cast_bases<U>(maybe_bases_or_empty(), source_data, target_data, ti);
}
else {
(void)rebind_ti;
string_view this_ti = usertype_traits<T>::qualified_name();
if (ti == this_ti) {
// direct match, return 1
return 1;
}
return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
}
}
template <typename U, typename... Bases>
static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) {
using uc_bases_t = types<Bases...>;
if constexpr (is_actual_type_rebindable_for_v<U>) {
using rebound_actual_type = unique_usertype_rebind_actual_t<U>;
using cond_bases_t = meta::conditional_t<std::is_void_v<rebound_actual_type>, types<>, uc_bases_t>;
string_view this_rebind_ti = usertype_traits<rebound_actual_type>::qualified_name();
if (rebind_ti != this_rebind_ti) {
// this is not even of the same unique type
return 0;
}
string_view this_ti = usertype_traits<T>::qualified_name();
if (ti == this_ti) {
// direct match, return 1
return 1;
}
return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
}
else {
(void)rebind_ti;
string_view this_ti = usertype_traits<T>::qualified_name();
if (ti == this_ti) {
// direct match, return 1
return 1;
}
return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti);
}
}
};
using inheritance_check_function = decltype(&inheritance<void>::type_check);
using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
using inheritance_unique_cast_function = decltype(&inheritance<void>::type_unique_cast<void>);
} // namespace detail
} // namespace sol
#endif // SOL_INHERITANCE_HPP

@ -1,95 +1,95 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_LUA_TABLE_HPP
#define SOL_LUA_TABLE_HPP
#include <sol/table_core.hpp>
namespace sol {
template <typename ref_t>
struct basic_lua_table : basic_table_core<false, ref_t> {
private:
using base_t = basic_table_core<false, ref_t>;
friend class state;
friend class state_view;
public:
using base_t::lua_state;
basic_lua_table() noexcept = default;
basic_lua_table(const basic_lua_table&) = default;
basic_lua_table(basic_lua_table&&) = default;
basic_lua_table& operator=(const basic_lua_table&) = default;
basic_lua_table& operator=(basic_lua_table&&) = default;
basic_lua_table(const stack_reference& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
}
basic_lua_table(stack_reference&& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
}
template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_lua_table>(lua_state(), -1, handler);
#endif // Safety
}
basic_lua_table(lua_State* L, const new_table& nt) : base_t(L, nt) {
if (!is_stack_based<meta::unqualified_t<ref_t>>::value) {
lua_pop(L, 1);
}
}
basic_lua_table(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
constructor_handler handler {};
stack::check<basic_lua_table>(L, index, handler);
#endif // Safety
}
basic_lua_table(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_lua_table>(lua_state(), -1, handler);
#endif // Safety
}
template <typename T,
meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_lua_table>>, meta::neg<std::is_same<ref_t, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(T&& r) noexcept : basic_lua_table(detail::no_safety, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
if (!is_table<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_lua_table>(lua_state(), -1, handler);
}
#endif // Safety
}
basic_lua_table(lua_nil_t r) noexcept : basic_lua_table(detail::no_safety, r) {
}
};
} // namespace sol
#endif // SOL_LUA_TABLE_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_LUA_TABLE_HPP
#define SOL_LUA_TABLE_HPP
#include <sol/table_core.hpp>
namespace sol {
template <typename ref_t>
struct basic_lua_table : basic_table_core<false, ref_t> {
private:
using base_t = basic_table_core<false, ref_t>;
friend class state;
friend class state_view;
public:
using base_t::lua_state;
basic_lua_table() noexcept = default;
basic_lua_table(const basic_lua_table&) = default;
basic_lua_table(basic_lua_table&&) = default;
basic_lua_table& operator=(const basic_lua_table&) = default;
basic_lua_table& operator=(basic_lua_table&&) = default;
basic_lua_table(const stack_reference& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
}
basic_lua_table(stack_reference&& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
}
template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_lua_table>(lua_state(), -1, handler);
#endif // Safety
}
basic_lua_table(lua_State* L, const new_table& nt) : base_t(L, nt) {
if (!is_stack_based<meta::unqualified_t<ref_t>>::value) {
lua_pop(L, 1);
}
}
basic_lua_table(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
constructor_handler handler {};
stack::check<basic_lua_table>(L, index, handler);
#endif // Safety
}
basic_lua_table(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_lua_table>(lua_state(), -1, handler);
#endif // Safety
}
template <typename T,
meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_lua_table>>, meta::neg<std::is_same<ref_t, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(T&& r) noexcept : basic_lua_table(detail::no_safety, std::forward<T>(r)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
if (!is_table<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_lua_table>(lua_state(), -1, handler);
}
#endif // Safety
}
basic_lua_table(lua_nil_t r) noexcept : basic_lua_table(detail::no_safety, r) {
}
};
} // namespace sol
#endif // SOL_LUA_TABLE_HPP

@ -1,162 +1,162 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_LUA_VALUE_HPP
#define SOL_LUA_VALUE_HPP
#include <sol/stack.hpp>
#include <sol/reference.hpp>
#include <sol/make_reference.hpp>
namespace sol {
struct lua_value {
public:
struct arr : detail::ebco<std::initializer_list<lua_value>> {
private:
using base_t = detail::ebco<std::initializer_list<lua_value>>;
public:
using base_t::base_t;
};
private:
template <typename T>
using is_reference_or_lua_value_init_list
= meta::any<meta::is_specialization_of<T, std::initializer_list>, std::is_same<T, reference>, std::is_same<T, arr>>;
template <typename T>
using is_lua_value_single_constructible = meta::any<std::is_same<T, lua_value>, is_reference_or_lua_value_init_list<T>>;
static lua_State*& thread_local_lua_state() {
#if SOL_IS_ON(SOL_USE_THREAD_LOCAL_I_)
static thread_local lua_State* L = nullptr;
#else
static lua_State* L = nullptr;
#endif
return L;
}
reference ref_value;
public:
static void set_lua_state(lua_State* L) {
thread_local_lua_state() = L;
}
template <typename T, meta::disable<is_reference_or_lua_value_init_list<meta::unqualified_t<T>>> = meta::enabler>
lua_value(lua_State* L_, T&& value) : lua_value(((set_lua_state(L_)), std::forward<T>(value))) {
}
template <typename T, meta::disable<is_lua_value_single_constructible<meta::unqualified_t<T>>> = meta::enabler>
lua_value(T&& value) : ref_value(make_reference(thread_local_lua_state(), std::forward<T>(value))) {
}
lua_value(lua_State* L_, std::initializer_list<std::pair<lua_value, lua_value>> il)
: lua_value([&L_, &il]() {
set_lua_state(L_);
return std::move(il);
}()) {
}
lua_value(std::initializer_list<std::pair<lua_value, lua_value>> il) : ref_value(make_reference(thread_local_lua_state(), std::move(il))) {
}
lua_value(lua_State* L_, arr il)
: lua_value([&L_, &il]() {
set_lua_state(L_);
return std::move(il);
}()) {
}
lua_value(arr il) : ref_value(make_reference(thread_local_lua_state(), std::move(il.value()))) {
}
lua_value(lua_State* L_, reference r)
: lua_value([&L_, &r]() {
set_lua_state(L_);
return std::move(r);
}()) {
}
lua_value(reference r) : ref_value(std::move(r)) {
}
lua_value(const lua_value&) noexcept = default;
lua_value(lua_value&&) = default;
lua_value& operator=(const lua_value&) = default;
lua_value& operator=(lua_value&&) = default;
const reference& value() const& {
return ref_value;
}
reference& value() & {
return ref_value;
}
reference&& value() && {
return std::move(ref_value);
}
template <typename T>
decltype(auto) as() const {
ref_value.push();
return stack::pop<T>(ref_value.lua_state());
}
template <typename T>
bool is() const {
int r = ref_value.registry_index();
if (r == LUA_REFNIL)
return meta::any_same<meta::unqualified_t<T>, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false;
if (r == LUA_NOREF)
return false;
auto pp = stack::push_pop(ref_value);
return stack::check<T>(ref_value.lua_state(), -1, &no_panic);
}
};
using array_value = typename lua_value::arr;
namespace stack {
template <>
struct unqualified_pusher<lua_value> {
static int push(lua_State* L, const lua_value& lv) {
return stack::push(L, lv.value());
}
static int push(lua_State* L, lua_value&& lv) {
return stack::push(L, std::move(lv).value());
}
};
template <>
struct unqualified_getter<lua_value> {
static lua_value get(lua_State* L, int index, record& tracking) {
return lua_value(L, stack::get<reference>(L, index, tracking));
}
};
} // namespace stack
} // namespace sol
#endif // SOL_LUA_VALUE_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_LUA_VALUE_HPP
#define SOL_LUA_VALUE_HPP
#include <sol/stack.hpp>
#include <sol/reference.hpp>
#include <sol/make_reference.hpp>
namespace sol {
struct lua_value {
public:
struct arr : detail::ebco<std::initializer_list<lua_value>> {
private:
using base_t = detail::ebco<std::initializer_list<lua_value>>;
public:
using base_t::base_t;
};
private:
template <typename T>
using is_reference_or_lua_value_init_list
= meta::any<meta::is_specialization_of<T, std::initializer_list>, std::is_same<T, reference>, std::is_same<T, arr>>;
template <typename T>
using is_lua_value_single_constructible = meta::any<std::is_same<T, lua_value>, is_reference_or_lua_value_init_list<T>>;
static lua_State*& thread_local_lua_state() {
#if SOL_IS_ON(SOL_USE_THREAD_LOCAL_I_)
static thread_local lua_State* L = nullptr;
#else
static lua_State* L = nullptr;
#endif
return L;
}
reference ref_value;
public:
static void set_lua_state(lua_State* L) {
thread_local_lua_state() = L;
}
template <typename T, meta::disable<is_reference_or_lua_value_init_list<meta::unqualified_t<T>>> = meta::enabler>
lua_value(lua_State* L_, T&& value) : lua_value(((set_lua_state(L_)), std::forward<T>(value))) {
}
template <typename T, meta::disable<is_lua_value_single_constructible<meta::unqualified_t<T>>> = meta::enabler>
lua_value(T&& value) : ref_value(make_reference(thread_local_lua_state(), std::forward<T>(value))) {
}
lua_value(lua_State* L_, std::initializer_list<std::pair<lua_value, lua_value>> il)
: lua_value([&L_, &il]() {
set_lua_state(L_);
return std::move(il);
}()) {
}
lua_value(std::initializer_list<std::pair<lua_value, lua_value>> il) : ref_value(make_reference(thread_local_lua_state(), std::move(il))) {
}
lua_value(lua_State* L_, arr il)
: lua_value([&L_, &il]() {
set_lua_state(L_);
return std::move(il);
}()) {
}
lua_value(arr il) : ref_value(make_reference(thread_local_lua_state(), std::move(il.value()))) {
}
lua_value(lua_State* L_, reference r)
: lua_value([&L_, &r]() {
set_lua_state(L_);
return std::move(r);
}()) {
}
lua_value(reference r) : ref_value(std::move(r)) {
}
lua_value(const lua_value&) noexcept = default;
lua_value(lua_value&&) = default;
lua_value& operator=(const lua_value&) = default;
lua_value& operator=(lua_value&&) = default;
const reference& value() const& {
return ref_value;
}
reference& value() & {
return ref_value;
}
reference&& value() && {
return std::move(ref_value);
}
template <typename T>
decltype(auto) as() const {
ref_value.push();
return stack::pop<T>(ref_value.lua_state());
}
template <typename T>
bool is() const {
int r = ref_value.registry_index();
if (r == LUA_REFNIL)
return meta::any_same<meta::unqualified_t<T>, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false;
if (r == LUA_NOREF)
return false;
auto pp = stack::push_pop(ref_value);
return stack::check<T>(ref_value.lua_state(), -1, &no_panic);
}
};
using array_value = typename lua_value::arr;
namespace stack {
template <>
struct unqualified_pusher<lua_value> {
static int push(lua_State* L, const lua_value& lv) {
return stack::push(L, lv.value());
}
static int push(lua_State* L, lua_value&& lv) {
return stack::push(L, std::move(lv).value());
}
};
template <>
struct unqualified_getter<lua_value> {
static lua_value get(lua_State* L, int index, record& tracking) {
return lua_value(L, stack::get<reference>(L, index, tracking));
}
};
} // namespace stack
} // namespace sol
#endif // SOL_LUA_VALUE_HPP

@ -1,262 +1,262 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_PACKAGED_COROUTINE_HPP
#define SOL_PACKAGED_COROUTINE_HPP
#include <sol/reference.hpp>
#include <sol/object.hpp>
#include <sol/stack.hpp>
#include <sol/function_result.hpp>
#include <sol/thread.hpp>
#include <sol/protected_handler.hpp>
#include <sol/coroutine.hpp>
namespace sol {
#if 0
class packaged_coroutine {
private:
lua_State* m_L;
sol::stateless_reference m_coroutine_reference;
sol::stateless_reference m_error_handler;
sol::thread m_thread_reference;
void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) {
#if SOL_LUA_VERSION_I_ >= 504
int nresults;
stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount), &nresults));
#else
stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount)));
#endif
}
template <std::size_t... I, typename... Ret>
auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) {
luacall(n, sizeof...(Ret));
return stack::pop<std::tuple<Ret...>>(lua_state());
}
template <std::size_t I, typename Ret>
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) {
luacall(n, 1);
return stack::pop<Ret>(lua_state());
}
template <std::size_t I>
void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) {
luacall(n, 0);
}
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) {
int firstreturn = 1;
luacall(n, LUA_MULTRET);
int poststacksize = lua_gettop(this->lua_state());
int returncount = poststacksize - (firstreturn - 1);
if (error()) {
if (m_error_handler.valid()) {
string_view err = stack::get<string_view>(this->lua_state(), poststacksize);
m_error_handler.push();
stack::push(this->lua_state(), err);
lua_call(lua_state(), 1, 1);
}
return protected_function_result(this->lua_state(), lua_absindex(this->lua_state(), -1), 1, returncount, status());
}
return protected_function_result(this->lua_state(), firstreturn, returncount, returncount, status());
}
public:
using base_t::lua_state;
basic_packaged_coroutine() = default;
template <typename T,
meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_packaged_coroutine>>,
meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_packaged_coroutine(T&& r) noexcept
: base_t(std::forward<T>(r)), m_error_handler(detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
if (!is_function<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(lua_state(), -1, handler);
}
#endif // Safety
}
basic_packaged_coroutine(const basic_packaged_coroutine& other) = default;
basic_packaged_coroutine& operator=(const basic_packaged_coroutine&) = default;
basic_packaged_coroutine(basic_packaged_coroutine&& other) noexcept
: base_t(std::move(other)), m_error_handler(this->lua_state(), std::move(other.m_error_handler)) {
}
basic_packaged_coroutine& operator=(basic_packaged_coroutine&& other) noexcept {
base_t::operator=(std::move(other));
// must change the state, since it could change on the coroutine type
m_error_handler.abandon();
m_error_handler = handler_t(this->lua_state(), std::move(other.m_error_handler));
return *this;
}
basic_packaged_coroutine(const basic_function<base_t>& b) noexcept
: basic_packaged_coroutine(b, detail::get_default_handler<reference, is_main_threaded_v<base_t>>(b.lua_state())) {
}
basic_packaged_coroutine(basic_function<base_t>&& b) noexcept
: basic_packaged_coroutine(std::move(b), detail::get_default_handler<reference, is_main_threaded_v<base_t>>(b.lua_state())) {
}
basic_packaged_coroutine(const basic_function<base_t>& b, handler_t eh) noexcept : base_t(b), m_error_handler(std::move(eh)) {
}
basic_packaged_coroutine(basic_function<base_t>&& b, handler_t eh) noexcept : base_t(std::move(b)), m_error_handler(std::move(eh)) {
}
basic_packaged_coroutine(const stack_reference& r) noexcept
: basic_packaged_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
}
basic_packaged_coroutine(stack_reference&& r) noexcept
: basic_packaged_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
}
basic_packaged_coroutine(const stack_reference& r, handler_t eh) noexcept : basic_packaged_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) {
}
basic_packaged_coroutine(stack_reference&& r, handler_t eh) noexcept : basic_packaged_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) {
}
template <typename Super>
basic_packaged_coroutine(const proxy_base<Super>& p)
: basic_packaged_coroutine(p, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) {
}
template <typename Super>
basic_packaged_coroutine(proxy_base<Super>&& p)
: basic_packaged_coroutine(std::move(p), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) {
}
template <typename Proxy, typename HandlerReference,
meta::enable<std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>, meta::neg<is_lua_index<meta::unqualified_t<HandlerReference>>>> = meta::enabler>
basic_packaged_coroutine(Proxy&& p, HandlerReference&& eh) : basic_packaged_coroutine(detail::force_cast<base_t>(p), std::forward<HandlerReference>(eh)) {
}
template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_packaged_coroutine(lua_State* L, T&& r) noexcept
: basic_packaged_coroutine(L, std::forward<T>(r), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_packaged_coroutine(lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward<T>(r)), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(lua_state(), -1, handler);
#endif // Safety
}
basic_packaged_coroutine(lua_nil_t n) : base_t(n), m_error_handler(n) {
}
basic_packaged_coroutine(lua_State* L, int index = -1)
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
basic_packaged_coroutine(lua_State* L, int index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#ifdef SOL_SAFE_REFERENCES
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(L, index, handler);
#endif // Safety
}
basic_packaged_coroutine(lua_State* L, absolute_index index)
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
basic_packaged_coroutine(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(L, index, handler);
#endif // Safety
}
basic_packaged_coroutine(lua_State* L, raw_index index)
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
basic_packaged_coroutine(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(L, index, handler);
#endif // Safety
}
basic_packaged_coroutine(lua_State* L, ref_index index)
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
basic_packaged_coroutine(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(lua_state(), -1, handler);
#endif // Safety
}
call_status status() const noexcept {
return stats;
}
bool error() const noexcept {
call_status cs = status();
return cs != call_status::ok && cs != call_status::yielded;
}
bool runnable() const noexcept {
return base_t::valid() && (status() == call_status::yielded);
}
reference error_handler() const noexcept {
return reference(m_L, registry_index(m_error_handler.index));
}
set_error_handler(reference new_error_handler) noexcept {
this->m_error_handler = stateless_reference(this->m_L, std::move(new_error_handler));
}
explicit operator bool() const noexcept {
return runnable();
}
template <typename... Args>
protected_function_result operator()(Args&&... args) {
return call<>(std::forward<Args>(args)...);
}
template <typename... Ret, typename... Args>
decltype(auto) operator()(types<Ret...>, Args&&... args) {
return call<Ret...>(std::forward<Args>(args)...);
}
template <typename... Ret, typename... Args>
decltype(auto) call(Args&&... args) {
// some users screw up coroutine.create
// and try to use it with sol::coroutine without ever calling the first resume in Lua
// this makes the stack incompatible with other kinds of stacks: protect against this
// make sure coroutines don't screw us over
base_t::push();
int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount);
}
};
#endif
} // namespace sol
#endif // SOL_PACKAGED_COROUTINE_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_PACKAGED_COROUTINE_HPP
#define SOL_PACKAGED_COROUTINE_HPP
#include <sol/reference.hpp>
#include <sol/object.hpp>
#include <sol/stack.hpp>
#include <sol/function_result.hpp>
#include <sol/thread.hpp>
#include <sol/protected_handler.hpp>
#include <sol/coroutine.hpp>
namespace sol {
#if 0
class packaged_coroutine {
private:
lua_State* m_L;
sol::stateless_reference m_coroutine_reference;
sol::stateless_reference m_error_handler;
sol::thread m_thread_reference;
void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) {
#if SOL_LUA_VERSION_I_ >= 504
int nresults;
stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount), &nresults));
#else
stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount)));
#endif
}
template <std::size_t... I, typename... Ret>
auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) {
luacall(n, sizeof...(Ret));
return stack::pop<std::tuple<Ret...>>(lua_state());
}
template <std::size_t I, typename Ret>
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) {
luacall(n, 1);
return stack::pop<Ret>(lua_state());
}
template <std::size_t I>
void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) {
luacall(n, 0);
}
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) {
int firstreturn = 1;
luacall(n, LUA_MULTRET);
int poststacksize = lua_gettop(this->lua_state());
int returncount = poststacksize - (firstreturn - 1);
if (error()) {
if (m_error_handler.valid()) {
string_view err = stack::get<string_view>(this->lua_state(), poststacksize);
m_error_handler.push();
stack::push(this->lua_state(), err);
lua_call(lua_state(), 1, 1);
}
return protected_function_result(this->lua_state(), lua_absindex(this->lua_state(), -1), 1, returncount, status());
}
return protected_function_result(this->lua_state(), firstreturn, returncount, returncount, status());
}
public:
using base_t::lua_state;
basic_packaged_coroutine() = default;
template <typename T,
meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_packaged_coroutine>>,
meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_packaged_coroutine(T&& r) noexcept
: base_t(std::forward<T>(r)), m_error_handler(detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
if (!is_function<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(lua_state(), -1, handler);
}
#endif // Safety
}
basic_packaged_coroutine(const basic_packaged_coroutine& other) = default;
basic_packaged_coroutine& operator=(const basic_packaged_coroutine&) = default;
basic_packaged_coroutine(basic_packaged_coroutine&& other) noexcept
: base_t(std::move(other)), m_error_handler(this->lua_state(), std::move(other.m_error_handler)) {
}
basic_packaged_coroutine& operator=(basic_packaged_coroutine&& other) noexcept {
base_t::operator=(std::move(other));
// must change the state, since it could change on the coroutine type
m_error_handler.abandon();
m_error_handler = handler_t(this->lua_state(), std::move(other.m_error_handler));
return *this;
}
basic_packaged_coroutine(const basic_function<base_t>& b) noexcept
: basic_packaged_coroutine(b, detail::get_default_handler<reference, is_main_threaded_v<base_t>>(b.lua_state())) {
}
basic_packaged_coroutine(basic_function<base_t>&& b) noexcept
: basic_packaged_coroutine(std::move(b), detail::get_default_handler<reference, is_main_threaded_v<base_t>>(b.lua_state())) {
}
basic_packaged_coroutine(const basic_function<base_t>& b, handler_t eh) noexcept : base_t(b), m_error_handler(std::move(eh)) {
}
basic_packaged_coroutine(basic_function<base_t>&& b, handler_t eh) noexcept : base_t(std::move(b)), m_error_handler(std::move(eh)) {
}
basic_packaged_coroutine(const stack_reference& r) noexcept
: basic_packaged_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
}
basic_packaged_coroutine(stack_reference&& r) noexcept
: basic_packaged_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
}
basic_packaged_coroutine(const stack_reference& r, handler_t eh) noexcept : basic_packaged_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) {
}
basic_packaged_coroutine(stack_reference&& r, handler_t eh) noexcept : basic_packaged_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) {
}
template <typename Super>
basic_packaged_coroutine(const proxy_base<Super>& p)
: basic_packaged_coroutine(p, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) {
}
template <typename Super>
basic_packaged_coroutine(proxy_base<Super>&& p)
: basic_packaged_coroutine(std::move(p), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) {
}
template <typename Proxy, typename HandlerReference,
meta::enable<std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>, meta::neg<is_lua_index<meta::unqualified_t<HandlerReference>>>> = meta::enabler>
basic_packaged_coroutine(Proxy&& p, HandlerReference&& eh) : basic_packaged_coroutine(detail::force_cast<base_t>(p), std::forward<HandlerReference>(eh)) {
}
template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_packaged_coroutine(lua_State* L, T&& r) noexcept
: basic_packaged_coroutine(L, std::forward<T>(r), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_packaged_coroutine(lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward<T>(r)), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(lua_state(), -1, handler);
#endif // Safety
}
basic_packaged_coroutine(lua_nil_t n) : base_t(n), m_error_handler(n) {
}
basic_packaged_coroutine(lua_State* L, int index = -1)
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
basic_packaged_coroutine(lua_State* L, int index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#ifdef SOL_SAFE_REFERENCES
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(L, index, handler);
#endif // Safety
}
basic_packaged_coroutine(lua_State* L, absolute_index index)
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
basic_packaged_coroutine(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(L, index, handler);
#endif // Safety
}
basic_packaged_coroutine(lua_State* L, raw_index index)
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
basic_packaged_coroutine(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(L, index, handler);
#endif // Safety
}
basic_packaged_coroutine(lua_State* L, ref_index index)
: basic_packaged_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) {
}
basic_packaged_coroutine(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
#if SOL_IS_ON(SOL_SAFE_REFERENCES_I_)
auto pp = stack::push_pop(*this);
constructor_handler handler {};
stack::check<basic_packaged_coroutine>(lua_state(), -1, handler);
#endif // Safety
}
call_status status() const noexcept {
return stats;
}
bool error() const noexcept {
call_status cs = status();
return cs != call_status::ok && cs != call_status::yielded;
}
bool runnable() const noexcept {
return base_t::valid() && (status() == call_status::yielded);
}
reference error_handler() const noexcept {
return reference(m_L, registry_index(m_error_handler.index));
}
set_error_handler(reference new_error_handler) noexcept {
this->m_error_handler = stateless_reference(this->m_L, std::move(new_error_handler));
}
explicit operator bool() const noexcept {
return runnable();
}
template <typename... Args>
protected_function_result operator()(Args&&... args) {
return call<>(std::forward<Args>(args)...);
}
template <typename... Ret, typename... Args>
decltype(auto) operator()(types<Ret...>, Args&&... args) {
return call<Ret...>(std::forward<Args>(args)...);
}
template <typename... Ret, typename... Args>
decltype(auto) call(Args&&... args) {
// some users screw up coroutine.create
// and try to use it with sol::coroutine without ever calling the first resume in Lua
// this makes the stack incompatible with other kinds of stacks: protect against this
// make sure coroutines don't screw us over
base_t::push();
int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount);
}
};
#endif
} // namespace sol
#endif // SOL_PACKAGED_COROUTINE_HPP

@ -1,275 +1,275 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_PAIRS_ITERATOR_HPP
#define SOL_PAIRS_ITERATOR_HPP
#include <sol/version.hpp>
#include <sol/reference.hpp>
#include <sol/stack_reference.hpp>
#include <sol/table_iterator.hpp>
#include <sol/protected_function.hpp>
#include <sol/stack/detail/pairs.hpp>
namespace sol {
struct pairs_sentinel { };
class pairs_iterator {
private:
inline static constexpr int empty_key_index = -1;
public:
using key_type = object;
using mapped_type = object;
using value_type = std::pair<object, object>;
using iterator_category = std::input_iterator_tag;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using const_pointer = value_type const*;
using reference = value_type&;
using const_reference = const value_type&;
pairs_iterator() noexcept
: m_L(nullptr)
, m_next_function_ref(lua_nil)
, m_table_ref(lua_nil)
, m_cached_key_value_pair({ lua_nil, lua_nil })
, m_key_index(empty_key_index)
, m_iteration_index(0) {
}
pairs_iterator(const pairs_iterator&) = delete;
pairs_iterator& operator=(const pairs_iterator&) = delete;
pairs_iterator(pairs_iterator&& right) noexcept
: m_L(right.m_L)
, m_next_function_ref(std::move(right.m_next_function_ref))
, m_table_ref(std::move(right.m_table_ref))
, m_cached_key_value_pair(std::move(right.m_cached_key_value_pair))
, m_key_index(right.m_key_index)
, m_iteration_index(right.m_iteration_index) {
right.m_key_index = empty_key_index;
}
pairs_iterator& operator=(pairs_iterator&& right) noexcept {
m_L = right.m_L;
m_next_function_ref = std::move(right.m_next_function_ref);
m_table_ref = std::move(right.m_table_ref);
m_cached_key_value_pair = std::move(right.m_cached_key_value_pair);
m_key_index = right.m_key_index;
m_iteration_index = right.m_iteration_index;
right.m_key_index = empty_key_index;
return *this;
}
template <typename Source>
pairs_iterator(const Source& source_) noexcept : m_L(source_.lua_state()), m_key_index(empty_key_index), m_iteration_index(0) {
if (m_L == nullptr || !source_.valid()) {
m_key_index = empty_key_index;
return;
}
int source_index = -source_.push(m_L);
int abs_source_index = lua_absindex(m_L, source_index);
int metatable_exists = lua_getmetatable(m_L, abs_source_index);
lua_remove(m_L, abs_source_index);
if (metatable_exists == 1) {
// just has a metatable, but does it have __pairs ?
stack_reference metatable(m_L, raw_index(abs_source_index));
stack::get_field<is_global_table_v<Source>, true>(m_L, meta_function::pairs, metatable.stack_index());
optional<protected_function> maybe_pairs_function = stack::pop<optional<protected_function>>(m_L);
if (maybe_pairs_function.has_value()) {
protected_function& pairs_function = *maybe_pairs_function;
protected_function_result next_fn_and_table_and_first_key = pairs_function(source_);
if (next_fn_and_table_and_first_key.valid()) {
m_next_function_ref = next_fn_and_table_and_first_key.get<protected_function>(0);
m_table_ref = next_fn_and_table_and_first_key.get<sol::reference>(1);
m_key_index = next_fn_and_table_and_first_key.stack_index() - 1;
// remove next function and table
lua_remove(m_L, m_key_index);
lua_remove(m_L, m_key_index);
next_fn_and_table_and_first_key.abandon();
lua_remove(m_L, abs_source_index);
this->operator++();
m_iteration_index = 0;
return;
}
}
}
{
auto maybe_next = stack::stack_detail::find_lua_next_function(m_L);
if (maybe_next.has_value()) {
m_next_function_ref = std::move(*maybe_next);
m_table_ref = source_;
stack::push(m_L, lua_nil);
m_key_index = lua_gettop(m_L);
this->operator++();
m_iteration_index = 0;
return;
}
}
// okay, so none of the above worked and now we need to create
// a shim / polyfill instead
stack::push(m_L, &stack::stack_detail::c_lua_next);
m_next_function_ref = stack::pop<protected_function>(m_L);
m_table_ref = source_;
stack::push(m_L, lua_nil);
m_key_index = lua_gettop(m_L);
this->operator++();
m_iteration_index = 0;
}
pairs_iterator& operator++() {
if (m_key_index == empty_key_index) {
return *this;
}
{
sol::protected_function_result next_results = m_next_function_ref(m_table_ref, stack_reference(m_L, m_key_index));
if (!next_results.valid()) {
// TODO: abort, or throw an error?
m_clear();
m_key_index = empty_key_index;
return *this;
}
int next_results_count = next_results.return_count();
if (next_results_count < 2) {
// iteration is over!
next_results.abandon();
lua_settop(m_L, m_key_index - 1);
m_key_index = empty_key_index;
++m_iteration_index;
return *this;
}
else {
lua_remove(m_L, m_key_index);
m_key_index = next_results.stack_index() - 1;
m_cached_key_value_pair.first = stack::get<object>(m_L, m_key_index);
m_cached_key_value_pair.second = stack::get<object>(m_L, m_key_index + 1);
lua_settop(m_L, m_key_index);
next_results.abandon();
}
}
++m_iteration_index;
return *this;
}
std::ptrdiff_t index() const {
return static_cast<std::ptrdiff_t>(m_iteration_index);
}
const_reference operator*() const noexcept {
return m_cached_key_value_pair;
}
reference operator*() noexcept {
return m_cached_key_value_pair;
}
friend bool operator==(const pairs_iterator& left, const pairs_iterator& right) noexcept {
return left.m_table_ref == right.m_table_ref && left.m_iteration_index == right.m_iteration_index;
}
friend bool operator!=(const pairs_iterator& left, const pairs_iterator& right) noexcept {
return left.m_table_ref != right.m_table_ref || left.m_iteration_index != right.m_iteration_index;
}
friend bool operator==(const pairs_iterator& left, const pairs_sentinel&) noexcept {
return left.m_key_index == empty_key_index;
}
friend bool operator!=(const pairs_iterator& left, const pairs_sentinel&) noexcept {
return left.m_key_index != empty_key_index;
}
friend bool operator==(const pairs_sentinel&, const pairs_iterator& left) noexcept {
return left.m_key_index == empty_key_index;
}
friend bool operator!=(const pairs_sentinel&, const pairs_iterator& left) noexcept {
return left.m_key_index != empty_key_index;
}
~pairs_iterator() {
if (m_key_index != empty_key_index) {
m_clear();
}
}
private:
void m_clear() noexcept {
lua_remove(m_L, m_key_index);
}
lua_State* m_L;
protected_function m_next_function_ref;
sol::reference m_table_ref;
std::pair<object, object> m_cached_key_value_pair;
int m_key_index;
int m_iteration_index;
};
template <typename Source>
class basic_pairs_range {
private:
using source_t = std::add_lvalue_reference_t<Source>;
source_t m_source;
public:
using iterator = pairs_iterator;
using const_iterator = pairs_iterator;
basic_pairs_range(source_t source_) noexcept : m_source(source_) {
}
iterator begin() noexcept {
return iterator(m_source);
}
iterator begin() const noexcept {
return iterator(m_source);
}
const_iterator cbegin() const noexcept {
return const_iterator(m_source);
}
pairs_sentinel end() noexcept {
return {};
}
pairs_sentinel end() const noexcept {
return {};
}
pairs_sentinel cend() const noexcept {
return {};
}
};
} // namespace sol
#endif // SOL_PAIRS_ITERATOR_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_PAIRS_ITERATOR_HPP
#define SOL_PAIRS_ITERATOR_HPP
#include <sol/version.hpp>
#include <sol/reference.hpp>
#include <sol/stack_reference.hpp>
#include <sol/table_iterator.hpp>
#include <sol/protected_function.hpp>
#include <sol/stack/detail/pairs.hpp>
namespace sol {
struct pairs_sentinel { };
class pairs_iterator {
private:
inline static constexpr int empty_key_index = -1;
public:
using key_type = object;
using mapped_type = object;
using value_type = std::pair<object, object>;
using iterator_category = std::input_iterator_tag;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using const_pointer = value_type const*;
using reference = value_type&;
using const_reference = const value_type&;
pairs_iterator() noexcept
: m_L(nullptr)
, m_next_function_ref(lua_nil)
, m_table_ref(lua_nil)
, m_cached_key_value_pair({ lua_nil, lua_nil })
, m_key_index(empty_key_index)
, m_iteration_index(0) {
}
pairs_iterator(const pairs_iterator&) = delete;
pairs_iterator& operator=(const pairs_iterator&) = delete;
pairs_iterator(pairs_iterator&& right) noexcept
: m_L(right.m_L)
, m_next_function_ref(std::move(right.m_next_function_ref))
, m_table_ref(std::move(right.m_table_ref))
, m_cached_key_value_pair(std::move(right.m_cached_key_value_pair))
, m_key_index(right.m_key_index)
, m_iteration_index(right.m_iteration_index) {
right.m_key_index = empty_key_index;
}
pairs_iterator& operator=(pairs_iterator&& right) noexcept {
m_L = right.m_L;
m_next_function_ref = std::move(right.m_next_function_ref);
m_table_ref = std::move(right.m_table_ref);
m_cached_key_value_pair = std::move(right.m_cached_key_value_pair);
m_key_index = right.m_key_index;
m_iteration_index = right.m_iteration_index;
right.m_key_index = empty_key_index;
return *this;
}
template <typename Source>
pairs_iterator(const Source& source_) noexcept : m_L(source_.lua_state()), m_key_index(empty_key_index), m_iteration_index(0) {
if (m_L == nullptr || !source_.valid()) {
m_key_index = empty_key_index;
return;
}
int source_index = -source_.push(m_L);
int abs_source_index = lua_absindex(m_L, source_index);
int metatable_exists = lua_getmetatable(m_L, abs_source_index);
lua_remove(m_L, abs_source_index);
if (metatable_exists == 1) {
// just has a metatable, but does it have __pairs ?
stack_reference metatable(m_L, raw_index(abs_source_index));
stack::get_field<is_global_table_v<Source>, true>(m_L, meta_function::pairs, metatable.stack_index());
optional<protected_function> maybe_pairs_function = stack::pop<optional<protected_function>>(m_L);
if (maybe_pairs_function.has_value()) {
protected_function& pairs_function = *maybe_pairs_function;
protected_function_result next_fn_and_table_and_first_key = pairs_function(source_);
if (next_fn_and_table_and_first_key.valid()) {
m_next_function_ref = next_fn_and_table_and_first_key.get<protected_function>(0);
m_table_ref = next_fn_and_table_and_first_key.get<sol::reference>(1);
m_key_index = next_fn_and_table_and_first_key.stack_index() - 1;
// remove next function and table
lua_remove(m_L, m_key_index);
lua_remove(m_L, m_key_index);
next_fn_and_table_and_first_key.abandon();
lua_remove(m_L, abs_source_index);
this->operator++();
m_iteration_index = 0;
return;
}
}
}
{
auto maybe_next = stack::stack_detail::find_lua_next_function(m_L);
if (maybe_next.has_value()) {
m_next_function_ref = std::move(*maybe_next);
m_table_ref = source_;
stack::push(m_L, lua_nil);
m_key_index = lua_gettop(m_L);
this->operator++();
m_iteration_index = 0;
return;
}
}
// okay, so none of the above worked and now we need to create
// a shim / polyfill instead
stack::push(m_L, &stack::stack_detail::c_lua_next);
m_next_function_ref = stack::pop<protected_function>(m_L);
m_table_ref = source_;
stack::push(m_L, lua_nil);
m_key_index = lua_gettop(m_L);
this->operator++();
m_iteration_index = 0;
}
pairs_iterator& operator++() {
if (m_key_index == empty_key_index) {
return *this;
}
{
sol::protected_function_result next_results = m_next_function_ref(m_table_ref, stack_reference(m_L, m_key_index));
if (!next_results.valid()) {
// TODO: abort, or throw an error?
m_clear();
m_key_index = empty_key_index;
return *this;
}
int next_results_count = next_results.return_count();
if (next_results_count < 2) {
// iteration is over!
next_results.abandon();
lua_settop(m_L, m_key_index - 1);
m_key_index = empty_key_index;
++m_iteration_index;
return *this;
}
else {
lua_remove(m_L, m_key_index);
m_key_index = next_results.stack_index() - 1;
m_cached_key_value_pair.first = stack::get<object>(m_L, m_key_index);
m_cached_key_value_pair.second = stack::get<object>(m_L, m_key_index + 1);
lua_settop(m_L, m_key_index);
next_results.abandon();
}
}
++m_iteration_index;
return *this;
}
std::ptrdiff_t index() const {
return static_cast<std::ptrdiff_t>(m_iteration_index);
}
const_reference operator*() const noexcept {
return m_cached_key_value_pair;
}
reference operator*() noexcept {
return m_cached_key_value_pair;
}
friend bool operator==(const pairs_iterator& left, const pairs_iterator& right) noexcept {
return left.m_table_ref == right.m_table_ref && left.m_iteration_index == right.m_iteration_index;
}
friend bool operator!=(const pairs_iterator& left, const pairs_iterator& right) noexcept {
return left.m_table_ref != right.m_table_ref || left.m_iteration_index != right.m_iteration_index;
}
friend bool operator==(const pairs_iterator& left, const pairs_sentinel&) noexcept {
return left.m_key_index == empty_key_index;
}
friend bool operator!=(const pairs_iterator& left, const pairs_sentinel&) noexcept {
return left.m_key_index != empty_key_index;
}
friend bool operator==(const pairs_sentinel&, const pairs_iterator& left) noexcept {
return left.m_key_index == empty_key_index;
}
friend bool operator!=(const pairs_sentinel&, const pairs_iterator& left) noexcept {
return left.m_key_index != empty_key_index;
}
~pairs_iterator() {
if (m_key_index != empty_key_index) {
m_clear();
}
}
private:
void m_clear() noexcept {
lua_remove(m_L, m_key_index);
}
lua_State* m_L;
protected_function m_next_function_ref;
sol::reference m_table_ref;
std::pair<object, object> m_cached_key_value_pair;
int m_key_index;
int m_iteration_index;
};
template <typename Source>
class basic_pairs_range {
private:
using source_t = std::add_lvalue_reference_t<Source>;
source_t m_source;
public:
using iterator = pairs_iterator;
using const_iterator = pairs_iterator;
basic_pairs_range(source_t source_) noexcept : m_source(source_) {
}
iterator begin() noexcept {
return iterator(m_source);
}
iterator begin() const noexcept {
return iterator(m_source);
}
const_iterator cbegin() const noexcept {
return const_iterator(m_source);
}
pairs_sentinel end() noexcept {
return {};
}
pairs_sentinel end() const noexcept {
return {};
}
pairs_sentinel cend() const noexcept {
return {};
}
};
} // namespace sol
#endif // SOL_PAIRS_ITERATOR_HPP

@ -1,102 +1,102 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_POINTER_LIKE_HPP
#define SOL_POINTER_LIKE_HPP
#include <sol/base_traits.hpp>
#include <utility>
#include <type_traits>
namespace sol {
namespace meta {
namespace meta_detail {
template <typename T>
using is_dereferenceable_test = decltype(*std::declval<T>());
template <typename T>
using is_explicitly_dereferenceable_test = decltype(std::declval<T>().operator*());
} // namespace meta_detail
template <typename T>
using is_pointer_like = std::integral_constant<bool,
!std::is_array_v<T> && (std::is_pointer_v<T> || is_detected_v<meta_detail::is_explicitly_dereferenceable_test, T>)>;
template <typename T>
constexpr inline bool is_pointer_like_v = is_pointer_like<T>::value;
} // namespace meta
namespace detail {
template <typename T>
auto unwrap(T&& item) -> decltype(std::forward<T>(item)) {
return std::forward<T>(item);
}
template <typename T>
T& unwrap(std::reference_wrapper<T> arg) {
return arg.get();
}
template <typename T>
inline decltype(auto) deref(T&& item) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::is_pointer_like_v<Tu>) {
return *std::forward<T>(item);
}
else {
return std::forward<T>(item);
}
}
template <typename T>
inline decltype(auto) deref_move_only(T&& item) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::is_pointer_like_v<Tu> && !std::is_pointer_v<Tu> && !std::is_copy_constructible_v<Tu>) {
return *std::forward<T>(item);
}
else {
return std::forward<T>(item);
}
}
template <typename T>
inline T* ptr(T& val) {
return std::addressof(val);
}
template <typename T>
inline T* ptr(std::reference_wrapper<T> val) {
return std::addressof(val.get());
}
template <typename T>
inline T* ptr(T* val) {
return val;
}
} // namespace detail
} // namespace sol
#endif // SOL_POINTER_LIKE_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_POINTER_LIKE_HPP
#define SOL_POINTER_LIKE_HPP
#include <sol/base_traits.hpp>
#include <utility>
#include <type_traits>
namespace sol {
namespace meta {
namespace meta_detail {
template <typename T>
using is_dereferenceable_test = decltype(*std::declval<T>());
template <typename T>
using is_explicitly_dereferenceable_test = decltype(std::declval<T>().operator*());
} // namespace meta_detail
template <typename T>
using is_pointer_like = std::integral_constant<bool,
!std::is_array_v<T> && (std::is_pointer_v<T> || is_detected_v<meta_detail::is_explicitly_dereferenceable_test, T>)>;
template <typename T>
constexpr inline bool is_pointer_like_v = is_pointer_like<T>::value;
} // namespace meta
namespace detail {
template <typename T>
auto unwrap(T&& item) -> decltype(std::forward<T>(item)) {
return std::forward<T>(item);
}
template <typename T>
T& unwrap(std::reference_wrapper<T> arg) {
return arg.get();
}
template <typename T>
inline decltype(auto) deref(T&& item) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::is_pointer_like_v<Tu>) {
return *std::forward<T>(item);
}
else {
return std::forward<T>(item);
}
}
template <typename T>
inline decltype(auto) deref_move_only(T&& item) {
using Tu = meta::unqualified_t<T>;
if constexpr (meta::is_pointer_like_v<Tu> && !std::is_pointer_v<Tu> && !std::is_copy_constructible_v<Tu>) {
return *std::forward<T>(item);
}
else {
return std::forward<T>(item);
}
}
template <typename T>
inline T* ptr(T& val) {
return std::addressof(val);
}
template <typename T>
inline T* ptr(std::reference_wrapper<T> val) {
return std::addressof(val.get());
}
template <typename T>
inline T* ptr(T* val) {
return val;
}
} // namespace detail
} // namespace sol
#endif // SOL_POINTER_LIKE_HPP

@ -1,47 +1,47 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
// clang-format off
#if defined(SOL_PROLOGUE_I_)
#error "[sol2] Library Prologue was already included in translation unit and not properly ended with an epilogue."
#endif
#define SOL_PROLOGUE_I_ 1
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_)
#define _FWD(...) static_cast<decltype( __VA_ARGS__ )&&>( __VA_ARGS__ )
#if SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ )
#else
#include <type_traits>
#define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) )
#endif
#endif
// clang-format on
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
// clang-format off
#if defined(SOL_PROLOGUE_I_)
#error "[sol2] Library Prologue was already included in translation unit and not properly ended with an epilogue."
#endif
#define SOL_PROLOGUE_I_ 1
#if SOL_IS_ON(SOL_BUILD_CXX_MODE_I_)
#define _FWD(...) static_cast<decltype( __VA_ARGS__ )&&>( __VA_ARGS__ )
#if SOL_IS_ON(SOL_COMPILER_GCC_I_) || SOL_IS_ON(SOL_COMPILER_CLANG_I_)
#define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ )
#else
#include <type_traits>
#define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) )
#endif
#endif
// clang-format on

@ -1,351 +1,351 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_STACK_HPP
#define SOL_STACK_HPP
#include <sol/trampoline.hpp>
#include <sol/stack_core.hpp>
#include <sol/stack_reference.hpp>
#include <sol/stack_check.hpp>
#include <sol/stack_get.hpp>
#include <sol/stack_check_get.hpp>
#include <sol/stack_push.hpp>
#include <sol/stack_pop.hpp>
#include <sol/stack_field.hpp>
#include <sol/stack_probe.hpp>
#include <cstring>
#include <array>
namespace sol {
namespace detail {
using typical_chunk_name_t = char[SOL_ID_SIZE_I_];
using typical_file_chunk_name_t = char[SOL_FILE_ID_SIZE_I_];
inline const std::string& default_chunk_name() {
static const std::string name = "";
return name;
}
template <std::size_t N>
const char* make_chunk_name(const string_view& code, const std::string& chunkname, char (&basechunkname)[N]) {
if (chunkname.empty()) {
auto it = code.cbegin();
auto e = code.cend();
std::size_t i = 0;
static const std::size_t n = N - 4;
for (i = 0; i < n && it != e; ++i, ++it) {
basechunkname[i] = *it;
}
if (it != e) {
for (std::size_t c = 0; c < 3; ++i, ++c) {
basechunkname[i] = '.';
}
}
basechunkname[i] = '\0';
return &basechunkname[0];
}
else {
return chunkname.c_str();
}
}
inline void clear_entries(stack_reference r) {
stack::push(r.lua_state(), lua_nil);
while (lua_next(r.lua_state(), -2)) {
absolute_index key(r.lua_state(), -2);
auto pn = stack::pop_n(r.lua_state(), 1);
stack::set_field<false, true>(r.lua_state(), key, lua_nil, r.stack_index());
}
}
inline void clear_entries(const reference& registry_reference) {
auto pp = stack::push_pop(registry_reference);
stack_reference ref(registry_reference.lua_state(), -1);
clear_entries(ref);
}
} // namespace detail
namespace stack {
namespace stack_detail {
template <typename T>
inline int push_as_upvalues(lua_State* L, T& item) {
typedef std::decay_t<T> TValue;
static const std::size_t itemsize = sizeof(TValue);
static const std::size_t voidsize = sizeof(void*);
static const std::size_t voidsizem1 = voidsize - 1;
static const std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize;
typedef std::array<void*, data_t_count> data_t;
data_t data { {} };
std::memcpy(&data[0], std::addressof(item), itemsize);
int pushcount = 0;
for (const auto& v : data) {
lua_pushlightuserdata(L, v);
pushcount += 1;
}
return pushcount;
}
template <typename T>
inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 2) {
static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
typedef std::array<void*, data_t_count> data_t;
data_t voiddata { {} };
for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
voiddata[i] = lua_touserdata(L, upvalue_index(index++));
}
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
}
template <typename T>
inline std::pair<T, int> get_as_upvalues_using_function(lua_State* L, int function_index = -1) {
static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
typedef std::array<void*, data_t_count> data_t;
function_index = lua_absindex(L, function_index);
int index = 0;
data_t voiddata { {} };
for (std::size_t d = 0; d < sizeof(T); d += sizeof(void*)) {
// first upvalue is nullptr to respect environment shenanigans
// So +2 instead of +1
const char* upvalue_name = lua_getupvalue(L, function_index, index + 2);
if (upvalue_name == nullptr) {
// We should freak out here...
break;
}
voiddata[index] = lua_touserdata(L, -1);
++index;
}
lua_pop(L, index);
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
}
template <bool checked, typename Handler, typename Fx, typename... Args>
static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, Handler&&, record&, Fx&& fx, Args&&... args) {
return std::forward<Fx>(fx)(std::forward<Args>(args)...);
}
template <bool checked, typename Arg, typename... Args, std::size_t I, std::size_t... Is, typename Handler, typename Fx, typename... FxArgs>
static decltype(auto) eval(types<Arg, Args...>, std::index_sequence<I, Is...>, lua_State* L_, int start_index_, Handler&& handler_,
record& tracking_, Fx&& fx_, FxArgs&&... fxargs_) {
#if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS_I_)
// We can save performance/time by letting errors unwind produced arguments
// rather than checking everything once, and then potentially re-doing work
if constexpr (checked) {
return eval<checked>(types<Args...>(),
std::index_sequence<Is...>(),
L_,
start_index_,
std::forward<Handler>(handler_),
tracking_,
std::forward<Fx>(fx_),
std::forward<FxArgs>(fxargs_)...,
*stack_detail::check_get_arg<Arg>(L_, start_index_ + tracking_.used, handler_, tracking_));
}
else
#endif
{
return eval<checked>(types<Args...>(),
std::index_sequence<Is...>(),
L_,
start_index_,
std::forward<Handler>(handler_),
tracking_,
std::forward<Fx>(fx_),
std::forward<FxArgs>(fxargs_)...,
stack_detail::unchecked_get_arg<Arg>(L_, start_index_ + tracking_.used, tracking_));
}
}
template <bool checkargs = detail::default_safe_function_calls, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs>
inline decltype(auto) call(types<R>, types<Args...> argument_types_, std::index_sequence<I...> argument_indices_, lua_State* L_,
int start_index_, Fx&& fx_, FxArgs&&... args_) {
static_assert(meta::all_v<meta::is_not_move_only<Args>...>,
"One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take "
"a reference and std::move it manually if this was your intention.");
argument_handler<types<R, Args...>> handler {};
record tracking {};
#if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS_I_)
if constexpr (checkargs) {
multi_check<Args...>(L_, start_index_, handler);
}
#endif
if constexpr (std::is_void_v<R>) {
eval<checkargs>(
argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...);
}
else {
return eval<checkargs>(
argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...);
}
}
} // namespace stack_detail
template <typename T>
int set_ref(lua_State* L, T&& arg, int tableindex = -2) {
push(L, std::forward<T>(arg));
return luaL_ref(L, tableindex);
}
template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs>
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
using args_indices = std::make_index_sequence<sizeof...(Args)>;
if constexpr (std::is_void_v<R>) {
stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
else {
return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
}
template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs>
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
if constexpr (std::is_void_v<R>) {
call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
else {
return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
}
template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs>
inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
using expected_count_t = meta::count_for_pack<lua_size, Args...>;
if constexpr (std::is_void_v<R>) {
call<check_args>(tr,
ta,
L,
(std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value), static_cast<int>(0)),
std::forward<Fx>(fx),
std::forward<FxArgs>(args)...);
}
else {
return call<check_args>(tr,
ta,
L,
(std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value), static_cast<int>(0)),
std::forward<Fx>(fx),
std::forward<FxArgs>(args)...);
}
}
template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Ret0, typename... Ret, typename... Args,
typename Fx, typename... FxArgs>
inline int call_into_lua(types<Ret0, Ret...> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
if constexpr (std::is_void_v<Ret0>) {
call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
if constexpr (clean_stack) {
lua_settop(L, 0);
}
return 0;
}
else {
(void)tr;
decltype(auto) r
= call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
using R = meta::unqualified_t<decltype(r)>;
using is_stack = meta::any<is_stack_based<R>, std::is_same<R, absolute_index>, std::is_same<R, ref_index>, std::is_same<R, raw_index>>;
if constexpr (clean_stack && !is_stack::value) {
lua_settop(L, 0);
}
return push_reference(L, std::forward<decltype(r)>(r));
}
}
template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... FxArgs>
inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
using traits_type = lua_bind_traits<meta::unqualified_t<Fx>>;
using args_list = typename traits_type::args_list;
using returns_list = typename traits_type::returns_list;
return call_into_lua<check_args, clean_stack>(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
}
inline call_syntax get_call_syntax(lua_State* L, const string_view& key, int index) {
if (lua_gettop(L) < 1) {
return call_syntax::dot;
}
luaL_getmetatable(L, key.data());
auto pn = pop_n(L, 1);
if (lua_compare(L, -1, index, LUA_OPEQ) != 1) {
return call_syntax::dot;
}
return call_syntax::colon;
}
inline void script(
lua_State* L, lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
detail::typical_chunk_name_t basechunkname = {};
const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
lua_error(L);
}
}
inline void script(
lua_State* L, const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
detail::typical_chunk_name_t basechunkname = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
lua_error(L);
}
}
inline void script_file(lua_State* L, const std::string& filename, load_mode mode = load_mode::any) {
if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
lua_error(L);
}
}
inline void luajit_exception_handler(lua_State* L, int (*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) {
#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_)
if (L == nullptr) {
return;
}
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
#endif // make sure stack doesn't overflow
lua_pushlightuserdata(L, (void*)handler);
auto pn = pop_n(L, 1);
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
#else
(void)L;
(void)handler;
#endif
}
inline void luajit_exception_off(lua_State* L) {
#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_)
if (L == nullptr) {
return;
}
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF);
#else
(void)L;
#endif
}
} // namespace stack
} // namespace sol
#endif // SOL_STACK_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_STACK_HPP
#define SOL_STACK_HPP
#include <sol/trampoline.hpp>
#include <sol/stack_core.hpp>
#include <sol/stack_reference.hpp>
#include <sol/stack_check.hpp>
#include <sol/stack_get.hpp>
#include <sol/stack_check_get.hpp>
#include <sol/stack_push.hpp>
#include <sol/stack_pop.hpp>
#include <sol/stack_field.hpp>
#include <sol/stack_probe.hpp>
#include <cstring>
#include <array>
namespace sol {
namespace detail {
using typical_chunk_name_t = char[SOL_ID_SIZE_I_];
using typical_file_chunk_name_t = char[SOL_FILE_ID_SIZE_I_];
inline const std::string& default_chunk_name() {
static const std::string name = "";
return name;
}
template <std::size_t N>
const char* make_chunk_name(const string_view& code, const std::string& chunkname, char (&basechunkname)[N]) {
if (chunkname.empty()) {
auto it = code.cbegin();
auto e = code.cend();
std::size_t i = 0;
static const std::size_t n = N - 4;
for (i = 0; i < n && it != e; ++i, ++it) {
basechunkname[i] = *it;
}
if (it != e) {
for (std::size_t c = 0; c < 3; ++i, ++c) {
basechunkname[i] = '.';
}
}
basechunkname[i] = '\0';
return &basechunkname[0];
}
else {
return chunkname.c_str();
}
}
inline void clear_entries(stack_reference r) {
stack::push(r.lua_state(), lua_nil);
while (lua_next(r.lua_state(), -2)) {
absolute_index key(r.lua_state(), -2);
auto pn = stack::pop_n(r.lua_state(), 1);
stack::set_field<false, true>(r.lua_state(), key, lua_nil, r.stack_index());
}
}
inline void clear_entries(const reference& registry_reference) {
auto pp = stack::push_pop(registry_reference);
stack_reference ref(registry_reference.lua_state(), -1);
clear_entries(ref);
}
} // namespace detail
namespace stack {
namespace stack_detail {
template <typename T>
inline int push_as_upvalues(lua_State* L, T& item) {
typedef std::decay_t<T> TValue;
static const std::size_t itemsize = sizeof(TValue);
static const std::size_t voidsize = sizeof(void*);
static const std::size_t voidsizem1 = voidsize - 1;
static const std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize;
typedef std::array<void*, data_t_count> data_t;
data_t data { {} };
std::memcpy(&data[0], std::addressof(item), itemsize);
int pushcount = 0;
for (const auto& v : data) {
lua_pushlightuserdata(L, v);
pushcount += 1;
}
return pushcount;
}
template <typename T>
inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 2) {
static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
typedef std::array<void*, data_t_count> data_t;
data_t voiddata { {} };
for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
voiddata[i] = lua_touserdata(L, upvalue_index(index++));
}
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
}
template <typename T>
inline std::pair<T, int> get_as_upvalues_using_function(lua_State* L, int function_index = -1) {
static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
typedef std::array<void*, data_t_count> data_t;
function_index = lua_absindex(L, function_index);
int index = 0;
data_t voiddata { {} };
for (std::size_t d = 0; d < sizeof(T); d += sizeof(void*)) {
// first upvalue is nullptr to respect environment shenanigans
// So +2 instead of +1
const char* upvalue_name = lua_getupvalue(L, function_index, index + 2);
if (upvalue_name == nullptr) {
// We should freak out here...
break;
}
voiddata[index] = lua_touserdata(L, -1);
++index;
}
lua_pop(L, index);
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
}
template <bool checked, typename Handler, typename Fx, typename... Args>
static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, Handler&&, record&, Fx&& fx, Args&&... args) {
return std::forward<Fx>(fx)(std::forward<Args>(args)...);
}
template <bool checked, typename Arg, typename... Args, std::size_t I, std::size_t... Is, typename Handler, typename Fx, typename... FxArgs>
static decltype(auto) eval(types<Arg, Args...>, std::index_sequence<I, Is...>, lua_State* L_, int start_index_, Handler&& handler_,
record& tracking_, Fx&& fx_, FxArgs&&... fxargs_) {
#if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS_I_)
// We can save performance/time by letting errors unwind produced arguments
// rather than checking everything once, and then potentially re-doing work
if constexpr (checked) {
return eval<checked>(types<Args...>(),
std::index_sequence<Is...>(),
L_,
start_index_,
std::forward<Handler>(handler_),
tracking_,
std::forward<Fx>(fx_),
std::forward<FxArgs>(fxargs_)...,
*stack_detail::check_get_arg<Arg>(L_, start_index_ + tracking_.used, handler_, tracking_));
}
else
#endif
{
return eval<checked>(types<Args...>(),
std::index_sequence<Is...>(),
L_,
start_index_,
std::forward<Handler>(handler_),
tracking_,
std::forward<Fx>(fx_),
std::forward<FxArgs>(fxargs_)...,
stack_detail::unchecked_get_arg<Arg>(L_, start_index_ + tracking_.used, tracking_));
}
}
template <bool checkargs = detail::default_safe_function_calls, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs>
inline decltype(auto) call(types<R>, types<Args...> argument_types_, std::index_sequence<I...> argument_indices_, lua_State* L_,
int start_index_, Fx&& fx_, FxArgs&&... args_) {
static_assert(meta::all_v<meta::is_not_move_only<Args>...>,
"One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take "
"a reference and std::move it manually if this was your intention.");
argument_handler<types<R, Args...>> handler {};
record tracking {};
#if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS_I_)
if constexpr (checkargs) {
multi_check<Args...>(L_, start_index_, handler);
}
#endif
if constexpr (std::is_void_v<R>) {
eval<checkargs>(
argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...);
}
else {
return eval<checkargs>(
argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...);
}
}
} // namespace stack_detail
template <typename T>
int set_ref(lua_State* L, T&& arg, int tableindex = -2) {
push(L, std::forward<T>(arg));
return luaL_ref(L, tableindex);
}
template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs>
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
using args_indices = std::make_index_sequence<sizeof...(Args)>;
if constexpr (std::is_void_v<R>) {
stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
else {
return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
}
template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs>
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
if constexpr (std::is_void_v<R>) {
call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
else {
return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
}
template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs>
inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
using expected_count_t = meta::count_for_pack<lua_size, Args...>;
if constexpr (std::is_void_v<R>) {
call<check_args>(tr,
ta,
L,
(std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value), static_cast<int>(0)),
std::forward<Fx>(fx),
std::forward<FxArgs>(args)...);
}
else {
return call<check_args>(tr,
ta,
L,
(std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value), static_cast<int>(0)),
std::forward<Fx>(fx),
std::forward<FxArgs>(args)...);
}
}
template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Ret0, typename... Ret, typename... Args,
typename Fx, typename... FxArgs>
inline int call_into_lua(types<Ret0, Ret...> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
if constexpr (std::is_void_v<Ret0>) {
call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
if constexpr (clean_stack) {
lua_settop(L, 0);
}
return 0;
}
else {
(void)tr;
decltype(auto) r
= call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
using R = meta::unqualified_t<decltype(r)>;
using is_stack = meta::any<is_stack_based<R>, std::is_same<R, absolute_index>, std::is_same<R, ref_index>, std::is_same<R, raw_index>>;
if constexpr (clean_stack && !is_stack::value) {
lua_settop(L, 0);
}
return push_reference(L, std::forward<decltype(r)>(r));
}
}
template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... FxArgs>
inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
using traits_type = lua_bind_traits<meta::unqualified_t<Fx>>;
using args_list = typename traits_type::args_list;
using returns_list = typename traits_type::returns_list;
return call_into_lua<check_args, clean_stack>(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
}
inline call_syntax get_call_syntax(lua_State* L, const string_view& key, int index) {
if (lua_gettop(L) < 1) {
return call_syntax::dot;
}
luaL_getmetatable(L, key.data());
auto pn = pop_n(L, 1);
if (lua_compare(L, -1, index, LUA_OPEQ) != 1) {
return call_syntax::dot;
}
return call_syntax::colon;
}
inline void script(
lua_State* L, lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
detail::typical_chunk_name_t basechunkname = {};
const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
lua_error(L);
}
}
inline void script(
lua_State* L, const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
detail::typical_chunk_name_t basechunkname = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
lua_error(L);
}
}
inline void script_file(lua_State* L, const std::string& filename, load_mode mode = load_mode::any) {
if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
lua_error(L);
}
}
inline void luajit_exception_handler(lua_State* L, int (*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) {
#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_)
if (L == nullptr) {
return;
}
#if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_)
luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
#endif // make sure stack doesn't overflow
lua_pushlightuserdata(L, (void*)handler);
auto pn = pop_n(L, 1);
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
#else
(void)L;
(void)handler;
#endif
}
inline void luajit_exception_off(lua_State* L) {
#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_)
if (L == nullptr) {
return;
}
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF);
#else
(void)L;
#endif
}
} // namespace stack
} // namespace sol
#endif // SOL_STACK_HPP

@ -1,98 +1,98 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this Spermission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_DETAIL_PAIRS_HPP
#define SOL_DETAIL_PAIRS_HPP
#include <sol/version.hpp>
#include <sol/stack.hpp>
#include <sol/stack_reference.hpp>
#include <sol/protected_function.hpp>
#include <sol/assert.hpp>
#include <optional>
namespace sol { namespace stack { namespace stack_detail {
inline bool maybe_push_lua_next_function(lua_State* L_) {
stack::get_field<true, false>(L_, "next");
bool is_next = stack::check<protected_function>(L_);
if (is_next) {
return true;
}
stack::get_field<true, false>(L_, "table");
stack::record tracking{};
if (!stack::loose_table_check(L_, -1, &no_panic, tracking)) {
return false;
}
lua_getfield(L_, -1, "next");
bool is_table_next_func = stack::check<protected_function>(L_, -1);
if (is_table_next_func) {
return true;
}
lua_pop(L_, 1);
return false;
}
inline std::optional<protected_function> find_lua_next_function(lua_State* L_) {
if (maybe_push_lua_next_function(L_)) {
return stack::pop<protected_function>(L_);
}
return std::nullopt;
}
inline int c_lua_next(lua_State* L_) noexcept {
stack_reference table_stack_ref(L_, raw_index(1));
stateless_stack_reference key_stack_ref(L_, raw_index(2));
int result = lua_next(table_stack_ref.lua_state(), table_stack_ref.stack_index());
if (result == 0) {
stack::push(L_, lua_nil);
return 1;
}
return 2;
}
inline int readonly_pairs(lua_State* L_) noexcept {
int pushed = 0;
if (!maybe_push_lua_next_function(L_)) {
// we do not have the "next" function in the global namespace
// from the "table" global entiry, use our own
pushed += stack::push(L_, &c_lua_next);
}
else {
pushed += 1;
}
int metatable_exists = lua_getmetatable(L_, 1);
sol_c_assert(metatable_exists == 1);
const auto& index_key = to_string(sol::meta_function::index);
lua_getfield(L_, lua_gettop(L_), index_key.c_str());
lua_remove(L_, -2);
pushed += 1;
pushed += stack::push(L_, lua_nil);
return pushed;
}
}}} // sol::stack::stack_detail
#endif // SOL_DETAIL_PAIRS_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this Spermission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_DETAIL_PAIRS_HPP
#define SOL_DETAIL_PAIRS_HPP
#include <sol/version.hpp>
#include <sol/stack.hpp>
#include <sol/stack_reference.hpp>
#include <sol/protected_function.hpp>
#include <sol/assert.hpp>
#include <optional>
namespace sol { namespace stack { namespace stack_detail {
inline bool maybe_push_lua_next_function(lua_State* L_) {
stack::get_field<true, false>(L_, "next");
bool is_next = stack::check<protected_function>(L_);
if (is_next) {
return true;
}
stack::get_field<true, false>(L_, "table");
stack::record tracking{};
if (!stack::loose_table_check(L_, -1, &no_panic, tracking)) {
return false;
}
lua_getfield(L_, -1, "next");
bool is_table_next_func = stack::check<protected_function>(L_, -1);
if (is_table_next_func) {
return true;
}
lua_pop(L_, 1);
return false;
}
inline std::optional<protected_function> find_lua_next_function(lua_State* L_) {
if (maybe_push_lua_next_function(L_)) {
return stack::pop<protected_function>(L_);
}
return std::nullopt;
}
inline int c_lua_next(lua_State* L_) noexcept {
stack_reference table_stack_ref(L_, raw_index(1));
stateless_stack_reference key_stack_ref(L_, raw_index(2));
int result = lua_next(table_stack_ref.lua_state(), table_stack_ref.stack_index());
if (result == 0) {
stack::push(L_, lua_nil);
return 1;
}
return 2;
}
inline int readonly_pairs(lua_State* L_) noexcept {
int pushed = 0;
if (!maybe_push_lua_next_function(L_)) {
// we do not have the "next" function in the global namespace
// from the "table" global entiry, use our own
pushed += stack::push(L_, &c_lua_next);
}
else {
pushed += 1;
}
int metatable_exists = lua_getmetatable(L_, 1);
sol_c_assert(metatable_exists == 1);
const auto& index_key = to_string(sol::meta_function::index);
lua_getfield(L_, lua_gettop(L_), index_key.c_str());
lua_remove(L_, -2);
pushed += 1;
pushed += stack::push(L_, lua_nil);
return pushed;
}
}}} // sol::stack::stack_detail
#endif // SOL_DETAIL_PAIRS_HPP

@ -1,116 +1,116 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_TABLE_HPP
#define SOL_TABLE_HPP
#include <sol/table_core.hpp>
#include <sol/lua_table.hpp>
#include <sol/usertype.hpp>
namespace sol {
typedef table_core<false> table;
template <bool is_global, typename base_type>
template <typename Class, typename Key>
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key) {
constant_automagic_enrollments<> enrollments {};
return this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
}
template <bool is_global, typename base_type>
template <typename Class, typename Key, automagic_flags enrollment_flags>
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, constant_automagic_enrollments<enrollment_flags> enrollments) {
int mt_index = u_detail::register_usertype<Class, enrollment_flags>(this->lua_state(), std::move(enrollments));
usertype<Class> mt(this->lua_state(), -mt_index);
lua_pop(this->lua_state(), 1);
set(std::forward<Key>(key), mt);
return mt;
}
template <bool is_global, typename base_type>
template <typename Class, typename Key>
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, automagic_enrollments enrollments) {
int mt_index = u_detail::register_usertype<Class, automagic_flags::all>(this->lua_state(), std::move(enrollments));
usertype<Class> mt(this->lua_state(), -mt_index);
lua_pop(this->lua_state(), 1);
set(std::forward<Key>(key), mt);
return mt;
}
template <bool is_global, typename base_type>
template <typename Class, typename Key, typename Arg, typename... Args, typename>
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, Arg&& arg, Args&&... args) {
constexpr automagic_flags enrollment_flags = meta::any_same_v<no_construction, meta::unqualified_t<Arg>, meta::unqualified_t<Args>...>
? clear_flags(automagic_flags::all, automagic_flags::default_constructor)
: automagic_flags::all;
constant_automagic_enrollments<enrollment_flags> enrollments;
enrollments.default_constructor = !detail::any_is_constructor_v<Arg, Args...>;
enrollments.destructor = !detail::any_is_destructor_v<Arg, Args...>;
usertype<Class> ut = this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
static_assert(sizeof...(Args) % 2 == static_cast<std::size_t>(!detail::any_is_constructor_v<Arg>),
"you must pass an even number of arguments to new_usertype after first passing a constructor");
if constexpr (detail::any_is_constructor_v<Arg>) {
ut.set(meta_function::construct, std::forward<Arg>(arg));
ut.tuple_set(std::make_index_sequence<(sizeof...(Args)) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
}
else {
ut.tuple_set(std::make_index_sequence<(sizeof...(Args) + 1) / 2>(), std::forward_as_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...));
}
return ut;
}
template <typename base_type>
template <typename Key, typename Value>
basic_metatable<base_type>& basic_metatable<base_type>::set(Key&& key, Value&& value) {
this->push();
lua_State* L = this->lua_state();
int target = lua_gettop(L);
optional<u_detail::usertype_storage_base&> maybe_uts = nullopt;
maybe_uts = u_detail::maybe_get_usertype_storage_base(L, target);
if (maybe_uts) {
u_detail::usertype_storage_base& uts = *maybe_uts;
uts.set(L, std::forward<Key>(key), std::forward<Value>(value));
return *this;
}
else {
base_t::set(std::forward<Key>(key), std::forward<Value>(value));
}
this->pop();
return *this;
}
namespace stack {
template <>
struct unqualified_getter<metatable_key_t> {
static metatable get(lua_State* L, int index = -1) {
if (lua_getmetatable(L, index) == 0) {
return metatable(L, ref_index(LUA_REFNIL));
}
return metatable(L, -1);
}
};
} // namespace stack
} // namespace sol
#endif // SOL_TABLE_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_TABLE_HPP
#define SOL_TABLE_HPP
#include <sol/table_core.hpp>
#include <sol/lua_table.hpp>
#include <sol/usertype.hpp>
namespace sol {
typedef table_core<false> table;
template <bool is_global, typename base_type>
template <typename Class, typename Key>
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key) {
constant_automagic_enrollments<> enrollments {};
return this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
}
template <bool is_global, typename base_type>
template <typename Class, typename Key, automagic_flags enrollment_flags>
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, constant_automagic_enrollments<enrollment_flags> enrollments) {
int mt_index = u_detail::register_usertype<Class, enrollment_flags>(this->lua_state(), std::move(enrollments));
usertype<Class> mt(this->lua_state(), -mt_index);
lua_pop(this->lua_state(), 1);
set(std::forward<Key>(key), mt);
return mt;
}
template <bool is_global, typename base_type>
template <typename Class, typename Key>
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, automagic_enrollments enrollments) {
int mt_index = u_detail::register_usertype<Class, automagic_flags::all>(this->lua_state(), std::move(enrollments));
usertype<Class> mt(this->lua_state(), -mt_index);
lua_pop(this->lua_state(), 1);
set(std::forward<Key>(key), mt);
return mt;
}
template <bool is_global, typename base_type>
template <typename Class, typename Key, typename Arg, typename... Args, typename>
usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, Arg&& arg, Args&&... args) {
constexpr automagic_flags enrollment_flags = meta::any_same_v<no_construction, meta::unqualified_t<Arg>, meta::unqualified_t<Args>...>
? clear_flags(automagic_flags::all, automagic_flags::default_constructor)
: automagic_flags::all;
constant_automagic_enrollments<enrollment_flags> enrollments;
enrollments.default_constructor = !detail::any_is_constructor_v<Arg, Args...>;
enrollments.destructor = !detail::any_is_destructor_v<Arg, Args...>;
usertype<Class> ut = this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
static_assert(sizeof...(Args) % 2 == static_cast<std::size_t>(!detail::any_is_constructor_v<Arg>),
"you must pass an even number of arguments to new_usertype after first passing a constructor");
if constexpr (detail::any_is_constructor_v<Arg>) {
ut.set(meta_function::construct, std::forward<Arg>(arg));
ut.tuple_set(std::make_index_sequence<(sizeof...(Args)) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
}
else {
ut.tuple_set(std::make_index_sequence<(sizeof...(Args) + 1) / 2>(), std::forward_as_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...));
}
return ut;
}
template <typename base_type>
template <typename Key, typename Value>
basic_metatable<base_type>& basic_metatable<base_type>::set(Key&& key, Value&& value) {
this->push();
lua_State* L = this->lua_state();
int target = lua_gettop(L);
optional<u_detail::usertype_storage_base&> maybe_uts = nullopt;
maybe_uts = u_detail::maybe_get_usertype_storage_base(L, target);
if (maybe_uts) {
u_detail::usertype_storage_base& uts = *maybe_uts;
uts.set(L, std::forward<Key>(key), std::forward<Value>(value));
return *this;
}
else {
base_t::set(std::forward<Key>(key), std::forward<Value>(value));
}
this->pop();
return *this;
}
namespace stack {
template <>
struct unqualified_getter<metatable_key_t> {
static metatable get(lua_State* L, int index = -1) {
if (lua_getmetatable(L, index) == 0) {
return metatable(L, ref_index(LUA_REFNIL));
}
return metatable(L, -1);
}
};
} // namespace stack
} // namespace sol
#endif // SOL_TABLE_HPP

@ -1,93 +1,93 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_TUPLE_HPP
#define SOL_TUPLE_HPP
#include <sol/forward.hpp>
#include <sol/base_traits.hpp>
#include <tuple>
#include <cstddef>
namespace sol {
namespace detail {
using swallow = std::initializer_list<int>;
} // namespace detail
namespace meta {
template <typename T>
using is_tuple = is_specialization_of<T, std::tuple>;
template <typename T>
constexpr inline bool is_tuple_v = is_tuple<T>::value;
namespace detail {
template <typename... Args>
struct tuple_types_ {
typedef types<Args...> type;
};
template <typename... Args>
struct tuple_types_<std::tuple<Args...>> {
typedef types<Args...> type;
};
} // namespace detail
template <typename... Args>
using tuple_types = typename detail::tuple_types_<Args...>::type;
template <typename Arg>
struct pop_front_type;
template <typename Arg>
using pop_front_type_t = typename pop_front_type<Arg>::type;
template <typename... Args>
struct pop_front_type<types<Args...>> {
typedef void front_type;
typedef types<Args...> type;
};
template <typename Arg, typename... Args>
struct pop_front_type<types<Arg, Args...>> {
typedef Arg front_type;
typedef types<Args...> type;
};
template <std::size_t N, typename Tuple>
using tuple_element = std::tuple_element<N, std::remove_reference_t<Tuple>>;
template <std::size_t N, typename Tuple>
using tuple_element_t = std::tuple_element_t<N, std::remove_reference_t<Tuple>>;
template <std::size_t N, typename Tuple>
using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>;
template <std::size_t N, typename Tuple>
using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>;
} // namespace meta
} // namespace sol
#endif // SOL_TUPLE_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_TUPLE_HPP
#define SOL_TUPLE_HPP
#include <sol/forward.hpp>
#include <sol/base_traits.hpp>
#include <tuple>
#include <cstddef>
namespace sol {
namespace detail {
using swallow = std::initializer_list<int>;
} // namespace detail
namespace meta {
template <typename T>
using is_tuple = is_specialization_of<T, std::tuple>;
template <typename T>
constexpr inline bool is_tuple_v = is_tuple<T>::value;
namespace detail {
template <typename... Args>
struct tuple_types_ {
typedef types<Args...> type;
};
template <typename... Args>
struct tuple_types_<std::tuple<Args...>> {
typedef types<Args...> type;
};
} // namespace detail
template <typename... Args>
using tuple_types = typename detail::tuple_types_<Args...>::type;
template <typename Arg>
struct pop_front_type;
template <typename Arg>
using pop_front_type_t = typename pop_front_type<Arg>::type;
template <typename... Args>
struct pop_front_type<types<Args...>> {
typedef void front_type;
typedef types<Args...> type;
};
template <typename Arg, typename... Args>
struct pop_front_type<types<Arg, Args...>> {
typedef Arg front_type;
typedef types<Args...> type;
};
template <std::size_t N, typename Tuple>
using tuple_element = std::tuple_element<N, std::remove_reference_t<Tuple>>;
template <std::size_t N, typename Tuple>
using tuple_element_t = std::tuple_element_t<N, std::remove_reference_t<Tuple>>;
template <std::size_t N, typename Tuple>
using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>;
template <std::size_t N, typename Tuple>
using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>;
} // namespace meta
} // namespace sol
#endif // SOL_TUPLE_HPP

@ -1,308 +1,308 @@
#pragma once
#include <sol/string_view.hpp>
#include <array>
#include <cstring>
namespace sol {
// Everything here was lifted pretty much straight out of
// ogonek, because fuck figuring it out=
namespace unicode {
enum class error_code {
ok = 0,
invalid_code_point,
invalid_code_unit,
invalid_leading_surrogate,
invalid_trailing_surrogate,
sequence_too_short,
overlong_sequence,
};
inline const string_view& to_string(error_code ec) {
static const string_view storage[7] = { "ok",
"invalid code points",
"invalid code unit",
"invalid leading surrogate",
"invalid trailing surrogate",
"sequence too short",
"overlong sequence" };
return storage[static_cast<std::size_t>(ec)];
}
template <typename It>
struct decoded_result {
error_code error;
char32_t codepoint;
It next;
};
template <typename C>
struct encoded_result {
error_code error;
std::size_t code_units_size;
std::array<C, 4> code_units;
};
struct unicode_detail {
// codepoint related
static constexpr char32_t last_code_point = 0x10FFFF;
static constexpr char32_t first_lead_surrogate = 0xD800;
static constexpr char32_t last_lead_surrogate = 0xDBFF;
static constexpr char32_t first_trail_surrogate = 0xDC00;
static constexpr char32_t last_trail_surrogate = 0xDFFF;
static constexpr char32_t first_surrogate = first_lead_surrogate;
static constexpr char32_t last_surrogate = last_trail_surrogate;
static constexpr bool is_lead_surrogate(char32_t u) {
return u >= first_lead_surrogate && u <= last_lead_surrogate;
}
static constexpr bool is_trail_surrogate(char32_t u) {
return u >= first_trail_surrogate && u <= last_trail_surrogate;
}
static constexpr bool is_surrogate(char32_t u) {
return u >= first_surrogate && u <= last_surrogate;
}
// utf8 related
static constexpr auto last_1byte_value = 0x7Fu;
static constexpr auto last_2byte_value = 0x7FFu;
static constexpr auto last_3byte_value = 0xFFFFu;
static constexpr auto start_2byte_mask = 0x80u;
static constexpr auto start_3byte_mask = 0xE0u;
static constexpr auto start_4byte_mask = 0xF0u;
static constexpr auto continuation_mask = 0xC0u;
static constexpr auto continuation_signature = 0x80u;
static constexpr bool is_invalid(unsigned char b) {
return b == 0xC0 || b == 0xC1 || b > 0xF4;
}
static constexpr bool is_continuation(unsigned char b) {
return (b & unicode_detail::continuation_mask) == unicode_detail::continuation_signature;
}
static constexpr bool is_overlong(char32_t u, std::size_t bytes) {
return u <= unicode_detail::last_1byte_value || (u <= unicode_detail::last_2byte_value && bytes > 2)
|| (u <= unicode_detail::last_3byte_value && bytes > 3);
}
static constexpr int sequence_length(unsigned char b) {
return (b & start_2byte_mask) == 0 ? 1
: (b & start_3byte_mask) != start_3byte_mask ? 2
: (b & start_4byte_mask) != start_4byte_mask ? 3
: 4;
}
static constexpr char32_t decode(unsigned char b0, unsigned char b1) {
return (static_cast<char32_t>((b0 & 0x1Fu) << 6u) | static_cast<char32_t>(b1 & 0x3Fu));
}
static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2) {
return static_cast<char32_t>((b0 & 0x0Fu) << 12u) | static_cast<char32_t>((b1 & 0x3Fu) << 6u) | static_cast<char32_t>(b2 & 0x3Fu);
}
static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3) {
return static_cast<char32_t>(static_cast<char32_t>((b0 & 0x07u) << 18u) | static_cast<char32_t>((b1 & 0x3F) << 12)
| static_cast<char32_t>((b2 & 0x3Fu) << 6u) | static_cast<char32_t>(b3 & 0x3Fu));
}
// utf16 related
static constexpr char32_t last_bmp_value = 0xFFFF;
static constexpr char32_t normalizing_value = 0x10000;
static constexpr int lead_surrogate_bitmask = 0xFFC00;
static constexpr int trail_surrogate_bitmask = 0x3FF;
static constexpr int lead_shifted_bits = 10;
static constexpr char32_t replacement = 0xFFFD;
static char32_t combine_surrogates(char16_t lead, char16_t trail) {
auto hi = lead - first_lead_surrogate;
auto lo = trail - first_trail_surrogate;
return normalizing_value + ((hi << lead_shifted_bits) | lo);
}
};
inline encoded_result<char> code_point_to_utf8(char32_t codepoint) {
encoded_result<char> er;
er.error = error_code::ok;
if (codepoint <= unicode_detail::last_1byte_value) {
er.code_units_size = 1;
er.code_units = std::array<char, 4> { { static_cast<char>(codepoint) } };
}
else if (codepoint <= unicode_detail::last_2byte_value) {
er.code_units_size = 2;
er.code_units = std::array<char, 4> { {
static_cast<char>(0xC0 | ((codepoint & 0x7C0) >> 6)),
static_cast<char>(0x80 | (codepoint & 0x3F)),
} };
}
else if (codepoint <= unicode_detail::last_3byte_value) {
er.code_units_size = 3;
er.code_units = std::array<char, 4> { {
static_cast<char>(0xE0 | ((codepoint & 0xF000) >> 12)),
static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)),
static_cast<char>(0x80 | (codepoint & 0x3F)),
} };
}
else {
er.code_units_size = 4;
er.code_units = std::array<char, 4> { {
static_cast<char>(0xF0 | ((codepoint & 0x1C0000) >> 18)),
static_cast<char>(0x80 | ((codepoint & 0x3F000) >> 12)),
static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)),
static_cast<char>(0x80 | (codepoint & 0x3F)),
} };
}
return er;
}
inline encoded_result<char16_t> code_point_to_utf16(char32_t codepoint) {
encoded_result<char16_t> er;
if (codepoint <= unicode_detail::last_bmp_value) {
er.code_units_size = 1;
er.code_units = std::array<char16_t, 4> { { static_cast<char16_t>(codepoint) } };
er.error = error_code::ok;
}
else {
auto normal = codepoint - unicode_detail::normalizing_value;
auto lead = unicode_detail::first_lead_surrogate + ((normal & unicode_detail::lead_surrogate_bitmask) >> unicode_detail::lead_shifted_bits);
auto trail = unicode_detail::first_trail_surrogate + (normal & unicode_detail::trail_surrogate_bitmask);
er.code_units = std::array<char16_t, 4> { { static_cast<char16_t>(lead), static_cast<char16_t>(trail) } };
er.code_units_size = 2;
er.error = error_code::ok;
}
return er;
}
inline encoded_result<char32_t> code_point_to_utf32(char32_t codepoint) {
encoded_result<char32_t> er;
er.code_units_size = 1;
er.code_units[0] = codepoint;
er.error = error_code::ok;
return er;
}
template <typename It>
inline decoded_result<It> utf8_to_code_point(It it, It last) {
decoded_result<It> dr;
if (it == last) {
dr.next = it;
dr.error = error_code::sequence_too_short;
return dr;
}
unsigned char b0 = static_cast<unsigned char>(*it);
std::size_t length = static_cast<std::size_t>(unicode_detail::sequence_length(b0));
if (length == 1) {
dr.codepoint = static_cast<char32_t>(b0);
dr.error = error_code::ok;
++it;
dr.next = it;
return dr;
}
if (unicode_detail::is_invalid(b0) || unicode_detail::is_continuation(b0)) {
dr.error = error_code::invalid_code_unit;
dr.next = it;
return dr;
}
++it;
std::array<unsigned char, 4> b;
b[0] = b0;
for (std::size_t i = 1; i < length; ++i) {
b[i] = static_cast<unsigned char>(*it);
if (!unicode_detail::is_continuation(b[i])) {
dr.error = error_code::invalid_code_unit;
dr.next = it;
return dr;
}
++it;
}
char32_t decoded;
switch (length) {
case 2:
decoded = unicode_detail::decode(b[0], b[1]);
break;
case 3:
decoded = unicode_detail::decode(b[0], b[1], b[2]);
break;
default:
decoded = unicode_detail::decode(b[0], b[1], b[2], b[3]);
break;
}
if (unicode_detail::is_overlong(decoded, length)) {
dr.error = error_code::overlong_sequence;
return dr;
}
if (unicode_detail::is_surrogate(decoded) || decoded > unicode_detail::last_code_point) {
dr.error = error_code::invalid_code_point;
return dr;
}
// then everything is fine
dr.codepoint = decoded;
dr.error = error_code::ok;
dr.next = it;
return dr;
}
template <typename It>
inline decoded_result<It> utf16_to_code_point(It it, It last) {
decoded_result<It> dr;
if (it == last) {
dr.next = it;
dr.error = error_code::sequence_too_short;
return dr;
}
char16_t lead = static_cast<char16_t>(*it);
if (!unicode_detail::is_surrogate(lead)) {
++it;
dr.codepoint = static_cast<char32_t>(lead);
dr.next = it;
dr.error = error_code::ok;
return dr;
}
if (!unicode_detail::is_lead_surrogate(lead)) {
dr.error = error_code::invalid_leading_surrogate;
dr.next = it;
return dr;
}
++it;
auto trail = *it;
if (!unicode_detail::is_trail_surrogate(trail)) {
dr.error = error_code::invalid_trailing_surrogate;
dr.next = it;
return dr;
}
dr.codepoint = unicode_detail::combine_surrogates(lead, trail);
dr.next = ++it;
dr.error = error_code::ok;
return dr;
}
template <typename It>
inline decoded_result<It> utf32_to_code_point(It it, It last) {
decoded_result<It> dr;
if (it == last) {
dr.next = it;
dr.error = error_code::sequence_too_short;
return dr;
}
dr.codepoint = static_cast<char32_t>(*it);
dr.next = ++it;
dr.error = error_code::ok;
return dr;
}
} // namespace unicode
} // namespace sol
#pragma once
#include <sol/string_view.hpp>
#include <array>
#include <cstring>
namespace sol {
// Everything here was lifted pretty much straight out of
// ogonek, because fuck figuring it out=
namespace unicode {
enum class error_code {
ok = 0,
invalid_code_point,
invalid_code_unit,
invalid_leading_surrogate,
invalid_trailing_surrogate,
sequence_too_short,
overlong_sequence,
};
inline const string_view& to_string(error_code ec) {
static const string_view storage[7] = { "ok",
"invalid code points",
"invalid code unit",
"invalid leading surrogate",
"invalid trailing surrogate",
"sequence too short",
"overlong sequence" };
return storage[static_cast<std::size_t>(ec)];
}
template <typename It>
struct decoded_result {
error_code error;
char32_t codepoint;
It next;
};
template <typename C>
struct encoded_result {
error_code error;
std::size_t code_units_size;
std::array<C, 4> code_units;
};
struct unicode_detail {
// codepoint related
static constexpr char32_t last_code_point = 0x10FFFF;
static constexpr char32_t first_lead_surrogate = 0xD800;
static constexpr char32_t last_lead_surrogate = 0xDBFF;
static constexpr char32_t first_trail_surrogate = 0xDC00;
static constexpr char32_t last_trail_surrogate = 0xDFFF;
static constexpr char32_t first_surrogate = first_lead_surrogate;
static constexpr char32_t last_surrogate = last_trail_surrogate;
static constexpr bool is_lead_surrogate(char32_t u) {
return u >= first_lead_surrogate && u <= last_lead_surrogate;
}
static constexpr bool is_trail_surrogate(char32_t u) {
return u >= first_trail_surrogate && u <= last_trail_surrogate;
}
static constexpr bool is_surrogate(char32_t u) {
return u >= first_surrogate && u <= last_surrogate;
}
// utf8 related
static constexpr auto last_1byte_value = 0x7Fu;
static constexpr auto last_2byte_value = 0x7FFu;
static constexpr auto last_3byte_value = 0xFFFFu;
static constexpr auto start_2byte_mask = 0x80u;
static constexpr auto start_3byte_mask = 0xE0u;
static constexpr auto start_4byte_mask = 0xF0u;
static constexpr auto continuation_mask = 0xC0u;
static constexpr auto continuation_signature = 0x80u;
static constexpr bool is_invalid(unsigned char b) {
return b == 0xC0 || b == 0xC1 || b > 0xF4;
}
static constexpr bool is_continuation(unsigned char b) {
return (b & unicode_detail::continuation_mask) == unicode_detail::continuation_signature;
}
static constexpr bool is_overlong(char32_t u, std::size_t bytes) {
return u <= unicode_detail::last_1byte_value || (u <= unicode_detail::last_2byte_value && bytes > 2)
|| (u <= unicode_detail::last_3byte_value && bytes > 3);
}
static constexpr int sequence_length(unsigned char b) {
return (b & start_2byte_mask) == 0 ? 1
: (b & start_3byte_mask) != start_3byte_mask ? 2
: (b & start_4byte_mask) != start_4byte_mask ? 3
: 4;
}
static constexpr char32_t decode(unsigned char b0, unsigned char b1) {
return (static_cast<char32_t>((b0 & 0x1Fu) << 6u) | static_cast<char32_t>(b1 & 0x3Fu));
}
static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2) {
return static_cast<char32_t>((b0 & 0x0Fu) << 12u) | static_cast<char32_t>((b1 & 0x3Fu) << 6u) | static_cast<char32_t>(b2 & 0x3Fu);
}
static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3) {
return static_cast<char32_t>(static_cast<char32_t>((b0 & 0x07u) << 18u) | static_cast<char32_t>((b1 & 0x3F) << 12)
| static_cast<char32_t>((b2 & 0x3Fu) << 6u) | static_cast<char32_t>(b3 & 0x3Fu));
}
// utf16 related
static constexpr char32_t last_bmp_value = 0xFFFF;
static constexpr char32_t normalizing_value = 0x10000;
static constexpr int lead_surrogate_bitmask = 0xFFC00;
static constexpr int trail_surrogate_bitmask = 0x3FF;
static constexpr int lead_shifted_bits = 10;
static constexpr char32_t replacement = 0xFFFD;
static char32_t combine_surrogates(char16_t lead, char16_t trail) {
auto hi = lead - first_lead_surrogate;
auto lo = trail - first_trail_surrogate;
return normalizing_value + ((hi << lead_shifted_bits) | lo);
}
};
inline encoded_result<char> code_point_to_utf8(char32_t codepoint) {
encoded_result<char> er;
er.error = error_code::ok;
if (codepoint <= unicode_detail::last_1byte_value) {
er.code_units_size = 1;
er.code_units = std::array<char, 4> { { static_cast<char>(codepoint) } };
}
else if (codepoint <= unicode_detail::last_2byte_value) {
er.code_units_size = 2;
er.code_units = std::array<char, 4> { {
static_cast<char>(0xC0 | ((codepoint & 0x7C0) >> 6)),
static_cast<char>(0x80 | (codepoint & 0x3F)),
} };
}
else if (codepoint <= unicode_detail::last_3byte_value) {
er.code_units_size = 3;
er.code_units = std::array<char, 4> { {
static_cast<char>(0xE0 | ((codepoint & 0xF000) >> 12)),
static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)),
static_cast<char>(0x80 | (codepoint & 0x3F)),
} };
}
else {
er.code_units_size = 4;
er.code_units = std::array<char, 4> { {
static_cast<char>(0xF0 | ((codepoint & 0x1C0000) >> 18)),
static_cast<char>(0x80 | ((codepoint & 0x3F000) >> 12)),
static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)),
static_cast<char>(0x80 | (codepoint & 0x3F)),
} };
}
return er;
}
inline encoded_result<char16_t> code_point_to_utf16(char32_t codepoint) {
encoded_result<char16_t> er;
if (codepoint <= unicode_detail::last_bmp_value) {
er.code_units_size = 1;
er.code_units = std::array<char16_t, 4> { { static_cast<char16_t>(codepoint) } };
er.error = error_code::ok;
}
else {
auto normal = codepoint - unicode_detail::normalizing_value;
auto lead = unicode_detail::first_lead_surrogate + ((normal & unicode_detail::lead_surrogate_bitmask) >> unicode_detail::lead_shifted_bits);
auto trail = unicode_detail::first_trail_surrogate + (normal & unicode_detail::trail_surrogate_bitmask);
er.code_units = std::array<char16_t, 4> { { static_cast<char16_t>(lead), static_cast<char16_t>(trail) } };
er.code_units_size = 2;
er.error = error_code::ok;
}
return er;
}
inline encoded_result<char32_t> code_point_to_utf32(char32_t codepoint) {
encoded_result<char32_t> er;
er.code_units_size = 1;
er.code_units[0] = codepoint;
er.error = error_code::ok;
return er;
}
template <typename It>
inline decoded_result<It> utf8_to_code_point(It it, It last) {
decoded_result<It> dr;
if (it == last) {
dr.next = it;
dr.error = error_code::sequence_too_short;
return dr;
}
unsigned char b0 = static_cast<unsigned char>(*it);
std::size_t length = static_cast<std::size_t>(unicode_detail::sequence_length(b0));
if (length == 1) {
dr.codepoint = static_cast<char32_t>(b0);
dr.error = error_code::ok;
++it;
dr.next = it;
return dr;
}
if (unicode_detail::is_invalid(b0) || unicode_detail::is_continuation(b0)) {
dr.error = error_code::invalid_code_unit;
dr.next = it;
return dr;
}
++it;
std::array<unsigned char, 4> b;
b[0] = b0;
for (std::size_t i = 1; i < length; ++i) {
b[i] = static_cast<unsigned char>(*it);
if (!unicode_detail::is_continuation(b[i])) {
dr.error = error_code::invalid_code_unit;
dr.next = it;
return dr;
}
++it;
}
char32_t decoded;
switch (length) {
case 2:
decoded = unicode_detail::decode(b[0], b[1]);
break;
case 3:
decoded = unicode_detail::decode(b[0], b[1], b[2]);
break;
default:
decoded = unicode_detail::decode(b[0], b[1], b[2], b[3]);
break;
}
if (unicode_detail::is_overlong(decoded, length)) {
dr.error = error_code::overlong_sequence;
return dr;
}
if (unicode_detail::is_surrogate(decoded) || decoded > unicode_detail::last_code_point) {
dr.error = error_code::invalid_code_point;
return dr;
}
// then everything is fine
dr.codepoint = decoded;
dr.error = error_code::ok;
dr.next = it;
return dr;
}
template <typename It>
inline decoded_result<It> utf16_to_code_point(It it, It last) {
decoded_result<It> dr;
if (it == last) {
dr.next = it;
dr.error = error_code::sequence_too_short;
return dr;
}
char16_t lead = static_cast<char16_t>(*it);
if (!unicode_detail::is_surrogate(lead)) {
++it;
dr.codepoint = static_cast<char32_t>(lead);
dr.next = it;
dr.error = error_code::ok;
return dr;
}
if (!unicode_detail::is_lead_surrogate(lead)) {
dr.error = error_code::invalid_leading_surrogate;
dr.next = it;
return dr;
}
++it;
auto trail = *it;
if (!unicode_detail::is_trail_surrogate(trail)) {
dr.error = error_code::invalid_trailing_surrogate;
dr.next = it;
return dr;
}
dr.codepoint = unicode_detail::combine_surrogates(lead, trail);
dr.next = ++it;
dr.error = error_code::ok;
return dr;
}
template <typename It>
inline decoded_result<It> utf32_to_code_point(It it, It last) {
decoded_result<It> dr;
if (it == last) {
dr.next = it;
dr.error = error_code::sequence_too_short;
return dr;
}
dr.codepoint = static_cast<char32_t>(*it);
dr.next = ++it;
dr.error = error_code::ok;
return dr;
}
} // namespace unicode
} // namespace sol

@ -1,240 +1,240 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_UNIQUE_USERTYPE_TRAITS_HPP
#define SOL_UNIQUE_USERTYPE_TRAITS_HPP
#include <sol/base_traits.hpp>
#include <sol/pointer_like.hpp>
#include <sol/forward.hpp>
#include <memory>
namespace sol {
namespace detail {
template <typename T>
struct unique_fallback {
using SOL_INTERNAL_UNSPECIALIZED_MARKER_ = int;
};
template <typename T>
struct unique_fallback<std::shared_ptr<T>> {
private:
using pointer = typename std::pointer_traits<std::shared_ptr<T>>::element_type*;
public:
// rebind is non-void
// if and only if unique usertype
// is cast-capable
template <typename X>
using rebind_actual_type = std::shared_ptr<X>;
static bool is_null(lua_State*, const std::shared_ptr<T>& p) noexcept {
return p == nullptr;
}
static pointer get(lua_State*, const std::shared_ptr<T>& p) noexcept {
return p.get();
}
};
template <typename T, typename D>
struct unique_fallback<std::unique_ptr<T, D>> {
private:
using pointer = typename std::unique_ptr<T, D>::pointer;
public:
static bool is_null(lua_State*, const std::unique_ptr<T, D>& p) noexcept {
return p == nullptr;
}
static pointer get(lua_State*, const std::unique_ptr<T, D>& p) noexcept {
return p.get();
}
};
} // namespace detail
namespace meta { namespace meta_detail {
template <typename T, typename = void>
struct unique_actual_type;
template <typename T>
struct unique_actual_type<T, meta::void_t<typename T::actual_type>> {
using type = typename T::actual_type;
};
template <typename T, typename... Rest, template <typename...> class Templ>
struct unique_actual_type<Templ<T, Rest...>> {
using type = T;
};
}} // namespace meta::meta_detail
template <typename T>
using unique_usertype_actual_t = typename meta::meta_detail::unique_actual_type<unique_usertype_traits<T>>::type;
namespace meta { namespace meta_detail {
template <typename T>
using value_test_t = decltype(T::value);
template <typename T>
using type_test_t = typename T::type;
template <typename T>
using type_element_type_t = typename T::element_type;
template <typename T, typename = void>
struct unique_element_type {
using type = typename std::pointer_traits<typename unique_actual_type<T>::type>::element_type;
};
template <typename T>
struct unique_element_type<T, std::enable_if_t<meta::is_detected_v<type_element_type_t, T>>> {
using type = typename T::element_type;
};
template <typename T>
struct unique_element_type<T, std::enable_if_t<meta::is_detected_v<type_test_t, T>>> {
using type = typename T::type;
};
template <typename T, typename = void>
struct unique_valid : std::integral_constant<bool, !has_internal_marker_v<T>> { };
template <typename T>
struct unique_valid<T, meta::void_t<decltype(T::value)>> : std::integral_constant<bool, T::value> { };
}} // namespace meta::meta_detail
template <typename T>
using unique_usertype_element_t = typename meta::meta_detail::unique_element_type<unique_usertype_traits<T>>::type;
template <typename T, typename Element = void>
using unique_usertype_rebind_actual_t = typename unique_usertype_traits<T>::template rebind_actual_type<Element>;
template <typename T>
struct unique_usertype_traits : public detail::unique_fallback<T> { };
template <typename T>
struct is_unique_usertype : std::integral_constant<bool, meta::meta_detail::unique_valid<unique_usertype_traits<T>>::value> { };
template <typename T>
inline constexpr bool is_unique_usertype_v = is_unique_usertype<T>::value;
namespace meta { namespace meta_detail {
template <typename T>
using adl_sol_lua_check_access_test_t
= decltype(sol_lua_check_access(types<T>(), static_cast<lua_State*>(nullptr), -1, std::declval<stack::record&>()));
template <typename T>
inline constexpr bool is_adl_sol_lua_check_access_v = meta::is_detected_v<adl_sol_lua_check_access_test_t, T>;
template <typename T>
using unique_usertype_get_with_state_test_t
= decltype(unique_usertype_traits<T>::get(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<T>>()));
template <typename T>
inline constexpr bool unique_usertype_get_with_state_v = meta::is_detected_v<unique_usertype_get_with_state_test_t, T>;
template <typename T>
using unique_usertype_is_null_with_state_test_t
= decltype(unique_usertype_traits<T>::is_null(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<T>>()));
template <typename T>
inline constexpr bool unique_usertype_is_null_with_state_v = meta::is_detected_v<unique_usertype_is_null_with_state_test_t, T>;
}} // namespace meta::meta_detail
namespace detail {
template <typename T>
constexpr bool unique_is_null_noexcept() noexcept {
if constexpr (meta::meta_detail::unique_usertype_is_null_with_state_v<std::remove_cv_t<T>>) {
return noexcept(
unique_usertype_traits<T>::is_null(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>()));
}
else {
return noexcept(unique_usertype_traits<T>::is_null(std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>()));
}
}
template <typename T>
bool unique_is_null(lua_State* L_, T& value_) noexcept(unique_is_null_noexcept<std::remove_cv_t<T>>()) {
using Tu = std::remove_cv_t<T>;
if constexpr (meta::meta_detail::unique_usertype_is_null_with_state_v<Tu>) {
return unique_usertype_traits<Tu>::is_null(L_, value_);
}
else {
return unique_usertype_traits<Tu>::is_null(value_);
}
}
template <typename T>
constexpr bool unique_get_noexcept() noexcept {
if constexpr (meta::meta_detail::unique_usertype_get_with_state_v<std::remove_cv_t<T>>) {
return noexcept(
unique_usertype_traits<T>::get(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>()));
}
else {
return noexcept(unique_usertype_traits<T>::get(std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>()));
}
}
template <typename T>
auto unique_get(lua_State* L_, T& value_) noexcept(unique_get_noexcept<std::remove_cv_t<T>>()) {
using Tu = std::remove_cv_t<T>;
if constexpr (meta::meta_detail::unique_usertype_get_with_state_v<Tu>) {
return unique_usertype_traits<Tu>::get(L_, value_);
}
else {
return unique_usertype_traits<Tu>::get(value_);
}
}
} // namespace detail
namespace meta { namespace meta_detail {
template <typename T, typename Element = void>
using is_rebind_actual_type_test_t = typename T::template rebind_actual_type<Element>;
template <typename T, typename Element = void>
using is_rebind_actual_type = meta::is_detected<is_rebind_actual_type_test_t, T, Element>;
template <typename T, typename Element = void>
inline constexpr bool is_rebind_actual_type_v = is_rebind_actual_type<T, Element>::value;
template <typename T, typename Element, bool = is_rebind_actual_type_v<T, Element>>
struct is_actual_type_rebindable_for_test : std::false_type { };
template <typename T, typename Element>
struct is_actual_type_rebindable_for_test<T, Element, true>
: std::integral_constant<bool, !std::is_void_v<typename T::template rebind_actual_type<Element>>> { };
}} // namespace meta::meta_detail
template <typename T, typename Element = void>
using is_actual_type_rebindable_for = typename meta::meta_detail::is_actual_type_rebindable_for_test<unique_usertype_traits<T>, Element>::type;
template <typename T, typename Element = void>
inline constexpr bool is_actual_type_rebindable_for_v = is_actual_type_rebindable_for<T, Element>::value;
} // namespace sol
#endif // SOL_UNIQUE_USERTYPE_TRAITS_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_UNIQUE_USERTYPE_TRAITS_HPP
#define SOL_UNIQUE_USERTYPE_TRAITS_HPP
#include <sol/base_traits.hpp>
#include <sol/pointer_like.hpp>
#include <sol/forward.hpp>
#include <memory>
namespace sol {
namespace detail {
template <typename T>
struct unique_fallback {
using SOL_INTERNAL_UNSPECIALIZED_MARKER_ = int;
};
template <typename T>
struct unique_fallback<std::shared_ptr<T>> {
private:
using pointer = typename std::pointer_traits<std::shared_ptr<T>>::element_type*;
public:
// rebind is non-void
// if and only if unique usertype
// is cast-capable
template <typename X>
using rebind_actual_type = std::shared_ptr<X>;
static bool is_null(lua_State*, const std::shared_ptr<T>& p) noexcept {
return p == nullptr;
}
static pointer get(lua_State*, const std::shared_ptr<T>& p) noexcept {
return p.get();
}
};
template <typename T, typename D>
struct unique_fallback<std::unique_ptr<T, D>> {
private:
using pointer = typename std::unique_ptr<T, D>::pointer;
public:
static bool is_null(lua_State*, const std::unique_ptr<T, D>& p) noexcept {
return p == nullptr;
}
static pointer get(lua_State*, const std::unique_ptr<T, D>& p) noexcept {
return p.get();
}
};
} // namespace detail
namespace meta { namespace meta_detail {
template <typename T, typename = void>
struct unique_actual_type;
template <typename T>
struct unique_actual_type<T, meta::void_t<typename T::actual_type>> {
using type = typename T::actual_type;
};
template <typename T, typename... Rest, template <typename...> class Templ>
struct unique_actual_type<Templ<T, Rest...>> {
using type = T;
};
}} // namespace meta::meta_detail
template <typename T>
using unique_usertype_actual_t = typename meta::meta_detail::unique_actual_type<unique_usertype_traits<T>>::type;
namespace meta { namespace meta_detail {
template <typename T>
using value_test_t = decltype(T::value);
template <typename T>
using type_test_t = typename T::type;
template <typename T>
using type_element_type_t = typename T::element_type;
template <typename T, typename = void>
struct unique_element_type {
using type = typename std::pointer_traits<typename unique_actual_type<T>::type>::element_type;
};
template <typename T>
struct unique_element_type<T, std::enable_if_t<meta::is_detected_v<type_element_type_t, T>>> {
using type = typename T::element_type;
};
template <typename T>
struct unique_element_type<T, std::enable_if_t<meta::is_detected_v<type_test_t, T>>> {
using type = typename T::type;
};
template <typename T, typename = void>
struct unique_valid : std::integral_constant<bool, !has_internal_marker_v<T>> { };
template <typename T>
struct unique_valid<T, meta::void_t<decltype(T::value)>> : std::integral_constant<bool, T::value> { };
}} // namespace meta::meta_detail
template <typename T>
using unique_usertype_element_t = typename meta::meta_detail::unique_element_type<unique_usertype_traits<T>>::type;
template <typename T, typename Element = void>
using unique_usertype_rebind_actual_t = typename unique_usertype_traits<T>::template rebind_actual_type<Element>;
template <typename T>
struct unique_usertype_traits : public detail::unique_fallback<T> { };
template <typename T>
struct is_unique_usertype : std::integral_constant<bool, meta::meta_detail::unique_valid<unique_usertype_traits<T>>::value> { };
template <typename T>
inline constexpr bool is_unique_usertype_v = is_unique_usertype<T>::value;
namespace meta { namespace meta_detail {
template <typename T>
using adl_sol_lua_check_access_test_t
= decltype(sol_lua_check_access(types<T>(), static_cast<lua_State*>(nullptr), -1, std::declval<stack::record&>()));
template <typename T>
inline constexpr bool is_adl_sol_lua_check_access_v = meta::is_detected_v<adl_sol_lua_check_access_test_t, T>;
template <typename T>
using unique_usertype_get_with_state_test_t
= decltype(unique_usertype_traits<T>::get(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<T>>()));
template <typename T>
inline constexpr bool unique_usertype_get_with_state_v = meta::is_detected_v<unique_usertype_get_with_state_test_t, T>;
template <typename T>
using unique_usertype_is_null_with_state_test_t
= decltype(unique_usertype_traits<T>::is_null(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<T>>()));
template <typename T>
inline constexpr bool unique_usertype_is_null_with_state_v = meta::is_detected_v<unique_usertype_is_null_with_state_test_t, T>;
}} // namespace meta::meta_detail
namespace detail {
template <typename T>
constexpr bool unique_is_null_noexcept() noexcept {
if constexpr (meta::meta_detail::unique_usertype_is_null_with_state_v<std::remove_cv_t<T>>) {
return noexcept(
unique_usertype_traits<T>::is_null(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>()));
}
else {
return noexcept(unique_usertype_traits<T>::is_null(std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>()));
}
}
template <typename T>
bool unique_is_null(lua_State* L_, T& value_) noexcept(unique_is_null_noexcept<std::remove_cv_t<T>>()) {
using Tu = std::remove_cv_t<T>;
if constexpr (meta::meta_detail::unique_usertype_is_null_with_state_v<Tu>) {
return unique_usertype_traits<Tu>::is_null(L_, value_);
}
else {
return unique_usertype_traits<Tu>::is_null(value_);
}
}
template <typename T>
constexpr bool unique_get_noexcept() noexcept {
if constexpr (meta::meta_detail::unique_usertype_get_with_state_v<std::remove_cv_t<T>>) {
return noexcept(
unique_usertype_traits<T>::get(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>()));
}
else {
return noexcept(unique_usertype_traits<T>::get(std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>()));
}
}
template <typename T>
auto unique_get(lua_State* L_, T& value_) noexcept(unique_get_noexcept<std::remove_cv_t<T>>()) {
using Tu = std::remove_cv_t<T>;
if constexpr (meta::meta_detail::unique_usertype_get_with_state_v<Tu>) {
return unique_usertype_traits<Tu>::get(L_, value_);
}
else {
return unique_usertype_traits<Tu>::get(value_);
}
}
} // namespace detail
namespace meta { namespace meta_detail {
template <typename T, typename Element = void>
using is_rebind_actual_type_test_t = typename T::template rebind_actual_type<Element>;
template <typename T, typename Element = void>
using is_rebind_actual_type = meta::is_detected<is_rebind_actual_type_test_t, T, Element>;
template <typename T, typename Element = void>
inline constexpr bool is_rebind_actual_type_v = is_rebind_actual_type<T, Element>::value;
template <typename T, typename Element, bool = is_rebind_actual_type_v<T, Element>>
struct is_actual_type_rebindable_for_test : std::false_type { };
template <typename T, typename Element>
struct is_actual_type_rebindable_for_test<T, Element, true>
: std::integral_constant<bool, !std::is_void_v<typename T::template rebind_actual_type<Element>>> { };
}} // namespace meta::meta_detail
template <typename T, typename Element = void>
using is_actual_type_rebindable_for = typename meta::meta_detail::is_actual_type_rebindable_for_test<unique_usertype_traits<T>, Element>::type;
template <typename T, typename Element = void>
inline constexpr bool is_actual_type_rebindable_for_v = is_actual_type_rebindable_for<T, Element>::value;
} // namespace sol
#endif // SOL_UNIQUE_USERTYPE_TRAITS_HPP

@ -1,61 +1,61 @@
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_USERTYPE_TRAITS_HPP
#define SOL_USERTYPE_TRAITS_HPP
#include <sol/demangle.hpp>
namespace sol {
template <typename T>
struct usertype_traits {
static const std::string& name() {
static const std::string& n = detail::short_demangle<T>();
return n;
}
static const std::string& qualified_name() {
static const std::string& q_n = detail::demangle<T>();
return q_n;
}
static const std::string& metatable() {
static const std::string m = std::string("sol.").append(detail::demangle<T>());
return m;
}
static const std::string& user_metatable() {
static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user");
return u_m;
}
static const std::string& user_gc_metatable() {
static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB");
return u_g_m;
}
static const std::string& gc_table() {
static const std::string g_t = std::string("sol.").append(detail::demangle<T>()).append(".\xE2\x99\xBB");
return g_t;
}
};
} // namespace sol
#endif // SOL_USERTYPE_TRAITS_HPP
// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_USERTYPE_TRAITS_HPP
#define SOL_USERTYPE_TRAITS_HPP
#include <sol/demangle.hpp>
namespace sol {
template <typename T>
struct usertype_traits {
static const std::string& name() {
static const std::string& n = detail::short_demangle<T>();
return n;
}
static const std::string& qualified_name() {
static const std::string& q_n = detail::demangle<T>();
return q_n;
}
static const std::string& metatable() {
static const std::string m = std::string("sol.").append(detail::demangle<T>());
return m;
}
static const std::string& user_metatable() {
static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user");
return u_m;
}
static const std::string& user_gc_metatable() {
static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB");
return u_g_m;
}
static const std::string& gc_table() {
static const std::string g_t = std::string("sol.").append(detail::demangle<T>()).append(".\xE2\x99\xBB");
return g_t;
}
};
} // namespace sol
#endif // SOL_USERTYPE_TRAITS_HPP

@ -1,71 +1,71 @@
-------------------------------------------------------------------------------
-- Coroutine Manipulation.
-- The operations related to coroutines comprise a sub-library of the basic library
-- and come inside the table coroutine.
-- See http://www.lua.org/manual/5.1/manual.html#2.11 for a general description of coroutines.
-- @module coroutine
-------------------------------------------------------------------------------
-- Creates a new coroutine, with body `f`. `f` must be a Lua
-- function. Returns this new coroutine, an object with type `"thread"`.
-- @function [parent=#coroutine] create
-- @param f a function used as coroutine body.
-- @return #thread a new coroutine.
-------------------------------------------------------------------------------
-- Starts or continues the execution of coroutine `co`. The first time
-- you resume a coroutine, it starts running its body. The values `val1`,
-- ... are passed as the arguments to the body function. If the coroutine
-- has yielded, `resume` restarts it; the values `val1`, ... are passed
-- as the results from the yield.
--
-- If the coroutine runs without any errors, `resume` returns true plus any
-- values passed to `yield` (if the coroutine yields) or any values returned
-- by the body function (if the coroutine terminates). If there is any error,
-- `resume` returns false plus the error message.
-- @function [parent=#coroutine] resume
-- @param #thread co coroutine to start or resume.
-- @param ... arguments passed to the body function or as result of yield call.
-- @return #boolean true plus any values passed to `yield` (if the coroutine yields) or any values returned
-- by the body function (if the coroutine terminates)
-- @return #boolean false plus an error message.
-------------------------------------------------------------------------------
-- Returns the running coroutine, or nil when called by the main thread.
-- @function [parent=#coroutine] running
-- @return #thread the running coroutine, or nil when called by the main thread.
-------------------------------------------------------------------------------
-- Returns the status of coroutine `co`, as a string: `"running"`, if
-- the coroutine is running (that is, it called `status`); `"suspended"`, if
-- the coroutine is suspended in a call to `yield`, or if it has not started
-- running yet; `"normal"` if the coroutine is active but not running (that
-- is, it has resumed another coroutine); and `"dead"` if the coroutine has
-- finished its body function, or if it has stopped with an error.
-- @function [parent=#coroutine] status
-- @param #thread co a coroutine
-- @return #string the status : `"running"`, `"suspended"`, `"normal"` or `"dead"`.
-------------------------------------------------------------------------------
-- Creates a new coroutine, with body `f`. `f` must be a Lua
-- function. Returns a function that resumes the coroutine each time it is
-- called. Any arguments passed to the function behave as the extra arguments to
-- `resume`. Returns the same values returned by `resume`, except the first
-- boolean. In case of error, propagates the error.
-- @function [parent=#coroutine] wrap
-- @param f a function used as coroutine body.
-- @param ... arguments passed to the body function or as result of yield call.
-- @return Any values passed to `yield` (if the coroutine yields) or any values returned
-- by the body function (if the coroutine terminates).
-------------------------------------------------------------------------------
-- Suspends the execution of the calling coroutine. The coroutine cannot
-- be running a C function, a metamethod, or an iterator. Any arguments to
-- `yield` are passed as extra results to `resume`.
-- @function [parent=#coroutine] yield
-- @param ... arguments passed as extra results to `resume` function.
-- @return Any values passed to the `resume` function.
return nil
-------------------------------------------------------------------------------
-- Coroutine Manipulation.
-- The operations related to coroutines comprise a sub-library of the basic library
-- and come inside the table coroutine.
-- See http://www.lua.org/manual/5.1/manual.html#2.11 for a general description of coroutines.
-- @module coroutine
-------------------------------------------------------------------------------
-- Creates a new coroutine, with body `f`. `f` must be a Lua
-- function. Returns this new coroutine, an object with type `"thread"`.
-- @function [parent=#coroutine] create
-- @param f a function used as coroutine body.
-- @return #thread a new coroutine.
-------------------------------------------------------------------------------
-- Starts or continues the execution of coroutine `co`. The first time
-- you resume a coroutine, it starts running its body. The values `val1`,
-- ... are passed as the arguments to the body function. If the coroutine
-- has yielded, `resume` restarts it; the values `val1`, ... are passed
-- as the results from the yield.
--
-- If the coroutine runs without any errors, `resume` returns true plus any
-- values passed to `yield` (if the coroutine yields) or any values returned
-- by the body function (if the coroutine terminates). If there is any error,
-- `resume` returns false plus the error message.
-- @function [parent=#coroutine] resume
-- @param #thread co coroutine to start or resume.
-- @param ... arguments passed to the body function or as result of yield call.
-- @return #boolean true plus any values passed to `yield` (if the coroutine yields) or any values returned
-- by the body function (if the coroutine terminates)
-- @return #boolean false plus an error message.
-------------------------------------------------------------------------------
-- Returns the running coroutine, or nil when called by the main thread.
-- @function [parent=#coroutine] running
-- @return #thread the running coroutine, or nil when called by the main thread.
-------------------------------------------------------------------------------
-- Returns the status of coroutine `co`, as a string: `"running"`, if
-- the coroutine is running (that is, it called `status`); `"suspended"`, if
-- the coroutine is suspended in a call to `yield`, or if it has not started
-- running yet; `"normal"` if the coroutine is active but not running (that
-- is, it has resumed another coroutine); and `"dead"` if the coroutine has
-- finished its body function, or if it has stopped with an error.
-- @function [parent=#coroutine] status
-- @param #thread co a coroutine
-- @return #string the status : `"running"`, `"suspended"`, `"normal"` or `"dead"`.
-------------------------------------------------------------------------------
-- Creates a new coroutine, with body `f`. `f` must be a Lua
-- function. Returns a function that resumes the coroutine each time it is
-- called. Any arguments passed to the function behave as the extra arguments to
-- `resume`. Returns the same values returned by `resume`, except the first
-- boolean. In case of error, propagates the error.
-- @function [parent=#coroutine] wrap
-- @param f a function used as coroutine body.
-- @param ... arguments passed to the body function or as result of yield call.
-- @return Any values passed to `yield` (if the coroutine yields) or any values returned
-- by the body function (if the coroutine terminates).
-------------------------------------------------------------------------------
-- Suspends the execution of the calling coroutine. The coroutine cannot
-- be running a C function, a metamethod, or an iterator. Any arguments to
-- `yield` are passed as extra results to `resume`.
-- @function [parent=#coroutine] yield
-- @param ... arguments passed as extra results to `resume` function.
-- @return Any values passed to the `resume` function.
return nil

@ -1,269 +1,269 @@
-------------------------------------------------------------------------------
-- Lua global variables.
-- The basic library provides some core functions to Lua.
-- All the preloaded module of Lua are declared here.
-- @module global
------------------------------------------------------------------------------
-- This library provides generic functions for coroutine manipulation.
-- This is a global variable which hold the preloaded @{coroutine} module.
-- @field[parent = #global] coroutine#coroutine coroutine preloaded module
------------------------------------------------------------------------------
-- This library provides generic functions for string manipulation.
-- This is a global variable which hold the preloaded @{string} module.
-- @field[parent = #global] string#string string preloaded module
------------------------------------------------------------------------------
-- This library provides generic functions for table manipulation.
-- This is a global variable which hold the preloaded @{table} module.
-- @field[parent = #global] table#table table preloaded module
------------------------------------------------------------------------------
-- This library is an interface to the standard C math library.
-- This is a global variable which hold the preloaded @{math} module.
-- @field[parent = #global] math#math math preloaded module
------------------------------------------------------------------------------
-- This library is an interface to the standard C math library.
-- This is a global variable which hold the preloaded @{omwutil} module.
-- @field[parent = #global] omwutil#omwutil ou preloaded module
-------------------------------------------------------------------------------
-- Issues an error when the value of its argument `v` is false (i.e.,
-- **nil** or **false**); otherwise, returns all its arguments. `message` is an error
-- message; when absent, it defaults to *"assertion failed!"*.
-- @function [parent=#global] assert
-- @param v if this argument is false an error is issued.
-- @param #string message an error message. defaults value is *"assertion failed"*.
-- @return All its arguments.
-------------------------------------------------------------------------------
-- Terminates the last protected function called and returns `message`
-- as the error message. Function `error` never returns.
--
-- Usually, `error` adds some information about the error position at the
-- beginning of the message. The `level` argument specifies how to get the
-- error position.
-- With level 1 (the default), the error position is where the
-- `error` function was called.
-- Level 2 points the error to where the function
-- that called `error` was called; and so on.
-- Passing a level 0 avoids the addition of error position information to the message.
-- @function [parent=#global] error
-- @param #string message an error message.
-- @param #number level specifies how to get the error position, default value is `1`.
-------------------------------------------------------------------------------
-- If `object` does not have a metatable, returns nil. Otherwise, if the
-- object's metatable has a `"__metatable"` field, returns the associated
-- value. Otherwise, returns the metatable of the given object.
-- @function [parent=#global] getmetatable
-- @param object
-- @return #table the metatable of object.
-------------------------------------------------------------------------------
-- Use to iterate over a table by index.
-- Returns three values: an iterator function, the table `t`, and 0,
-- so that the construction :
--
-- for i,v in ipairs(t) do *body* end
-- will iterate over the pairs (`1,t[1]`), (`2,t[2]`), ..., up to the
-- first integer key absent from the table.
-- @function [parent=#global] ipairs
-- @param #table t a table by index.
-------------------------------------------------------------------------------
-- Allows a program to traverse all fields of a table. Its first argument is
-- a table and its second argument is an index in this table. `next` returns
-- the next index of the table and its associated value.
--
-- When called with nil
-- as its second argument, `next` returns an initial index and its associated
-- value. When called with the last index, or with nil in an empty table, `next`
-- returns nil.
--
-- If the second argument is absent, then it is interpreted as
-- nil. In particular, you can use `next(t)` to check whether a table is empty.
-- The order in which the indices are enumerated is not specified, *even for
-- numeric indices*. (To traverse a table in numeric order, use a numerical
-- for or the `ipairs` function.)
--
-- The behavior of `next` is *undefined* if, during the traversal, you assign
-- any value to a non-existent field in the table. You may however modify
-- existing fields. In particular, you may clear existing fields.
-- @function [parent=#global] next
-- @param #table table table to traverse.
-- @param index initial index.
-------------------------------------------------------------------------------
-- Use to iterate over a table.
-- Returns three values: the `next` function, the table `t`, and nil,
-- so that the construction :
--
-- for k,v in pairs(t) do *body* end
-- will iterate over all key-value pairs of table `t`.
--
-- See function `next` for the caveats of modifying the table during its
-- traversal.
-- @function [parent=#global] pairs
-- @param #table t table to traverse.
-------------------------------------------------------------------------------
-- Calls function `f` with the given arguments in *protected mode*. This
-- means that any error inside `f` is not propagated; instead, `pcall` catches
-- the error and returns a status code. Its first result is the status code (a
-- boolean), which is true if the call succeeds without errors. In such case,
-- `pcall` also returns all results from the call, after this first result. In
-- case of any error, `pcall` returns false plus the error message.
-- @function [parent=#global] pcall
-- @param f function to be call in *protected mode*.
-- @param ... function arguments.
-- @return #boolean true plus the result of `f` function if its call succeeds without errors.
-- @return #boolean,#string false plus the error message in case of any error.
-------------------------------------------------------------------------------
-- Receives any number of arguments, and prints their values to OpenMW log,
-- using the `tostring` function to convert them to strings. `print` is not
-- intended for formatted output, but only as a quick way to show a value,
-- typically for debugging. For formatted output, use `string.format`.
--
-- @function [parent=#global] print
-- @param ... values to print to `stdout`.
-------------------------------------------------------------------------------
-- Checks whether `v1` is equal to `v2`, without invoking any
-- metamethod. Returns a boolean.
-- @function [parent=#global] rawequal
-- @param v1
-- @param v2
-- @return #boolean true if `v1` is equal to `v2`.
-------------------------------------------------------------------------------
-- Gets the real value of `table[index]`, without invoking any
-- metamethod. `table` must be a table; `index` may be any value.
-- @function [parent=#global] rawget
-- @param #table table
-- @param index may be any value.
-- @return The real value of `table[index]`, without invoking any
-- metamethod.
-------------------------------------------------------------------------------
-- Sets the real value of `table[index]` to `value`, without invoking any
-- metamethod. `table` must be a table, `index` any value different from nil,
-- and `value` any Lua value.
-- This function returns `table`.
-- @function [parent=#global] rawset
-- @param #table table
-- @param index any value different from nil.
-- @param value any Lua value.
-------------------------------------------------------------------------------
-- If `index` is a number, returns all arguments after argument number
-- `index`. Otherwise, `index` must be the string `"#"`, and `select` returns
-- the total number of extra arguments it received.
-- @function [parent=#global] select
-- @param index a number or the string `"#"`
-- @param ...
-------------------------------------------------------------------------------
-- Sets the metatable for the given table. (You cannot change the metatable
-- of other types from Lua, only from C.) If `metatable` is nil, removes the
-- metatable of the given table. If the original metatable has a `"__metatable"`
-- field, raises an error.
-- This function returns `table`.
-- @function [parent=#global] setmetatable
-- @param #table table
-- @param #table metatable
-- @return The first argument `table`.
-------------------------------------------------------------------------------
-- Tries to convert its argument to a number. If the argument is already
-- a number or a string convertible to a number, then `tonumber` returns this
-- number; otherwise, it returns **nil.**
--
-- An optional argument specifies the base to interpret the numeral. The base
-- may be any integer between 2 and 36, inclusive. In bases above 10, the
-- letter '`A`' (in either upper or lower case) represents 10, '`B`' represents
-- 11, and so forth, with '`Z`' representing 35. In base 10 (the default),
-- the number can have a decimal part, as well as an optional exponent part.
-- In other bases, only unsigned integers are accepted.
-- @function [parent=#global] tonumber
-- @param e a number or string to convert to a number.
-- @param #number base the base to interpret the numeral, any integer between 2 and 36.(default is 10).
-- @return #number a number if conversion succeeds else **nil**.
-------------------------------------------------------------------------------
-- Receives an argument of any type and converts it to a string in a
-- reasonable format. For complete control of how numbers are converted, use
-- `string.format`.
--
-- If the metatable of `e` has a `"__tostring"` field, then `tostring` calls
-- the corresponding value with `e` as argument, and uses the result of the
-- call as its result.
-- @function [parent=#global] tostring
-- @param e an argument of any type.
-- @return #string a string in a reasonable format.
-------------------------------------------------------------------------------
-- Returns the type of its only argument, coded as a string. The possible
-- results of this function are "
-- `nil`" (a string, not the value nil), "`number`", "`string`", "`boolean`",
-- "`table`", "`function`", "`thread`", and "`userdata`".
-- @function [parent=#global] type
-- @param v any value.
-- @return #string the type of `v`.
-------------------------------------------------------------------------------
-- Returns the elements from the given table. This function is equivalent to
--
-- return list[i], list[i+1], ..., list[j]
-- except that the above code can be written only for a fixed number of
-- elements. By default, `i` is 1 and `j` is the length of the list, as
-- defined by the length operator.
-- @function [parent=#global] unpack
-- @param #table list a table by index
-- @param i index of first value.
-- @param j index of last value.
-------------------------------------------------------------------------------
-- A global variable (not a function) that holds a string containing the
-- current interpreter version. The current contents of this variable is
-- "`Lua 5.1`".
-- @field [parent = #global] #string _VERSION
-------------------------------------------------------------------------------
-- This function is similar to `pcall`, except that you can set a new
-- error handler.
--
-- `xpcall` calls function `f` in protected mode, using `err` as the error
-- handler. Any error inside `f` is not propagated; instead, `xpcall` catches
-- the error, calls the `err` function with the original error object, and
-- returns a status code. Its first result is the status code (a boolean),
-- which is true if the call succeeds without errors. In this case, `xpcall`
-- also returns all results from the call, after this first result. In case
-- of any error, `xpcall` returns false plus the result from `err`.
-- @function [parent=#global] xpcall
-- @param f function to be call in *protected mode*.
-- @param err function used as error handler.
-- @return #boolean true plus the result of `f` function if its call succeeds without errors.
-- @return #boolean,#string false plus the result of `err` function.
-------------------------------------------------------------------------------
-- Loads the given module.
-- If the requested module is one of the allowed standard libraries
-- (`coroutine`, `math`, `string`, `table`), then returns the library.
-- If it is one of the built-in OpenMW API packages, then returns the package.
-- Otherwise it searches for a Lua source file with such name in OpenMW data folders.
-- For example `require('my_lua_library.something')` will try to open the file
-- `my_lua_library/something.lua`.
--
-- Loading DLLs and precompiled Lua files is intentionally prohibited for reasons
-- of safety and compatibility between different platforms.
--
-- If there is any error loading or running the module, or if it cannot find
-- any loader for the module, then `require` signals an error.
-- @function [parent=#global] require
-- @param #string modname name of module to load.
return nil
-------------------------------------------------------------------------------
-- Lua global variables.
-- The basic library provides some core functions to Lua.
-- All the preloaded module of Lua are declared here.
-- @module global
------------------------------------------------------------------------------
-- This library provides generic functions for coroutine manipulation.
-- This is a global variable which hold the preloaded @{coroutine} module.
-- @field[parent = #global] coroutine#coroutine coroutine preloaded module
------------------------------------------------------------------------------
-- This library provides generic functions for string manipulation.
-- This is a global variable which hold the preloaded @{string} module.
-- @field[parent = #global] string#string string preloaded module
------------------------------------------------------------------------------
-- This library provides generic functions for table manipulation.
-- This is a global variable which hold the preloaded @{table} module.
-- @field[parent = #global] table#table table preloaded module
------------------------------------------------------------------------------
-- This library is an interface to the standard C math library.
-- This is a global variable which hold the preloaded @{math} module.
-- @field[parent = #global] math#math math preloaded module
------------------------------------------------------------------------------
-- This library is an interface to the standard C math library.
-- This is a global variable which hold the preloaded @{omwutil} module.
-- @field[parent = #global] omwutil#omwutil ou preloaded module
-------------------------------------------------------------------------------
-- Issues an error when the value of its argument `v` is false (i.e.,
-- **nil** or **false**); otherwise, returns all its arguments. `message` is an error
-- message; when absent, it defaults to *"assertion failed!"*.
-- @function [parent=#global] assert
-- @param v if this argument is false an error is issued.
-- @param #string message an error message. defaults value is *"assertion failed"*.
-- @return All its arguments.
-------------------------------------------------------------------------------
-- Terminates the last protected function called and returns `message`
-- as the error message. Function `error` never returns.
--
-- Usually, `error` adds some information about the error position at the
-- beginning of the message. The `level` argument specifies how to get the
-- error position.
-- With level 1 (the default), the error position is where the
-- `error` function was called.
-- Level 2 points the error to where the function
-- that called `error` was called; and so on.
-- Passing a level 0 avoids the addition of error position information to the message.
-- @function [parent=#global] error
-- @param #string message an error message.
-- @param #number level specifies how to get the error position, default value is `1`.
-------------------------------------------------------------------------------
-- If `object` does not have a metatable, returns nil. Otherwise, if the
-- object's metatable has a `"__metatable"` field, returns the associated
-- value. Otherwise, returns the metatable of the given object.
-- @function [parent=#global] getmetatable
-- @param object
-- @return #table the metatable of object.
-------------------------------------------------------------------------------
-- Use to iterate over a table by index.
-- Returns three values: an iterator function, the table `t`, and 0,
-- so that the construction :
--
-- for i,v in ipairs(t) do *body* end
-- will iterate over the pairs (`1,t[1]`), (`2,t[2]`), ..., up to the
-- first integer key absent from the table.
-- @function [parent=#global] ipairs
-- @param #table t a table by index.
-------------------------------------------------------------------------------
-- Allows a program to traverse all fields of a table. Its first argument is
-- a table and its second argument is an index in this table. `next` returns
-- the next index of the table and its associated value.
--
-- When called with nil
-- as its second argument, `next` returns an initial index and its associated
-- value. When called with the last index, or with nil in an empty table, `next`
-- returns nil.
--
-- If the second argument is absent, then it is interpreted as
-- nil. In particular, you can use `next(t)` to check whether a table is empty.
-- The order in which the indices are enumerated is not specified, *even for
-- numeric indices*. (To traverse a table in numeric order, use a numerical
-- for or the `ipairs` function.)
--
-- The behavior of `next` is *undefined* if, during the traversal, you assign
-- any value to a non-existent field in the table. You may however modify
-- existing fields. In particular, you may clear existing fields.
-- @function [parent=#global] next
-- @param #table table table to traverse.
-- @param index initial index.
-------------------------------------------------------------------------------
-- Use to iterate over a table.
-- Returns three values: the `next` function, the table `t`, and nil,
-- so that the construction :
--
-- for k,v in pairs(t) do *body* end
-- will iterate over all key-value pairs of table `t`.
--
-- See function `next` for the caveats of modifying the table during its
-- traversal.
-- @function [parent=#global] pairs
-- @param #table t table to traverse.
-------------------------------------------------------------------------------
-- Calls function `f` with the given arguments in *protected mode*. This
-- means that any error inside `f` is not propagated; instead, `pcall` catches
-- the error and returns a status code. Its first result is the status code (a
-- boolean), which is true if the call succeeds without errors. In such case,
-- `pcall` also returns all results from the call, after this first result. In
-- case of any error, `pcall` returns false plus the error message.
-- @function [parent=#global] pcall
-- @param f function to be call in *protected mode*.
-- @param ... function arguments.
-- @return #boolean true plus the result of `f` function if its call succeeds without errors.
-- @return #boolean,#string false plus the error message in case of any error.
-------------------------------------------------------------------------------
-- Receives any number of arguments, and prints their values to OpenMW log,
-- using the `tostring` function to convert them to strings. `print` is not
-- intended for formatted output, but only as a quick way to show a value,
-- typically for debugging. For formatted output, use `string.format`.
--
-- @function [parent=#global] print
-- @param ... values to print to `stdout`.
-------------------------------------------------------------------------------
-- Checks whether `v1` is equal to `v2`, without invoking any
-- metamethod. Returns a boolean.
-- @function [parent=#global] rawequal
-- @param v1
-- @param v2
-- @return #boolean true if `v1` is equal to `v2`.
-------------------------------------------------------------------------------
-- Gets the real value of `table[index]`, without invoking any
-- metamethod. `table` must be a table; `index` may be any value.
-- @function [parent=#global] rawget
-- @param #table table
-- @param index may be any value.
-- @return The real value of `table[index]`, without invoking any
-- metamethod.
-------------------------------------------------------------------------------
-- Sets the real value of `table[index]` to `value`, without invoking any
-- metamethod. `table` must be a table, `index` any value different from nil,
-- and `value` any Lua value.
-- This function returns `table`.
-- @function [parent=#global] rawset
-- @param #table table
-- @param index any value different from nil.
-- @param value any Lua value.
-------------------------------------------------------------------------------
-- If `index` is a number, returns all arguments after argument number
-- `index`. Otherwise, `index` must be the string `"#"`, and `select` returns
-- the total number of extra arguments it received.
-- @function [parent=#global] select
-- @param index a number or the string `"#"`
-- @param ...
-------------------------------------------------------------------------------
-- Sets the metatable for the given table. (You cannot change the metatable
-- of other types from Lua, only from C.) If `metatable` is nil, removes the
-- metatable of the given table. If the original metatable has a `"__metatable"`
-- field, raises an error.
-- This function returns `table`.
-- @function [parent=#global] setmetatable
-- @param #table table
-- @param #table metatable
-- @return The first argument `table`.
-------------------------------------------------------------------------------
-- Tries to convert its argument to a number. If the argument is already
-- a number or a string convertible to a number, then `tonumber` returns this
-- number; otherwise, it returns **nil.**
--
-- An optional argument specifies the base to interpret the numeral. The base
-- may be any integer between 2 and 36, inclusive. In bases above 10, the
-- letter '`A`' (in either upper or lower case) represents 10, '`B`' represents
-- 11, and so forth, with '`Z`' representing 35. In base 10 (the default),
-- the number can have a decimal part, as well as an optional exponent part.
-- In other bases, only unsigned integers are accepted.
-- @function [parent=#global] tonumber
-- @param e a number or string to convert to a number.
-- @param #number base the base to interpret the numeral, any integer between 2 and 36.(default is 10).
-- @return #number a number if conversion succeeds else **nil**.
-------------------------------------------------------------------------------
-- Receives an argument of any type and converts it to a string in a
-- reasonable format. For complete control of how numbers are converted, use
-- `string.format`.
--
-- If the metatable of `e` has a `"__tostring"` field, then `tostring` calls
-- the corresponding value with `e` as argument, and uses the result of the
-- call as its result.
-- @function [parent=#global] tostring
-- @param e an argument of any type.
-- @return #string a string in a reasonable format.
-------------------------------------------------------------------------------
-- Returns the type of its only argument, coded as a string. The possible
-- results of this function are "
-- `nil`" (a string, not the value nil), "`number`", "`string`", "`boolean`",
-- "`table`", "`function`", "`thread`", and "`userdata`".
-- @function [parent=#global] type
-- @param v any value.
-- @return #string the type of `v`.
-------------------------------------------------------------------------------
-- Returns the elements from the given table. This function is equivalent to
--
-- return list[i], list[i+1], ..., list[j]
-- except that the above code can be written only for a fixed number of
-- elements. By default, `i` is 1 and `j` is the length of the list, as
-- defined by the length operator.
-- @function [parent=#global] unpack
-- @param #table list a table by index
-- @param i index of first value.
-- @param j index of last value.
-------------------------------------------------------------------------------
-- A global variable (not a function) that holds a string containing the
-- current interpreter version. The current contents of this variable is
-- "`Lua 5.1`".
-- @field [parent = #global] #string _VERSION
-------------------------------------------------------------------------------
-- This function is similar to `pcall`, except that you can set a new
-- error handler.
--
-- `xpcall` calls function `f` in protected mode, using `err` as the error
-- handler. Any error inside `f` is not propagated; instead, `xpcall` catches
-- the error, calls the `err` function with the original error object, and
-- returns a status code. Its first result is the status code (a boolean),
-- which is true if the call succeeds without errors. In this case, `xpcall`
-- also returns all results from the call, after this first result. In case
-- of any error, `xpcall` returns false plus the result from `err`.
-- @function [parent=#global] xpcall
-- @param f function to be call in *protected mode*.
-- @param err function used as error handler.
-- @return #boolean true plus the result of `f` function if its call succeeds without errors.
-- @return #boolean,#string false plus the result of `err` function.
-------------------------------------------------------------------------------
-- Loads the given module.
-- If the requested module is one of the allowed standard libraries
-- (`coroutine`, `math`, `string`, `table`), then returns the library.
-- If it is one of the built-in OpenMW API packages, then returns the package.
-- Otherwise it searches for a Lua source file with such name in OpenMW data folders.
-- For example `require('my_lua_library.something')` will try to open the file
-- `my_lua_library/something.lua`.
--
-- Loading DLLs and precompiled Lua files is intentionally prohibited for reasons
-- of safety and compatibility between different platforms.
--
-- If there is any error loading or running the module, or if it cannot find
-- any loader for the module, then `require` signals an error.
-- @function [parent=#global] require
-- @param #string modname name of module to load.
return nil

@ -1,200 +1,200 @@
-------------------------------------------------------------------------------
-- Mathematical Functions.
-- This library is an interface to the standard C math library.
-- It provides all its functions inside the table math.
-- @module math
-------------------------------------------------------------------------------
-- Returns the absolute value of `x`.
-- @function [parent=#math] abs
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the arc cosine of `x` (in radians).
-- @function [parent=#math] acos
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the arc sine of `x` (in radians).
-- @function [parent=#math] asin
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the arc tangent of `x` (in radians).
-- @function [parent=#math] atan
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the arc tangent of `y/x` (in radians), but uses the signs
-- of both parameters to find the quadrant of the result. (It also handles
-- correctly the case of `x` being zero.)
-- @function [parent=#math] atan2
-- @param #number y
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the smallest integer larger than or equal to `x`.
-- @function [parent=#math] ceil
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the cosine of `x` (assumed to be in radians).
-- @function [parent=#math] cos
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the hyperbolic cosine of `x`.
-- @function [parent=#math] cosh
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the angle `x` (given in radians) in degrees.
-- @function [parent=#math] deg
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the value *e^x*.
-- @function [parent=#math] exp
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the largest integer smaller than or equal to `x`.
-- @function [parent=#math] floor
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the remainder of the division of `x` by `y` that rounds the
-- quotient towards zero.
-- @function [parent=#math] fmod
-- @param #number x
-- @param #number y
-- @return #number
-------------------------------------------------------------------------------
-- Returns `m` and `e` such that *x = m2^e*, `e` is an integer and the
-- absolute value of `m` is in the range *[0.5, 1)* (or zero when `x` is zero).
-- @function [parent=#math] frexp
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- The value `HUGE_VAL`, a value larger than or equal to any other
-- numerical value.
-- @field [parent=#math] #number huge
-------------------------------------------------------------------------------
-- Returns *m2^e* (`e` should be an integer).
-- @function [parent=#math] ldexp
-- @param #number m
-- @param #number e
-- @return #number
-------------------------------------------------------------------------------
-- Returns the natural logarithm of `x`.
-- @function [parent=#math] log
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the base-10 logarithm of `x`.
-- @function [parent=#math] log10
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the maximum value among its arguments.
-- @function [parent=#math] max
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the minimum value among its arguments.
-- @function [parent=#math] min
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns two numbers, the integral part of `x` and the fractional part of
-- `x`.
-- @function [parent=#math] modf
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- The value of *pi*.
-- @field [parent=#math] #number pi
-------------------------------------------------------------------------------
-- Returns *x^y*. (You can also use the expression `x^y` to compute this
-- value.)
-- @function [parent=#math] pow
-- @param #number x
-- @param #number y
-- @return #number
-------------------------------------------------------------------------------
-- Returns the angle `x` (given in degrees) in radians.
-- @function [parent=#math] rad
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- This function is an interface to the simple pseudo-random generator
-- function `rand` provided by ANSI C. (No guarantees can be given for its
-- statistical properties.)
--
-- When called without arguments, returns a uniform pseudo-random real
-- number in the range *[0,1)*. When called with an integer number `m`,
-- `math.random` returns a uniform pseudo-random integer in the range *[1,
-- m]*. When called with two integer numbers `m` and `n`, `math.random`
-- returns a uniform pseudo-random integer in the range *[m, n]*.
-- @function [parent=#math] random
-- @param #number m
-- @param #number n
-- @return #number
-------------------------------------------------------------------------------
-- Returns the sine of `x` (assumed to be in radians).
-- @function [parent=#math] sin
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the hyperbolic sine of `x`.
-- @function [parent=#math] sinh
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the square root of `x`. (You can also use the expression `x^0.5`
-- to compute this value.)
-- @function [parent=#math] sqrt
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the tangent of `x` (assumed to be in radians).
-- @function [parent=#math] tan
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the hyperbolic tangent of `x`.
-- @function [parent=#math] tanh
-- @param #number x
-- @return #number
return nil
-------------------------------------------------------------------------------
-- Mathematical Functions.
-- This library is an interface to the standard C math library.
-- It provides all its functions inside the table math.
-- @module math
-------------------------------------------------------------------------------
-- Returns the absolute value of `x`.
-- @function [parent=#math] abs
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the arc cosine of `x` (in radians).
-- @function [parent=#math] acos
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the arc sine of `x` (in radians).
-- @function [parent=#math] asin
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the arc tangent of `x` (in radians).
-- @function [parent=#math] atan
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the arc tangent of `y/x` (in radians), but uses the signs
-- of both parameters to find the quadrant of the result. (It also handles
-- correctly the case of `x` being zero.)
-- @function [parent=#math] atan2
-- @param #number y
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the smallest integer larger than or equal to `x`.
-- @function [parent=#math] ceil
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the cosine of `x` (assumed to be in radians).
-- @function [parent=#math] cos
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the hyperbolic cosine of `x`.
-- @function [parent=#math] cosh
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the angle `x` (given in radians) in degrees.
-- @function [parent=#math] deg
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the value *e^x*.
-- @function [parent=#math] exp
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the largest integer smaller than or equal to `x`.
-- @function [parent=#math] floor
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the remainder of the division of `x` by `y` that rounds the
-- quotient towards zero.
-- @function [parent=#math] fmod
-- @param #number x
-- @param #number y
-- @return #number
-------------------------------------------------------------------------------
-- Returns `m` and `e` such that *x = m2^e*, `e` is an integer and the
-- absolute value of `m` is in the range *[0.5, 1)* (or zero when `x` is zero).
-- @function [parent=#math] frexp
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- The value `HUGE_VAL`, a value larger than or equal to any other
-- numerical value.
-- @field [parent=#math] #number huge
-------------------------------------------------------------------------------
-- Returns *m2^e* (`e` should be an integer).
-- @function [parent=#math] ldexp
-- @param #number m
-- @param #number e
-- @return #number
-------------------------------------------------------------------------------
-- Returns the natural logarithm of `x`.
-- @function [parent=#math] log
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the base-10 logarithm of `x`.
-- @function [parent=#math] log10
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the maximum value among its arguments.
-- @function [parent=#math] max
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the minimum value among its arguments.
-- @function [parent=#math] min
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns two numbers, the integral part of `x` and the fractional part of
-- `x`.
-- @function [parent=#math] modf
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- The value of *pi*.
-- @field [parent=#math] #number pi
-------------------------------------------------------------------------------
-- Returns *x^y*. (You can also use the expression `x^y` to compute this
-- value.)
-- @function [parent=#math] pow
-- @param #number x
-- @param #number y
-- @return #number
-------------------------------------------------------------------------------
-- Returns the angle `x` (given in degrees) in radians.
-- @function [parent=#math] rad
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- This function is an interface to the simple pseudo-random generator
-- function `rand` provided by ANSI C. (No guarantees can be given for its
-- statistical properties.)
--
-- When called without arguments, returns a uniform pseudo-random real
-- number in the range *[0,1)*. When called with an integer number `m`,
-- `math.random` returns a uniform pseudo-random integer in the range *[1,
-- m]*. When called with two integer numbers `m` and `n`, `math.random`
-- returns a uniform pseudo-random integer in the range *[m, n]*.
-- @function [parent=#math] random
-- @param #number m
-- @param #number n
-- @return #number
-------------------------------------------------------------------------------
-- Returns the sine of `x` (assumed to be in radians).
-- @function [parent=#math] sin
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the hyperbolic sine of `x`.
-- @function [parent=#math] sinh
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the square root of `x`. (You can also use the expression `x^0.5`
-- to compute this value.)
-- @function [parent=#math] sqrt
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the tangent of `x` (assumed to be in radians).
-- @function [parent=#math] tan
-- @param #number x
-- @return #number
-------------------------------------------------------------------------------
-- Returns the hyperbolic tangent of `x`.
-- @function [parent=#math] tanh
-- @param #number x
-- @return #number
return nil

@ -1,231 +1,231 @@
-------------------------------------------------------------------------------
-- String Manipulation.
-- This library provides generic functions for string manipulation,
-- such as finding and extracting substrings, and pattern matching.
-- When indexing a string in Lua, the first character is at position 1 (not at 0, as in C).
-- Indices are allowed to be negative and are interpreted as indexing backwards, from the end of the string.
-- Thus, the last character is at position -1, and so on.
--
-- The string library provides all its functions inside the table string. It also sets a metatable for strings where the __index field points to the string table. Therefore, you can use the string functions in object-oriented style.
-- For instance, string.byte(s, i) can be written as s:byte(i).
--
-- The string library assumes one-byte character encodings.
-- @module string
-------------------------------------------------------------------------------
-- Returns the internal numerical codes of the characters `s[i]`, `s[i+1]`,
-- ..., `s[j]`. The default value for `i` is 1; the default value for `j`
-- is `i`.
-- Note that numerical codes are not necessarily portable across platforms.
-- @function [parent=#string] byte
-- @param #string s string to handle.
-- @param #number i start index, default value is 1.
-- @param #number j end index, default value is `i`.
-- @return the internal numerical codes of the characters `s[i]`, `s[i+1]`,..., `s[j]`
-------------------------------------------------------------------------------
-- Receives zero or more integers. Returns a string with length equal to
-- the number of arguments, in which each character has the internal numerical
-- code equal to its corresponding argument.
--
-- Note that numerical codes are not necessarily portable across platforms.
-- @function [parent=#string] char
-- @param ... zero or more integers.
-- @return #string a string with length equal to
-- the number of arguments, in which each character has the internal numerical
-- code equal to its corresponding argument.
-------------------------------------------------------------------------------
-- Returns a string containing a binary representation of the given
-- function, so that a later `loadstring` on this string returns a copy of
-- the function. `function` must be a Lua function without upvalues.
-- @function [parent=#string] dump
-- @param f the function to dump.
-- @return #string a string representation of the given function.
-------------------------------------------------------------------------------
-- Looks for the first match of `pattern` in the string `s`. If it finds a
-- match, then `find` returns the indices of `s` where this occurrence starts
-- and ends; otherwise, it returns nil.A third, optional numerical argument
-- `init` specifies where to start the search; its default value is 1 and
-- can be negative. A value of true as a fourth, optional argument `plain`
-- turns off the pattern matching facilities, so the function does a plain
-- "find substring" operation, with no characters in `pattern` being considered
-- "magic".
--
-- Note that if `plain` is given, then `init` must be given as well.
-- If the pattern has captures, then in a successful match the captured values
-- are also returned, after the two indices.
-- @function [parent=#string] find
-- @param #string s string to handle.
-- @param #string pattern pattern to search.
-- @param #number init index where to start the search. (default value is 1)
-- @param #boolean plain set to true to search without pattern matching. (default value is false)
-- @return #number, #number start and end indices of first occurence.
-- @return #nil if pattern not found.
-------------------------------------------------------------------------------
-- Returns a formatted version of its variable number of arguments following
-- the description given in its first argument (which must be a string). The
-- format string follows the same rules as the `printf` family of standard C
-- functions. The only differences are that the options/modifiers `*`, `l`,
-- `L`, `n`, `p`, and `h` are not supported and that there is an extra option,
-- `q`. The `q` option formats a string in a form suitable to be safely read
-- back by the Lua interpreter: the string is written between double quotes,
-- and all double quotes, newlines, embedded zeros, and backslashes in the
-- string are correctly escaped when written. For instance, the call
--
-- string.format('%q', 'a string with "quotes" and \n new line')
--
-- will produce the string:
--
-- "a string with \"quotes\" and \
-- new line"
--
-- The options `c`, `d`, `E`, `e`, `f`, `g`, `G`, `i`, `o`, `u`, `X`, and
-- `x` all expect a number as argument, whereas `q` and `s` expect a string.
-- This function does not accept string values containing embedded zeros,
-- except as arguments to the `q` option.
-- @function [parent=#string] format
-- @param #string formatstring the string template.
-- @param ... arguments could be strings or numbers.
-- @return #string the formatted string.
-------------------------------------------------------------------------------
-- Returns an iterator function that, each time it is called, returns the
-- next captures from `pattern` over string `s`. If `pattern` specifies no
-- captures, then the whole match is produced in each call.
-- As an example, the following loop
--
-- s = "hello world from Lua"
-- for w in string.gmatch(s, "%a+") do
-- print(w)
-- end
--
-- will iterate over all the words from string `s`, printing one per line. The
-- next example collects all pairs `key=value` from the given string into
-- a table:
--
-- t = {}
-- s = "from=world, to=Lua"
-- for k, v in string.gmatch(s, "(%w+)=(%w+)") do
-- t[k] = v
-- end
--
-- For this function, a '`^`' at the start of a pattern does not work as an
-- anchor, as this would prevent the iteration.
-- @function [parent=#string] gmatch
-- @param #string s string to handle.
-- @param #string pattern pattern to search.
-------------------------------------------------------------------------------
-- Returns a copy of `s` in which all (or the first `n`, if given)
-- occurrences of the `pattern` have been replaced by a replacement string
-- specified by `repl`, which can be a string, a table, or a function. `gsub`
-- also returns, as its second value, the total number of matches that occurred.
--
-- If `repl` is a string, then its value is used for replacement. The character
-- `%` works as an escape character: any sequence in `repl` of the form `%n`,
-- with *n* between 1 and 9, stands for the value of the *n*-th captured
-- substring (see below). The sequence `%0` stands for the whole match. The
-- sequence `%%` stands for a single `%`.
--
-- If `repl` is a table, then the table is queried for every match, using
-- the first capture as the key; if the pattern specifies no captures, then
-- the whole match is used as the key.
--
-- If `repl` is a function, then this function is called every time a match
-- occurs, with all captured substrings passed as arguments, in order; if
-- the pattern specifies no captures, then the whole match is passed as a
-- sole argument.
--
-- If the value returned by the table query or by the function call is a
-- string or a number, then it is used as the replacement string; otherwise,
-- if it is false or nil, then there is no replacement (that is, the original
-- match is kept in the string).
--
-- Here are some examples:
--
-- x = string.gsub("hello world", "(%w+)", "%1 %1")
-- --> x="hello hello world world"
-- x = string.gsub("hello world", "%w+", "%0 %0", 1)
-- --> x="hello hello world"
-- x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
-- --> x="world hello Lua from"
-- x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
-- --> x="home = /home/roberto, user = roberto"
-- x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
-- return loadstring(s)()
-- end)
-- --> x="4+5 = 9"
-- local t = {name="lua", version="5.1"}
-- x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
-- --> x="lua-5.1.tar.gz"
-- @function [parent=#string] gsub
-- @param #string s string to handle.
-- @param #string pattern pattern to search.
-- @param repl replacement could be a string, a table or a function.
-- @param #number n number of occurences to replace, default is nil which means all occurences.
-- @return #string a modified copy of `s`.
-------------------------------------------------------------------------------
-- Receives a string and returns its length. The empty string `""` has
-- length 0. Embedded zeros are counted, so `"a\000bc\000"` has length 5.
-- @function [parent=#string] len
-- @param #string s string to handle.
-- @return #number the lenght of `s`.
-------------------------------------------------------------------------------
-- Receives a string and returns a copy of this string with all uppercase
-- letters changed to lowercase. All other characters are left unchanged. The
-- definition of what an uppercase letter is depends on the current locale.
-- @function [parent=#string] lower
-- @param #string s string to handle.
-- @return #string a lower case version of `s`.
-------------------------------------------------------------------------------
-- Looks for the first *match* of `pattern` in the string `s`. If it
-- finds one, then `match` returns the captures from the pattern; otherwise
-- it returns nil. If `pattern` specifies no captures, then the whole match
-- is returned. A third, optional numerical argument `init` specifies where
-- to start the search; its default value is 1 and can be negative.
-- @function [parent=#string] match
-- @param #string s string to handle.
-- @param #string pattern pattern to search.
-- @param #number init index where to start the search. (default value is 1)
-- @return #string the captures from the pattern; otherwise it returns nil. If pattern specifies no captures, then the whole match is returned.
-------------------------------------------------------------------------------
-- Returns a string that is the concatenation of `n` copies of the string `s`.
-- @function [parent=#string] rep
-- @param #string s string to handle.
-- @param #number n number of repetition.
-- @return #string the concatenation of `n` copies of the string `s`.
-------------------------------------------------------------------------------
-- Returns a string that is the string `s` reversed.
-- @function [parent=#string] reverse
-- @param #string s string to handle.
-- @return #string the string `s` reversed.
-------------------------------------------------------------------------------
-- Returns the substring of `s` that starts at `i` and continues until
-- `j`; `i` and `j` can be negative. If `j` is absent, then it is assumed to
-- be equal to -1 (which is the same as the string length). In particular,
-- the call `string.sub(s,1,j)` returns a prefix of `s` with length `j`, and
-- `string.sub(s, -i)` returns a suffix of `s` with length `i`.
-- @function [parent=#string] sub
-- @param #string s string to handle.
-- @param #number i start index.
-- @param #number j end index. (default value is -1, which is the same as the string lenght)
-- @return #string the substring of `s` that starts at `i` and continues until `j`.
-------------------------------------------------------------------------------
-- Receives a string and returns a copy of this string with all lowercase
-- letters changed to uppercase. All other characters are left unchanged. The
-- definition of what a lowercase letter is depends on the current locale.
-- @function [parent=#string] upper
-- @param #string s string to handle.
-- @return #string a upper case version of `s`.
return nil
-------------------------------------------------------------------------------
-- String Manipulation.
-- This library provides generic functions for string manipulation,
-- such as finding and extracting substrings, and pattern matching.
-- When indexing a string in Lua, the first character is at position 1 (not at 0, as in C).
-- Indices are allowed to be negative and are interpreted as indexing backwards, from the end of the string.
-- Thus, the last character is at position -1, and so on.
--
-- The string library provides all its functions inside the table string. It also sets a metatable for strings where the __index field points to the string table. Therefore, you can use the string functions in object-oriented style.
-- For instance, string.byte(s, i) can be written as s:byte(i).
--
-- The string library assumes one-byte character encodings.
-- @module string
-------------------------------------------------------------------------------
-- Returns the internal numerical codes of the characters `s[i]`, `s[i+1]`,
-- ..., `s[j]`. The default value for `i` is 1; the default value for `j`
-- is `i`.
-- Note that numerical codes are not necessarily portable across platforms.
-- @function [parent=#string] byte
-- @param #string s string to handle.
-- @param #number i start index, default value is 1.
-- @param #number j end index, default value is `i`.
-- @return the internal numerical codes of the characters `s[i]`, `s[i+1]`,..., `s[j]`
-------------------------------------------------------------------------------
-- Receives zero or more integers. Returns a string with length equal to
-- the number of arguments, in which each character has the internal numerical
-- code equal to its corresponding argument.
--
-- Note that numerical codes are not necessarily portable across platforms.
-- @function [parent=#string] char
-- @param ... zero or more integers.
-- @return #string a string with length equal to
-- the number of arguments, in which each character has the internal numerical
-- code equal to its corresponding argument.
-------------------------------------------------------------------------------
-- Returns a string containing a binary representation of the given
-- function, so that a later `loadstring` on this string returns a copy of
-- the function. `function` must be a Lua function without upvalues.
-- @function [parent=#string] dump
-- @param f the function to dump.
-- @return #string a string representation of the given function.
-------------------------------------------------------------------------------
-- Looks for the first match of `pattern` in the string `s`. If it finds a
-- match, then `find` returns the indices of `s` where this occurrence starts
-- and ends; otherwise, it returns nil.A third, optional numerical argument
-- `init` specifies where to start the search; its default value is 1 and
-- can be negative. A value of true as a fourth, optional argument `plain`
-- turns off the pattern matching facilities, so the function does a plain
-- "find substring" operation, with no characters in `pattern` being considered
-- "magic".
--
-- Note that if `plain` is given, then `init` must be given as well.
-- If the pattern has captures, then in a successful match the captured values
-- are also returned, after the two indices.
-- @function [parent=#string] find
-- @param #string s string to handle.
-- @param #string pattern pattern to search.
-- @param #number init index where to start the search. (default value is 1)
-- @param #boolean plain set to true to search without pattern matching. (default value is false)
-- @return #number, #number start and end indices of first occurence.
-- @return #nil if pattern not found.
-------------------------------------------------------------------------------
-- Returns a formatted version of its variable number of arguments following
-- the description given in its first argument (which must be a string). The
-- format string follows the same rules as the `printf` family of standard C
-- functions. The only differences are that the options/modifiers `*`, `l`,
-- `L`, `n`, `p`, and `h` are not supported and that there is an extra option,
-- `q`. The `q` option formats a string in a form suitable to be safely read
-- back by the Lua interpreter: the string is written between double quotes,
-- and all double quotes, newlines, embedded zeros, and backslashes in the
-- string are correctly escaped when written. For instance, the call
--
-- string.format('%q', 'a string with "quotes" and \n new line')
--
-- will produce the string:
--
-- "a string with \"quotes\" and \
-- new line"
--
-- The options `c`, `d`, `E`, `e`, `f`, `g`, `G`, `i`, `o`, `u`, `X`, and
-- `x` all expect a number as argument, whereas `q` and `s` expect a string.
-- This function does not accept string values containing embedded zeros,
-- except as arguments to the `q` option.
-- @function [parent=#string] format
-- @param #string formatstring the string template.
-- @param ... arguments could be strings or numbers.
-- @return #string the formatted string.
-------------------------------------------------------------------------------
-- Returns an iterator function that, each time it is called, returns the
-- next captures from `pattern` over string `s`. If `pattern` specifies no
-- captures, then the whole match is produced in each call.
-- As an example, the following loop
--
-- s = "hello world from Lua"
-- for w in string.gmatch(s, "%a+") do
-- print(w)
-- end
--
-- will iterate over all the words from string `s`, printing one per line. The
-- next example collects all pairs `key=value` from the given string into
-- a table:
--
-- t = {}
-- s = "from=world, to=Lua"
-- for k, v in string.gmatch(s, "(%w+)=(%w+)") do
-- t[k] = v
-- end
--
-- For this function, a '`^`' at the start of a pattern does not work as an
-- anchor, as this would prevent the iteration.
-- @function [parent=#string] gmatch
-- @param #string s string to handle.
-- @param #string pattern pattern to search.
-------------------------------------------------------------------------------
-- Returns a copy of `s` in which all (or the first `n`, if given)
-- occurrences of the `pattern` have been replaced by a replacement string
-- specified by `repl`, which can be a string, a table, or a function. `gsub`
-- also returns, as its second value, the total number of matches that occurred.
--
-- If `repl` is a string, then its value is used for replacement. The character
-- `%` works as an escape character: any sequence in `repl` of the form `%n`,
-- with *n* between 1 and 9, stands for the value of the *n*-th captured
-- substring (see below). The sequence `%0` stands for the whole match. The
-- sequence `%%` stands for a single `%`.
--
-- If `repl` is a table, then the table is queried for every match, using
-- the first capture as the key; if the pattern specifies no captures, then
-- the whole match is used as the key.
--
-- If `repl` is a function, then this function is called every time a match
-- occurs, with all captured substrings passed as arguments, in order; if
-- the pattern specifies no captures, then the whole match is passed as a
-- sole argument.
--
-- If the value returned by the table query or by the function call is a
-- string or a number, then it is used as the replacement string; otherwise,
-- if it is false or nil, then there is no replacement (that is, the original
-- match is kept in the string).
--
-- Here are some examples:
--
-- x = string.gsub("hello world", "(%w+)", "%1 %1")
-- --> x="hello hello world world"
-- x = string.gsub("hello world", "%w+", "%0 %0", 1)
-- --> x="hello hello world"
-- x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
-- --> x="world hello Lua from"
-- x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
-- --> x="home = /home/roberto, user = roberto"
-- x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
-- return loadstring(s)()
-- end)
-- --> x="4+5 = 9"
-- local t = {name="lua", version="5.1"}
-- x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
-- --> x="lua-5.1.tar.gz"
-- @function [parent=#string] gsub
-- @param #string s string to handle.
-- @param #string pattern pattern to search.
-- @param repl replacement could be a string, a table or a function.
-- @param #number n number of occurences to replace, default is nil which means all occurences.
-- @return #string a modified copy of `s`.
-------------------------------------------------------------------------------
-- Receives a string and returns its length. The empty string `""` has
-- length 0. Embedded zeros are counted, so `"a\000bc\000"` has length 5.
-- @function [parent=#string] len
-- @param #string s string to handle.
-- @return #number the lenght of `s`.
-------------------------------------------------------------------------------
-- Receives a string and returns a copy of this string with all uppercase
-- letters changed to lowercase. All other characters are left unchanged. The
-- definition of what an uppercase letter is depends on the current locale.
-- @function [parent=#string] lower
-- @param #string s string to handle.
-- @return #string a lower case version of `s`.
-------------------------------------------------------------------------------
-- Looks for the first *match* of `pattern` in the string `s`. If it
-- finds one, then `match` returns the captures from the pattern; otherwise
-- it returns nil. If `pattern` specifies no captures, then the whole match
-- is returned. A third, optional numerical argument `init` specifies where
-- to start the search; its default value is 1 and can be negative.
-- @function [parent=#string] match
-- @param #string s string to handle.
-- @param #string pattern pattern to search.
-- @param #number init index where to start the search. (default value is 1)
-- @return #string the captures from the pattern; otherwise it returns nil. If pattern specifies no captures, then the whole match is returned.
-------------------------------------------------------------------------------
-- Returns a string that is the concatenation of `n` copies of the string `s`.
-- @function [parent=#string] rep
-- @param #string s string to handle.
-- @param #number n number of repetition.
-- @return #string the concatenation of `n` copies of the string `s`.
-------------------------------------------------------------------------------
-- Returns a string that is the string `s` reversed.
-- @function [parent=#string] reverse
-- @param #string s string to handle.
-- @return #string the string `s` reversed.
-------------------------------------------------------------------------------
-- Returns the substring of `s` that starts at `i` and continues until
-- `j`; `i` and `j` can be negative. If `j` is absent, then it is assumed to
-- be equal to -1 (which is the same as the string length). In particular,
-- the call `string.sub(s,1,j)` returns a prefix of `s` with length `j`, and
-- `string.sub(s, -i)` returns a suffix of `s` with length `i`.
-- @function [parent=#string] sub
-- @param #string s string to handle.
-- @param #number i start index.
-- @param #number j end index. (default value is -1, which is the same as the string lenght)
-- @return #string the substring of `s` that starts at `i` and continues until `j`.
-------------------------------------------------------------------------------
-- Receives a string and returns a copy of this string with all lowercase
-- letters changed to uppercase. All other characters are left unchanged. The
-- definition of what a lowercase letter is depends on the current locale.
-- @function [parent=#string] upper
-- @param #string s string to handle.
-- @return #string a upper case version of `s`.
return nil

@ -1,66 +1,66 @@
-------------------------------------------------------------------------------
-- Table Manipulation
-- This library provides generic functions for table manipulation.
-- It provides all its functions inside the table table.
--
-- Most functions in the table library assume that the table represents an array or a list.
-- For these functions, when we talk about the "length" of a table we mean the result of the length operator.
-- @module table
-------------------------------------------------------------------------------
-- Given an array where all elements are strings or numbers, returns
-- `table[i]..sep..table[i+1]...sep..table[j]`. The default value for
-- `sep` is the empty string, the default for `i` is 1, and the default for
-- `j` is the length of the table. If `i` is greater than `j`, returns the
-- empty string.
-- @function [parent=#table] concat
-- @param #table table table to handle.
-- @param #string sep the separator, default value is an empty string.
-- @param #number i start index, default value is 1.
-- @param #number j end index, default value is lenght of the table.
-- @return #string the concatenated table.
-------------------------------------------------------------------------------
-- Inserts element `value` at position `pos` in `table`, shifting up
-- other elements to open space, if necessary. The default value for `pos` is
-- `n+1`, where `n` is the length of the table, so that a call
-- `table.insert(t,x)` inserts `x` at the end of table `t`.
-- @function [parent=#table] insert
-- @param #table table table to modify.
-- @param #number pos index of insertion.
-- @param value value to insert.
-------------------------------------------------------------------------------
-- Returns the largest positive numerical index of the given table, or
-- zero if the table has no positive numerical indices. (To do its job this
-- function does a linear traversal of the whole table.)
-- @function [parent=#table] maxn
-- @param #table table table to traverse.
-- @return #number the largest positive numerical index of the given table, or
-- zero if the table has no positive numerical indices.
-------------------------------------------------------------------------------
-- Removes from `table` the element at position `pos`, shifting down other
-- elements to close the space, if necessary. Returns the value of the removed
-- element. The default value for `pos` is `n`, where `n` is the length of the
-- table, so that a call `table.remove(t)` removes the last element of table
-- `t`.
-- @function [parent=#table] remove
-- @param #table table table to modify.
-- @param #number pos index of deletion. (default value is the lenght of the table)
-------------------------------------------------------------------------------
-- Sorts table elements in a given order,
-- *in-place*, from `table[1]` to `table[n]`, where `n` is the length of the
-- table. If `comp` is given, then it must be a function that receives two
-- table elements, and returns true when the first is less than the second
-- (so that `not comp(a[i+1],a[i])` will be true after the sort). Lua operator < is used instead.
--
-- The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort.
-- @function [parent=#table] sort
-- @param #table table table to sort.
-- @param comp a function which take to table and returns true when the first is less than the second.
return nil
-------------------------------------------------------------------------------
-- Table Manipulation
-- This library provides generic functions for table manipulation.
-- It provides all its functions inside the table table.
--
-- Most functions in the table library assume that the table represents an array or a list.
-- For these functions, when we talk about the "length" of a table we mean the result of the length operator.
-- @module table
-------------------------------------------------------------------------------
-- Given an array where all elements are strings or numbers, returns
-- `table[i]..sep..table[i+1]...sep..table[j]`. The default value for
-- `sep` is the empty string, the default for `i` is 1, and the default for
-- `j` is the length of the table. If `i` is greater than `j`, returns the
-- empty string.
-- @function [parent=#table] concat
-- @param #table table table to handle.
-- @param #string sep the separator, default value is an empty string.
-- @param #number i start index, default value is 1.
-- @param #number j end index, default value is lenght of the table.
-- @return #string the concatenated table.
-------------------------------------------------------------------------------
-- Inserts element `value` at position `pos` in `table`, shifting up
-- other elements to open space, if necessary. The default value for `pos` is
-- `n+1`, where `n` is the length of the table, so that a call
-- `table.insert(t,x)` inserts `x` at the end of table `t`.
-- @function [parent=#table] insert
-- @param #table table table to modify.
-- @param #number pos index of insertion.
-- @param value value to insert.
-------------------------------------------------------------------------------
-- Returns the largest positive numerical index of the given table, or
-- zero if the table has no positive numerical indices. (To do its job this
-- function does a linear traversal of the whole table.)
-- @function [parent=#table] maxn
-- @param #table table table to traverse.
-- @return #number the largest positive numerical index of the given table, or
-- zero if the table has no positive numerical indices.
-------------------------------------------------------------------------------
-- Removes from `table` the element at position `pos`, shifting down other
-- elements to close the space, if necessary. Returns the value of the removed
-- element. The default value for `pos` is `n`, where `n` is the length of the
-- table, so that a call `table.remove(t)` removes the last element of table
-- `t`.
-- @function [parent=#table] remove
-- @param #table table table to modify.
-- @param #number pos index of deletion. (default value is the lenght of the table)
-------------------------------------------------------------------------------
-- Sorts table elements in a given order,
-- *in-place*, from `table[1]` to `table[n]`, where `n` is the length of the
-- table. If `comp` is given, then it must be a function that receives two
-- table elements, and returns true when the first is less than the second
-- (so that `not comp(a[i+1],a[i])` will be true after the sort). Lua operator < is used instead.
--
-- The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort.
-- @function [parent=#table] sort
-- @param #table table table to sort.
-- @param comp a function which take to table and returns true when the first is less than the second.
return nil

@ -1,25 +1,25 @@
\section{OpenCS starting dialog}
\subsection{Introduction}
The great day has come. Today, you shall open \OCS{} application. And when you do this, you shall see our starting dialog window that holds three buttons
that can bring both pain and happiness. So just do this, please.
\subsection{Basics}
Back to the manual? Great! As you can see, the starting window holds just three buttons. Since you are already familiar with our files system, they come
to you with no surprise.\\
First, there is a \textbf{Create A New Game} button. Clearly, you should press it when you want to create a game file. Than, what \textbf{Create A New Addon} button do?
Yes! You are right! This button will create any addon content file (and new project file associated with it)! Wonderful! And what the last remaining button do? \textbf{Edit A Content File}? Well, it comes with no surprise that this should be used when you need to alter existing content file, either a game or addon.\\
\paragraph{Selecting Files For New Addon}
As We wrote earlier, both \OMW{} and \OCS{} are operating with dependency idea in mind. As You remember you should only depend on files you are actually using. But how?\\
It is simple. When you click either \textbf{Create new Addon} you will be asked to choose those with a new dialog window. The window is using vertical layout, first you should consider the the top element, the one that allows you to select a game file with drop down menu. Since we are operating on the assumption that there is only one game file loaded at the time, you can depend only on one game file. Next, choose addons that you want to use in your addon with checkboxes.\\
The last thing to do is to name your your addon and click create.
\paragraph{Selecting File for Editing}
Clicking \textbf{Edit A Content File} will show somewhat similar window. Here you should select your Game file with drop down menu. If you want to edit this game file, simply click \textbf{OK} button. If you want to alter addon depending on that file, mark it with check-box and than click \textbf{Ok} button.
\subsection{Advanced}
If you are paying attention, you noticed any extra icon with wrench. This one will open small settings window. Those are general OpenCS settings. We will cover this is separate section.\\
\section{OpenCS starting dialog}
\subsection{Introduction}
The great day has come. Today, you shall open \OCS{} application. And when you do this, you shall see our starting dialog window that holds three buttons
that can bring both pain and happiness. So just do this, please.
\subsection{Basics}
Back to the manual? Great! As you can see, the starting window holds just three buttons. Since you are already familiar with our files system, they come
to you with no surprise.\\
First, there is a \textbf{Create A New Game} button. Clearly, you should press it when you want to create a game file. Than, what \textbf{Create A New Addon} button do?
Yes! You are right! This button will create any addon content file (and new project file associated with it)! Wonderful! And what the last remaining button do? \textbf{Edit A Content File}? Well, it comes with no surprise that this should be used when you need to alter existing content file, either a game or addon.\\
\paragraph{Selecting Files For New Addon}
As We wrote earlier, both \OMW{} and \OCS{} are operating with dependency idea in mind. As You remember you should only depend on files you are actually using. But how?\\
It is simple. When you click either \textbf{Create new Addon} you will be asked to choose those with a new dialog window. The window is using vertical layout, first you should consider the the top element, the one that allows you to select a game file with drop down menu. Since we are operating on the assumption that there is only one game file loaded at the time, you can depend only on one game file. Next, choose addons that you want to use in your addon with checkboxes.\\
The last thing to do is to name your your addon and click create.
\paragraph{Selecting File for Editing}
Clicking \textbf{Edit A Content File} will show somewhat similar window. Here you should select your Game file with drop down menu. If you want to edit this game file, simply click \textbf{OK} button. If you want to alter addon depending on that file, mark it with check-box and than click \textbf{Ok} button.
\subsection{Advanced}
If you are paying attention, you noticed any extra icon with wrench. This one will open small settings window. Those are general OpenCS settings. We will cover this is separate section.\\
And that would be it. There is no point spending more time here. We should go forward now.

@ -1,118 +1,118 @@
\section{Files and Directories}
\subsection{Introduction}
This section of the manual describes the directories and file types used by OpenCS. A file is a resource for storing data (e.g. .exe, .jpg, .txt),
whereas a directory is a folder or file system structure which points to these files (or other directories). You are most likely already familiar
with these concepts.
\subsection{Used terms} %TODO
\subsection{Basics}
\paragraph{Directories}
OpenMW and \OCS{} store their files in multiple directories. Firstly, there is the \textbf{user directory} that holds configuration
files and several other folders. The location of the user directory is hard coded for each supported operating system.
%TODO list paths.
In addition to the user directory, both \OMW{} and \OCS{} need a place to store the games actual data files: for example, the
textures, models, sounds and records of in-game objects. We support multiple paths to these files (termed \textbf{data paths}),
as specified in the configuration. Usually, one data path points to the directory where \MW{} is installed; however, you are
free to specify as many data paths as you would like. In addition, one particular data path, as described below, is used to store
newly created content files.
\paragraph{Content files}
\BS{} \MW{} engine uses two file types: ESM (master) and ESP (plugin). The distinction between the two is often confusing.
You would expect that the ESM (master) file is used to specify a single master which is modified by the ESP files (plugins), and indeed:
this is the basic idea. However, the original expansions are also ESM files, even though they can be described as very large plugins.
There were technical reasons behind this decision -- somewhat valid in the case of the original engine -- but a more logical file system is
much preferable. \OMW{} achieves this through the creation of our own types of content file.
We support both ESM and ESP files, but, in order to make use of \OMW{}'s new features, one should consider using new file types designed
with our engine in mind: game files and addon files, collectively termed \textbf{content files}.
\subparagraph{OpenMW content files}
The distinction between game and addon files is similar to that between ESM and ESP, however their relationship to each other is
strictly defined - the former are always master files, and the latter are always plugins. If you want to make a new game using the \OMW{}
engine (i.e. a ``total conversion''), you should create a game file. If you want to create an addon for an existing game file, simply
create an addon file. Nothing else matters: the only distinction you should consider is whether your project involves changing another game,
or creating a new one. Simple as that.
Furthermore, our content files extensions are .omwaddon for addon files and .omwgame for game files.
%TODO describe what content files contains. and what not.
\subparagraph{\MW{} content files}
Using our content files is the recommended solution for projects that employ the \OMW{} engine. However, some players will wish to use
the original \MW{} engine, despite its large flaws and lacking features\footnote{If this is wrong, we are a very successful project. Yay!}.
In addition, since 2002, thousands of ESP/ESM files have been created, some with truly outstanding content. Because of this, \OCS{}
will support ESP/ESM files, although this will impose limitations on the user. If you do decide to use ESP/ESM files rather than our own content
files, you are most likely aiming for original engine compatibility. This subject is covered in the very last section of the manual.
%not finished TODO add the said section. Most likely when more features are present.
The actual creation of new files is described in the next chapter. Here we are going to focus only on the essential information needed
to create your first \OCS{} file. For now, let's jut remember that content files are stored in the user directory, in the \textbf{data}
subfolder (the particular data directory mentioned above).
\subparagraph{Dependencies}
Since addons aim to modify an existing game, it is logical that they also depend on the said game: otherwise they will not function.
For example, your modification changes the price of iron swords. But what if there are no iron swords in the game? That is right:
it is nonsense. Therefore, it is necessary to make your addon a dependency of other content files. These can be either game files
(e.g. an entirely new island), or other addon files (e.g. a house on the island). It is a good idea for addons to depend only on the
content files they modify, but this is up to the end user to determine.
Game files do not depend on any other content files, as they act as master files. A player can only use one game file at a time
(although this does not apply to the original and dirty ESP/ESM system).
%\subparagraph{Loading order} %TODO
\paragraph{Project files}
Project files contain data not used by the \OMW{} game engine but which are still needed by OpenCS. Good examples of this data type
are the record filters (described below). As a mod author, you probably do not need and/or want to distribute project files at all,
as they are meant to be used only by you.
Since project files govern how content files are used in OpenCS, they are always used in conjunction with your specific project.
In fact, each time work commences on a content file that does not have a corresponding project file, a new project file will be created.
The project file extension is ``.project''. The name of the project file is the whole name of the content file with appended extensions.
For instance, a content file named swords.omwaddon is associated with the project file swords.omwaddon.project.
%TODO where are they stored.
Project files are stored inside the user directory, in the \textbf{projects} subfolder. This is both the location of newly created
project files, and the place where \OCS{} looks for already existing files.
\paragraph{Resource files}
%textures, sounds, whatever
The vast majority of modern video games use what we shall term \textbf{resource files}: models, textures, icons, sounds and so on.
ESPs, ESMs and \OMW{} content files do not contain these files, merely instructions on how they are used. It follows that the \OMW{}
engine must be capable of supporting these resource files in order for them to function. Therefore this section covers ways to add
resource files to your content file, and outlines which formats are supported. Later, you will learn how to make use of these files
in your content.
\subparagraph{Audio}
OpenMW utilises {FFmpeg} for audio playback, so we support every audio type supported by this library. This is a huge list.
Below is only a small sample of supported file types.
\begin{description}
\item mp3 ({MPEG}-1 {Part 3 Layer 3}) A popular audio file format and the \textit{de facto} standard for storing audio. Used by
the \MW{} game.
\item ogg Open source, multimedia container file which uses the high quality vorbis audio codec. Recommended.
\end{description}
\subparagraph{Video}
As in the case of audio files, we use {FFmpeg} to decode video files. The list of supported files is long - only the most
significant will be covered.
\begin{description}
\item bik Format used by the original \MW{} game.
\item mp4 Multimedia container which use more advanced codecs ({MPEG-4 Parts 2,3,10}) with a better audio and video compression rate,
but which require more {CPU} intensive decoding -- this probably makes it less suited for storing sounds in computer games, but
good for videos.
\item webm A new, shiny and open source video format with excellent compression. It needs quite a lot of processing power to be decoded,
but since game logic is not running during cut scenes we can recommend it for use with \OMW.
\item ogv An alternative, open source container using theora codec for video and vorbis for audio.
\end{description}
\subparagraph{Textures and images}
\MW{} uses {DDS} and {TGA} files for all kinds of two dimensional images and textures. In addition, the original engine supported BMP
files (although {BMP} is a terrible format for a video game). We also support an extended set of image files -- including {JPEG} and {PNG}.
JPEG and PNG files can be useful in some cases. For instance, a JPEG file is a valid option for a skybox texture and PNG can useful for masks.
However, keep in mind that a JPEG can grow large quickly and so are not the best option with a {DirectX} rendering backend. DDS files
are therefore recommended for textures.
\section{Files and Directories}
\subsection{Introduction}
This section of the manual describes the directories and file types used by OpenCS. A file is a resource for storing data (e.g. .exe, .jpg, .txt),
whereas a directory is a folder or file system structure which points to these files (or other directories). You are most likely already familiar
with these concepts.
\subsection{Used terms} %TODO
\subsection{Basics}
\paragraph{Directories}
OpenMW and \OCS{} store their files in multiple directories. Firstly, there is the \textbf{user directory} that holds configuration
files and several other folders. The location of the user directory is hard coded for each supported operating system.
%TODO list paths.
In addition to the user directory, both \OMW{} and \OCS{} need a place to store the games actual data files: for example, the
textures, models, sounds and records of in-game objects. We support multiple paths to these files (termed \textbf{data paths}),
as specified in the configuration. Usually, one data path points to the directory where \MW{} is installed; however, you are
free to specify as many data paths as you would like. In addition, one particular data path, as described below, is used to store
newly created content files.
\paragraph{Content files}
\BS{} \MW{} engine uses two file types: ESM (master) and ESP (plugin). The distinction between the two is often confusing.
You would expect that the ESM (master) file is used to specify a single master which is modified by the ESP files (plugins), and indeed:
this is the basic idea. However, the original expansions are also ESM files, even though they can be described as very large plugins.
There were technical reasons behind this decision -- somewhat valid in the case of the original engine -- but a more logical file system is
much preferable. \OMW{} achieves this through the creation of our own types of content file.
We support both ESM and ESP files, but, in order to make use of \OMW{}'s new features, one should consider using new file types designed
with our engine in mind: game files and addon files, collectively termed \textbf{content files}.
\subparagraph{OpenMW content files}
The distinction between game and addon files is similar to that between ESM and ESP, however their relationship to each other is
strictly defined - the former are always master files, and the latter are always plugins. If you want to make a new game using the \OMW{}
engine (i.e. a ``total conversion''), you should create a game file. If you want to create an addon for an existing game file, simply
create an addon file. Nothing else matters: the only distinction you should consider is whether your project involves changing another game,
or creating a new one. Simple as that.
Furthermore, our content files extensions are .omwaddon for addon files and .omwgame for game files.
%TODO describe what content files contains. and what not.
\subparagraph{\MW{} content files}
Using our content files is the recommended solution for projects that employ the \OMW{} engine. However, some players will wish to use
the original \MW{} engine, despite its large flaws and lacking features\footnote{If this is wrong, we are a very successful project. Yay!}.
In addition, since 2002, thousands of ESP/ESM files have been created, some with truly outstanding content. Because of this, \OCS{}
will support ESP/ESM files, although this will impose limitations on the user. If you do decide to use ESP/ESM files rather than our own content
files, you are most likely aiming for original engine compatibility. This subject is covered in the very last section of the manual.
%not finished TODO add the said section. Most likely when more features are present.
The actual creation of new files is described in the next chapter. Here we are going to focus only on the essential information needed
to create your first \OCS{} file. For now, let's jut remember that content files are stored in the user directory, in the \textbf{data}
subfolder (the particular data directory mentioned above).
\subparagraph{Dependencies}
Since addons aim to modify an existing game, it is logical that they also depend on the said game: otherwise they will not function.
For example, your modification changes the price of iron swords. But what if there are no iron swords in the game? That is right:
it is nonsense. Therefore, it is necessary to make your addon a dependency of other content files. These can be either game files
(e.g. an entirely new island), or other addon files (e.g. a house on the island). It is a good idea for addons to depend only on the
content files they modify, but this is up to the end user to determine.
Game files do not depend on any other content files, as they act as master files. A player can only use one game file at a time
(although this does not apply to the original and dirty ESP/ESM system).
%\subparagraph{Loading order} %TODO
\paragraph{Project files}
Project files contain data not used by the \OMW{} game engine but which are still needed by OpenCS. Good examples of this data type
are the record filters (described below). As a mod author, you probably do not need and/or want to distribute project files at all,
as they are meant to be used only by you.
Since project files govern how content files are used in OpenCS, they are always used in conjunction with your specific project.
In fact, each time work commences on a content file that does not have a corresponding project file, a new project file will be created.
The project file extension is ``.project''. The name of the project file is the whole name of the content file with appended extensions.
For instance, a content file named swords.omwaddon is associated with the project file swords.omwaddon.project.
%TODO where are they stored.
Project files are stored inside the user directory, in the \textbf{projects} subfolder. This is both the location of newly created
project files, and the place where \OCS{} looks for already existing files.
\paragraph{Resource files}
%textures, sounds, whatever
The vast majority of modern video games use what we shall term \textbf{resource files}: models, textures, icons, sounds and so on.
ESPs, ESMs and \OMW{} content files do not contain these files, merely instructions on how they are used. It follows that the \OMW{}
engine must be capable of supporting these resource files in order for them to function. Therefore this section covers ways to add
resource files to your content file, and outlines which formats are supported. Later, you will learn how to make use of these files
in your content.
\subparagraph{Audio}
OpenMW utilises {FFmpeg} for audio playback, so we support every audio type supported by this library. This is a huge list.
Below is only a small sample of supported file types.
\begin{description}
\item mp3 ({MPEG}-1 {Part 3 Layer 3}) A popular audio file format and the \textit{de facto} standard for storing audio. Used by
the \MW{} game.
\item ogg Open source, multimedia container file which uses the high quality vorbis audio codec. Recommended.
\end{description}
\subparagraph{Video}
As in the case of audio files, we use {FFmpeg} to decode video files. The list of supported files is long - only the most
significant will be covered.
\begin{description}
\item bik Format used by the original \MW{} game.
\item mp4 Multimedia container which use more advanced codecs ({MPEG-4 Parts 2,3,10}) with a better audio and video compression rate,
but which require more {CPU} intensive decoding -- this probably makes it less suited for storing sounds in computer games, but
good for videos.
\item webm A new, shiny and open source video format with excellent compression. It needs quite a lot of processing power to be decoded,
but since game logic is not running during cut scenes we can recommend it for use with \OMW.
\item ogv An alternative, open source container using theora codec for video and vorbis for audio.
\end{description}
\subparagraph{Textures and images}
\MW{} uses {DDS} and {TGA} files for all kinds of two dimensional images and textures. In addition, the original engine supported BMP
files (although {BMP} is a terrible format for a video game). We also support an extended set of image files -- including {JPEG} and {PNG}.
JPEG and PNG files can be useful in some cases. For instance, a JPEG file is a valid option for a skybox texture and PNG can useful for masks.
However, keep in mind that a JPEG can grow large quickly and so are not the best option with a {DirectX} rendering backend. DDS files
are therefore recommended for textures.
%\subparagraph{Meshes} %TODO once we will support something more than just nifs

@ -1,202 +1,202 @@
\section{Record filters}
\subsection{Introduction}
Filters are the key element of \OCS{} use cases by allowing rapid and easy access to the searched records presented in all tables.
Therefore: in order to use this application fully effective you should make sure that all concepts and instructions written in
the this section of the manual are perfectly clear to you.
Do not be afraid though, filters are fairly intuitive and easy to use.
\subsubsection{Used Terms}
\begin{description}
\item[Filter] is generally speaking a tool able to ``Filter'' (that is: select some elements, while discarding others) according
to the some criteria. In case of \OCS: records are being filtered according to the criteria of user choice. Criteria are written
down in language with simple syntax.
\item[Criteria] describes condition under with any any record is being select by the filter.
\item[Syntax] as you may noticed computers (in general) are rather strict, and expect only strictly formulated orders -- that is:
written with correct syntax.
\item[Expression] is way we are actually performing filtering. Filter can be treated as ``functions'': accepts arguments, and evaluates
either to the true or false for every column record at the time.
\item[N-ary] is any expression that expects one or more expressions as arguments. It is useful for grouping two (or more) other expressions
together in order to create filter that will check for criteria placed in two (again: or more) columns (logical \textit{or}, \textit{and}).
\item[unary] is any expression that expects one other expression. The example is \textit{not} expression. In fact \textit{not} is the only useful
unary expression in \OCS{} record filters.
\item[nullary] is expression that does not accepts other expressions. It accepts arguments specified later.
\end{description}
\subsubsection{Basics}
In fact you do not need to learn everything about filters in order to use them. In fact all you need to know to achieve decent productivity
with \OCS{} is inside basics section.
\subsubsection{Interface}
Above each table there is a field that is used to enter filter: either predefined by the \OMW{} developers or made by you, the user.
You probably noticed it before. However there is also completely new element, although using familiar table layout. Go to the application
menu view, and click filters. You should see set of default filters, made by the \OMW{} team in the table with the following columns: filter,
description and modified.
\begin{description}
\item[ID] contains the name of the filter.
\item[Modified] just like in all other tables you have seen so far modified indicates if a filter was added, modified or removed.
\item[Filter] column containing expression of the filter.
\item[Description] contains the short description of the filter function. Do not expect any surprises there.
\end{description}
So let's learn how to actually use those to speed up your work.
\subsubsection{Using predefined filters}
Using those filters is quite easy and involves typing inside the filter field above the table. For instance, try to open referencables
table and type in the filters field the following: \mono{project::weapons}. As soon as you complete the text, table will magicly alter
and will show only the weapons. As you could noticed \mono{project::weapons} is nothing else than a~ID of one of the predefined filters. That is it:
in order to use the filter inside the table you simply type it is name inside the filter field.
To make life easier filter IDs follow simple convention.
\begin{itemize}
\item Filter ID filtering a specific record type contains usually the name of a specific group. For instance \mono{project::weapons} filter
contains the word weapons (did you noticed?). Plural form is always used.
\item When filtering specific subgroup the ID starts just like in the case of general filter. For instance \mono{project::weaponssilver} will
filter only silver weapons (new mechanic introduced by the \BM{}, silver weapons deal double damage against werewolfs) and
\mono{project::weaponsmagical} will filter only magical weapons (able to hurt ghosts and other supernatural creatures).
\item There are few exceptions from the above rule. For instance there is a \mono{project::added}, \mono{project::removed},
\mono{project::modyfied}, \mono{project::base}.
You would probably except something more like \mono{project::statusadded} but in this case typing this few extra characters would only
help to break your keyboard faster.
\end{itemize}
We strongly recommend to take a look at the filters table right now to see what you can filter with that. And try using it! It is very simple.
\subsection{Advanced}
Back to the manual? Great.
If you want to create your own filter you have to know exactly what do you want to get in order to translate this into the expressions.
Finally, you will have to write this with correct syntax. As a result table will show only desired rows.
Advance subsection covers everything that you need to know in order to create any filter you may want to %TODO the filter part is actually wrong
\subsubsection{Namespaces}
Did you noticed that every default filter has \mono{project::} prefix? It is a \textit{namespace}, a~term borrowed from the \CPP{} language.
In case of \OCS{} namespace always means scope of the said object\footnote{You are not supposed to understand this at the moment.}.
But what does it mean in case of filters? Well, short explanation is actually simple.
\begin{description}
\item[project::] namespace indicates that filter is used with the project, in multiple sessions. You can restart \OCS{} and filter
is still there.
\item[session::] namespace indicates that filter is not stored trough multiple sessions and once you will quit \OCS{} (close session)
the filter will be gone. Forever! Until then it can be found inside the filters table.
\end{description}
In addition to this two scopes, there is a third one; called one-shot. One-shot filters are not stored (even during single session)
anywhere and as the name implies they are supposed to be created when needed only once. Good thing about the one-shot filters is that
you do not need to open filters table in order to create it. Instead you just type it directly inside the filter field, starting with
exclamation mark: ``!''.
Still, you may wonder how you are supposed to write expressions, what expressions you should use, and what syntax looks like. Let's start
with nullary expressions that will allow you to create a basic filter.
\subsubsection{Nullary expressions}
All nullary expressions are used in similar manner. First off: you have to write it is name (for instance: \mono{string}) and secondly:
condition that will be checked inside brackets (for instance \mono{string(something, something)}). If conditions of your expression will be meet
by a record (technical speaking: expression will evaluate to true) the record will show up in the table.
It is clear that you need to know what are you checking, that is: what column of the table contains information that you are interested
in and what should be inside specific cell inside this column to meet your requirements. In most cases first word inside brackets sets column
you want to see, while the second one sets desired value inside of the cell. To separate column argument from the value argument use comma.
\paragraph{String -- string(``column'', ``value'')}
String in programmers language is often\footnote{Often, not always. There are different programming languages using slightly different terms.}
just a word for anything composed of characters. In case of \OCS{} this is in fact true for every value inside the column that is not composed
of the pure numbers. Even columns containing only ``true`` and ``false`` values can be targeted by the string expression\footnote{There is no
Boolean (``true'' or ``false'') value in the \OCS. You should use string for those.}. String evaluates to true,
when record contains in the specified column exactly the same value as specified.
Since majority of the columns contain string values, string is among the most often used expressions. Examples:
\begin{itemize}
\item \mono{string(``Record Type'', ``Weapon'')} -- will evaluate to true for all records containing \mono{Weapon} in the \mono{Record Type} column cell.
This group contains every weapon (including arrows and bolts) found in the game.
\item \mono{string(``Portable'', ``true'')} -- will evaluate to true for all records containing word true inside \mono{Portable} column cell.
This group contains every portable light sources (lanterns, torches etc.).
\end{itemize}
This is probably enough to create around 90 string filters you will eventually need. However, this expression is even more powerful
-- it accepts regular expressions (also called regexps). Regular expressions is a way to create string criteria that will be matched
by one than just one specific value in the column. For instance, you can display both left and right gauntlets with the following expression:
\mono{string("armor type", ".* gauntlet"))} because \mono{.*} in regexps means just: ``anything''. This filter says: please, show me ``any'' gauntlet.
There are left and right gauntlets in the \MW{} so this will evaluate to true for both. Simple, isn't it?
Creating regexps can be a difficult and annoying -- especially when you need complex criteria. On the other hand, we are under impression that in reality complex expressions are needed only in sporadic cases. In fact, the truth is: that most of the time only already mentioned
\mono{.*} is needed and therefore the following description of regexps can be skipped by vast majority of readers.
Before working with Regular Expressions, you should understand what actually are regular expressions. Essentially, the idea is simple:
when you are writing any word, you are using strictly defined letters -- that is: letters create a word. What you want to do with regular
expression is to use set of rules that will match to many words. It is not that difficult to see what it's needed to do so: first,
you will clearly need way to determinate what letters you want to match (word is composed by letters).
Before introducing other ways to choose between characters, I want explain anchors. Anchors allows you to decide where to ``look'' in the string.
You surely should know about \mono{\textasciicircum} anchor and \mono{\textdollar}. Putting \mono{\textasciicircum} will tell to \OCS{}
to look on the beginning of string, while \mono{\textdollar} is used to mark the end of it. For instance, pattern
\mono{\textasciicircum{}Pink.* elephant.\textdollar} will match any sentence beginning with the word \mono{Pink} and ending with
\mono{ elephant.}. Pink fat elephant. Pink cute elephant. It does not matter what is in between because \mono{.*} is used.
You have already seen the power of the simple \mono{.*}. But what if you want to chose between only two (or more) letters? Well, this is when
\mono{[|]} comes in handy. If you write something like: \mono{\textasciicircum[a|k].*} you are simply telling \OCS{} to filter anything that
starts with either \mono{a} or \mono{k}. Using \mono{\textasciicircum[a|k|l].*} will work in the same manner, that is; it will also cover strings starting with \mono{l} as well.
What if you want to match more than just one latter? Just use \mono{(|)}. It is pretty similar to the above one letter as you see, but it is
used to fit more than just one character. For instance: \mono{\textasciicircum(Pink|Green).* (elephant|crocodile).\textdollar} will be
true for all sentences starting with \mono{Pink} or \mono{Green} and ending with either \mono{elephant.} or \mono{crocodile.}.
Regular expressions are not the main topic of this manual. If you wish to learn more on this subject please, read the documentation on
Qt regular expressions syntax, or TRE regexp syntax (it is almost like in Qt). Above is just enough to use \OCS{} effectively.
\paragraph{Value -- value(``value'', (``open'', ``close''))}
While string expression covers vast group of columns containing string values, there are in fact columns with just numerical values like
``weight``. To filter those we need a value expression. This one works in similar manner to the string filter: first token name and criteria
inside brackets. Clearly, conditions should hold column to test in. However in this case wanted value is specified as a range.
As you would imagine the range can be specified as including a border value, or excluding. We are using two types of brackets for this:
\begin{itemize}
\item To include value use [] brackets. For value equal 5, expression \mono{value(something, [5, 10])} will evaluate to true.
\item To exclude value use () brackets. For value equal 5, expression \mono{value(something, (5, 10))} will evaluate to false.
\item Mixing brackets is completely legal. For value equal 10, expression \mono{value(something, [5, 10)} will evaluate to true.
The same expression will evaluate to false for value equal 10.
\end{itemize}
\paragraph{``true'' and ``false''}
Nullary \textit{true} and \textit{false} do not accept any arguments, and always evaluates to true (in case of \textit{true})
and false (in case of \textit{false}) no matter what. The main usage of this expressions is the give users ability to quickly
disable some part of the filter that makes heavy use of the logical expressions.
\subsubsection{Logical expressions}
This subsection takes care of two remaining groups of expressions: binary and unary. The only unary expression present in the \OCS{} is logical
\textit{not}, while the remaining binary expressions are: \textit{or}, \textit{and}. This clearly makes them (from the user point of view)
belonging to the same group of logical expressions.
\paragraph{not -- not expression()}
Sometimes you may be in need of reversing the output of the expression. This is where \textit{not} comes in handy. Adding \textit{not} before
expression will revert it: if expression was returning true, it will return false; if it was returning false, it will return true. Parenthesis are not needed: \textit{not} will revert only the first expression following it.
To show this on know example, let's consider the \mono{string("armor type", ".* gauntlet"))} filter. As we mentioned earlier this will return true
for every gauntlet found in game. In order to show everything, but gauntlets we simply do \mono{not string("armor type", ".* gauntlet"))}.
This is probably not the most useful filter on earth. The real value of \textit{not} expression shines when combined with
\textit{or}, \textit{and} filters.
\paragraph{or -- or(expression1(), expression2())}
\textit{Or} is a expression that will return true if one of the arguments evaluates to true. You can use two or more arguments, separated by the comma.
\textit{Or} expression is useful when showing two different group of records is needed. For instance the standard actor filter is using the following
\mono{or(string(``record type'', npc), string(``record type'', creature))} and will show both npcs and creatures.
\paragraph{and -- and(expression1(), expression2())}
\textit{And} is a expression that will return true if all arguments evaluates to true. As in the case of ``or'' you can use two or more arguments,
separated by a comma.
As we mentioned earlier in the \textit{not} filter, combining \textit{not} with \textit{and} can be very useful. For instance to show all armor types,
excluding gauntlets you can write the following: \mono{and (not string(``armor type'', ``.* gauntlet''), string(``Record Type'', ``Armor''))}.
\subsubsection{Creating and saving filter}
In order to create and save new filter, you should go to the filters table, right click and select option ``add record'' from the context menu.
A horizontal widget group at the bottom of the table should show up. From there you should select a namespace responsible for scope of
the filter (described earlier) and desired ID of the filter. After pressing OK button new entry will show up in the filters table. This filter
does nothing at the moment, since it still lacks expressions. In order to add your formula simply double click the filter cell of the new entry
and write it down there.
Done! You are free to use your filter.
\subsubsection{Replacing the default filters set}
OpenCS allows you to substitute default filters set provided by us, with your own filters. In order to do so you should create a new project,
add desired filters, remove undesired and save. Rename the file to the ``defaultfilters'' (do not forget to remove .omwaddon.project extension)
and place it inside your configuration directory.
The file acts as template for all new project files from now. If you wish to go back to the old default set, simply rename or remove the custom file.
\section{Record filters}
\subsection{Introduction}
Filters are the key element of \OCS{} use cases by allowing rapid and easy access to the searched records presented in all tables.
Therefore: in order to use this application fully effective you should make sure that all concepts and instructions written in
the this section of the manual are perfectly clear to you.
Do not be afraid though, filters are fairly intuitive and easy to use.
\subsubsection{Used Terms}
\begin{description}
\item[Filter] is generally speaking a tool able to ``Filter'' (that is: select some elements, while discarding others) according
to the some criteria. In case of \OCS: records are being filtered according to the criteria of user choice. Criteria are written
down in language with simple syntax.
\item[Criteria] describes condition under with any any record is being select by the filter.
\item[Syntax] as you may noticed computers (in general) are rather strict, and expect only strictly formulated orders -- that is:
written with correct syntax.
\item[Expression] is way we are actually performing filtering. Filter can be treated as ``functions'': accepts arguments, and evaluates
either to the true or false for every column record at the time.
\item[N-ary] is any expression that expects one or more expressions as arguments. It is useful for grouping two (or more) other expressions
together in order to create filter that will check for criteria placed in two (again: or more) columns (logical \textit{or}, \textit{and}).
\item[unary] is any expression that expects one other expression. The example is \textit{not} expression. In fact \textit{not} is the only useful
unary expression in \OCS{} record filters.
\item[nullary] is expression that does not accepts other expressions. It accepts arguments specified later.
\end{description}
\subsubsection{Basics}
In fact you do not need to learn everything about filters in order to use them. In fact all you need to know to achieve decent productivity
with \OCS{} is inside basics section.
\subsubsection{Interface}
Above each table there is a field that is used to enter filter: either predefined by the \OMW{} developers or made by you, the user.
You probably noticed it before. However there is also completely new element, although using familiar table layout. Go to the application
menu view, and click filters. You should see set of default filters, made by the \OMW{} team in the table with the following columns: filter,
description and modified.
\begin{description}
\item[ID] contains the name of the filter.
\item[Modified] just like in all other tables you have seen so far modified indicates if a filter was added, modified or removed.
\item[Filter] column containing expression of the filter.
\item[Description] contains the short description of the filter function. Do not expect any surprises there.
\end{description}
So let's learn how to actually use those to speed up your work.
\subsubsection{Using predefined filters}
Using those filters is quite easy and involves typing inside the filter field above the table. For instance, try to open referencables
table and type in the filters field the following: \mono{project::weapons}. As soon as you complete the text, table will magicly alter
and will show only the weapons. As you could noticed \mono{project::weapons} is nothing else than a~ID of one of the predefined filters. That is it:
in order to use the filter inside the table you simply type it is name inside the filter field.
To make life easier filter IDs follow simple convention.
\begin{itemize}
\item Filter ID filtering a specific record type contains usually the name of a specific group. For instance \mono{project::weapons} filter
contains the word weapons (did you noticed?). Plural form is always used.
\item When filtering specific subgroup the ID starts just like in the case of general filter. For instance \mono{project::weaponssilver} will
filter only silver weapons (new mechanic introduced by the \BM{}, silver weapons deal double damage against werewolfs) and
\mono{project::weaponsmagical} will filter only magical weapons (able to hurt ghosts and other supernatural creatures).
\item There are few exceptions from the above rule. For instance there is a \mono{project::added}, \mono{project::removed},
\mono{project::modyfied}, \mono{project::base}.
You would probably except something more like \mono{project::statusadded} but in this case typing this few extra characters would only
help to break your keyboard faster.
\end{itemize}
We strongly recommend to take a look at the filters table right now to see what you can filter with that. And try using it! It is very simple.
\subsection{Advanced}
Back to the manual? Great.
If you want to create your own filter you have to know exactly what do you want to get in order to translate this into the expressions.
Finally, you will have to write this with correct syntax. As a result table will show only desired rows.
Advance subsection covers everything that you need to know in order to create any filter you may want to %TODO the filter part is actually wrong
\subsubsection{Namespaces}
Did you noticed that every default filter has \mono{project::} prefix? It is a \textit{namespace}, a~term borrowed from the \CPP{} language.
In case of \OCS{} namespace always means scope of the said object\footnote{You are not supposed to understand this at the moment.}.
But what does it mean in case of filters? Well, short explanation is actually simple.
\begin{description}
\item[project::] namespace indicates that filter is used with the project, in multiple sessions. You can restart \OCS{} and filter
is still there.
\item[session::] namespace indicates that filter is not stored trough multiple sessions and once you will quit \OCS{} (close session)
the filter will be gone. Forever! Until then it can be found inside the filters table.
\end{description}
In addition to this two scopes, there is a third one; called one-shot. One-shot filters are not stored (even during single session)
anywhere and as the name implies they are supposed to be created when needed only once. Good thing about the one-shot filters is that
you do not need to open filters table in order to create it. Instead you just type it directly inside the filter field, starting with
exclamation mark: ``!''.
Still, you may wonder how you are supposed to write expressions, what expressions you should use, and what syntax looks like. Let's start
with nullary expressions that will allow you to create a basic filter.
\subsubsection{Nullary expressions}
All nullary expressions are used in similar manner. First off: you have to write it is name (for instance: \mono{string}) and secondly:
condition that will be checked inside brackets (for instance \mono{string(something, something)}). If conditions of your expression will be meet
by a record (technical speaking: expression will evaluate to true) the record will show up in the table.
It is clear that you need to know what are you checking, that is: what column of the table contains information that you are interested
in and what should be inside specific cell inside this column to meet your requirements. In most cases first word inside brackets sets column
you want to see, while the second one sets desired value inside of the cell. To separate column argument from the value argument use comma.
\paragraph{String -- string(``column'', ``value'')}
String in programmers language is often\footnote{Often, not always. There are different programming languages using slightly different terms.}
just a word for anything composed of characters. In case of \OCS{} this is in fact true for every value inside the column that is not composed
of the pure numbers. Even columns containing only ``true`` and ``false`` values can be targeted by the string expression\footnote{There is no
Boolean (``true'' or ``false'') value in the \OCS. You should use string for those.}. String evaluates to true,
when record contains in the specified column exactly the same value as specified.
Since majority of the columns contain string values, string is among the most often used expressions. Examples:
\begin{itemize}
\item \mono{string(``Record Type'', ``Weapon'')} -- will evaluate to true for all records containing \mono{Weapon} in the \mono{Record Type} column cell.
This group contains every weapon (including arrows and bolts) found in the game.
\item \mono{string(``Portable'', ``true'')} -- will evaluate to true for all records containing word true inside \mono{Portable} column cell.
This group contains every portable light sources (lanterns, torches etc.).
\end{itemize}
This is probably enough to create around 90 string filters you will eventually need. However, this expression is even more powerful
-- it accepts regular expressions (also called regexps). Regular expressions is a way to create string criteria that will be matched
by one than just one specific value in the column. For instance, you can display both left and right gauntlets with the following expression:
\mono{string("armor type", ".* gauntlet"))} because \mono{.*} in regexps means just: ``anything''. This filter says: please, show me ``any'' gauntlet.
There are left and right gauntlets in the \MW{} so this will evaluate to true for both. Simple, isn't it?
Creating regexps can be a difficult and annoying -- especially when you need complex criteria. On the other hand, we are under impression that in reality complex expressions are needed only in sporadic cases. In fact, the truth is: that most of the time only already mentioned
\mono{.*} is needed and therefore the following description of regexps can be skipped by vast majority of readers.
Before working with Regular Expressions, you should understand what actually are regular expressions. Essentially, the idea is simple:
when you are writing any word, you are using strictly defined letters -- that is: letters create a word. What you want to do with regular
expression is to use set of rules that will match to many words. It is not that difficult to see what it's needed to do so: first,
you will clearly need way to determinate what letters you want to match (word is composed by letters).
Before introducing other ways to choose between characters, I want explain anchors. Anchors allows you to decide where to ``look'' in the string.
You surely should know about \mono{\textasciicircum} anchor and \mono{\textdollar}. Putting \mono{\textasciicircum} will tell to \OCS{}
to look on the beginning of string, while \mono{\textdollar} is used to mark the end of it. For instance, pattern
\mono{\textasciicircum{}Pink.* elephant.\textdollar} will match any sentence beginning with the word \mono{Pink} and ending with
\mono{ elephant.}. Pink fat elephant. Pink cute elephant. It does not matter what is in between because \mono{.*} is used.
You have already seen the power of the simple \mono{.*}. But what if you want to chose between only two (or more) letters? Well, this is when
\mono{[|]} comes in handy. If you write something like: \mono{\textasciicircum[a|k].*} you are simply telling \OCS{} to filter anything that
starts with either \mono{a} or \mono{k}. Using \mono{\textasciicircum[a|k|l].*} will work in the same manner, that is; it will also cover strings starting with \mono{l} as well.
What if you want to match more than just one latter? Just use \mono{(|)}. It is pretty similar to the above one letter as you see, but it is
used to fit more than just one character. For instance: \mono{\textasciicircum(Pink|Green).* (elephant|crocodile).\textdollar} will be
true for all sentences starting with \mono{Pink} or \mono{Green} and ending with either \mono{elephant.} or \mono{crocodile.}.
Regular expressions are not the main topic of this manual. If you wish to learn more on this subject please, read the documentation on
Qt regular expressions syntax, or TRE regexp syntax (it is almost like in Qt). Above is just enough to use \OCS{} effectively.
\paragraph{Value -- value(``value'', (``open'', ``close''))}
While string expression covers vast group of columns containing string values, there are in fact columns with just numerical values like
``weight``. To filter those we need a value expression. This one works in similar manner to the string filter: first token name and criteria
inside brackets. Clearly, conditions should hold column to test in. However in this case wanted value is specified as a range.
As you would imagine the range can be specified as including a border value, or excluding. We are using two types of brackets for this:
\begin{itemize}
\item To include value use [] brackets. For value equal 5, expression \mono{value(something, [5, 10])} will evaluate to true.
\item To exclude value use () brackets. For value equal 5, expression \mono{value(something, (5, 10))} will evaluate to false.
\item Mixing brackets is completely legal. For value equal 10, expression \mono{value(something, [5, 10)} will evaluate to true.
The same expression will evaluate to false for value equal 10.
\end{itemize}
\paragraph{``true'' and ``false''}
Nullary \textit{true} and \textit{false} do not accept any arguments, and always evaluates to true (in case of \textit{true})
and false (in case of \textit{false}) no matter what. The main usage of this expressions is the give users ability to quickly
disable some part of the filter that makes heavy use of the logical expressions.
\subsubsection{Logical expressions}
This subsection takes care of two remaining groups of expressions: binary and unary. The only unary expression present in the \OCS{} is logical
\textit{not}, while the remaining binary expressions are: \textit{or}, \textit{and}. This clearly makes them (from the user point of view)
belonging to the same group of logical expressions.
\paragraph{not -- not expression()}
Sometimes you may be in need of reversing the output of the expression. This is where \textit{not} comes in handy. Adding \textit{not} before
expression will revert it: if expression was returning true, it will return false; if it was returning false, it will return true. Parenthesis are not needed: \textit{not} will revert only the first expression following it.
To show this on know example, let's consider the \mono{string("armor type", ".* gauntlet"))} filter. As we mentioned earlier this will return true
for every gauntlet found in game. In order to show everything, but gauntlets we simply do \mono{not string("armor type", ".* gauntlet"))}.
This is probably not the most useful filter on earth. The real value of \textit{not} expression shines when combined with
\textit{or}, \textit{and} filters.
\paragraph{or -- or(expression1(), expression2())}
\textit{Or} is a expression that will return true if one of the arguments evaluates to true. You can use two or more arguments, separated by the comma.
\textit{Or} expression is useful when showing two different group of records is needed. For instance the standard actor filter is using the following
\mono{or(string(``record type'', npc), string(``record type'', creature))} and will show both npcs and creatures.
\paragraph{and -- and(expression1(), expression2())}
\textit{And} is a expression that will return true if all arguments evaluates to true. As in the case of ``or'' you can use two or more arguments,
separated by a comma.
As we mentioned earlier in the \textit{not} filter, combining \textit{not} with \textit{and} can be very useful. For instance to show all armor types,
excluding gauntlets you can write the following: \mono{and (not string(``armor type'', ``.* gauntlet''), string(``Record Type'', ``Armor''))}.
\subsubsection{Creating and saving filter}
In order to create and save new filter, you should go to the filters table, right click and select option ``add record'' from the context menu.
A horizontal widget group at the bottom of the table should show up. From there you should select a namespace responsible for scope of
the filter (described earlier) and desired ID of the filter. After pressing OK button new entry will show up in the filters table. This filter
does nothing at the moment, since it still lacks expressions. In order to add your formula simply double click the filter cell of the new entry
and write it down there.
Done! You are free to use your filter.
\subsubsection{Replacing the default filters set}
OpenCS allows you to substitute default filters set provided by us, with your own filters. In order to do so you should create a new project,
add desired filters, remove undesired and save. Rename the file to the ``defaultfilters'' (do not forget to remove .omwaddon.project extension)
and place it inside your configuration directory.
The file acts as template for all new project files from now. If you wish to go back to the old default set, simply rename or remove the custom file.

@ -1,37 +1,37 @@
\documentclass[american]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{txfonts} % Public Times New Roman text & math font
\usepackage[pdftex]{graphicx}
\usepackage[final,colorlinks,pdftex,pdfpagelabels=true]{hyperref}
\author{OpenMW Team}
\def\pdfBorderAttrs{/Border [0 0 0] } % No border arround Links
\def\CPP{{C\kern-.05em\raise.23ex\hbox{+\kern-.05em+}}}
\hypersetup{%
pdfauthor={Copyright \textcopyright{} OpenMW Team },
pdftitle={OpenCS user manual}
}
\def\mono{\texttt}
\def\MW{\textit{Morrowind\texttrademark{}}}
\def\TB{\textit{Tribunal}}
\def\BM{\textit{Bloodmon}}
\def\BS{Bethesda Softworks}
\def\OMW{\hbox{OpenMW}}
\def\OCS{\hbox{OpenCS}}
\begin{document}
\title{OpenCS User Manual}
\maketitle
\newpage
\tableofcontents{}
\newpage
\input{files_and_directories}
\input{creating_file}
\input{windows}
\input{tables}
\input{recordtypes}
\input{filters}
\end{document}
\documentclass[american]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{txfonts} % Public Times New Roman text & math font
\usepackage[pdftex]{graphicx}
\usepackage[final,colorlinks,pdftex,pdfpagelabels=true]{hyperref}
\author{OpenMW Team}
\def\pdfBorderAttrs{/Border [0 0 0] } % No border arround Links
\def\CPP{{C\kern-.05em\raise.23ex\hbox{+\kern-.05em+}}}
\hypersetup{%
pdfauthor={Copyright \textcopyright{} OpenMW Team },
pdftitle={OpenCS user manual}
}
\def\mono{\texttt}
\def\MW{\textit{Morrowind\texttrademark{}}}
\def\TB{\textit{Tribunal}}
\def\BM{\textit{Bloodmon}}
\def\BS{Bethesda Softworks}
\def\OMW{\hbox{OpenMW}}
\def\OCS{\hbox{OpenCS}}
\begin{document}
\title{OpenCS User Manual}
\maketitle
\newpage
\tableofcontents{}
\newpage
\input{files_and_directories}
\input{creating_file}
\input{windows}
\input{tables}
\input{recordtypes}
\input{filters}
\end{document}

@ -1,18 +1,18 @@
\section{Record Types}
\subsection{Introduction}
A gameworld contains many items, such as chests, weapons and monsters. All these items are merely instances of templates that we call \textbf{Objects}. The OpenCS \textbf{Objects} table contains information about each of these template objects, eg. its value and weight in the case of items and an aggression level in the case of NPCs.
Let's go through all Record Types and discuss what you can tell OpenCS about them.
\begin{description}
\item[Activator:] When the player enters the same cell as this object, a script is started. Often it also has a \textbf{Script} attached to it, though it not mandatory. These scripts are small bits of code written in a special scripting language that OpenCS can read and interpret.
\item[Potion:] This is a potion that is not self-made. It has an \textbf{Icon} for your inventory, Aside from the self-explanatory \textbf{Weight} and \textbf{Coin Value}, it has an attribute called \textbf{Auto Calc} set to ``False''. This means that the effects of this potion are pre-configured. This does not happen when the player makes their own potion.
\item[Apparatus:] This is a tool to make potions. Again there's an icon for your inventory as well as a weight and a coin value. It also has a \textbf{Quality} value attached to it: higher the number, the better the effect on your potions will be. The \textbf{Apparatus Type} describes if the item is a Calcinator, Retort, Alembic or Mortar \& Pestle. Each has a different effect on the potion the player makes. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Alchemy#Tools}{UESP page on Alchemy Tools}.
\item[Armor:] This type of item adds \textbf{Enchantment Points} to the mix. Every piece of clothing or armor has a ''pool'' of potential Magicka that gets unlocked when you enchant it. Strong enchantments consume more Magicka from this pool: the stronger the enchantment, the more Enchantment Points each cast will take up. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Enchant}{Enchant page on UESP}. \textbf{Health} means the amount of hit points this piece of armor has. If it sustains enough damage, the armor will be destroyed. Finally, \textbf{Armor Value} tells the game how much points to add to the player character's Armor Rating.
\item[Book:] This includes scrolls and notes. For the game to make the distinction between books and scrolls, an extra property, \textbf{Scroll}, has been added. Under the \textbf{Skill} column a scroll or book can have an in-game skill listed. Reading this item will raise the player's level in that specific skill. For more information on this, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Skill_Books}{Skill Books page on UESP}.
\item[Clothing:] These items work just like Armors, but confer no protective properties. Rather than ``Armor Type'', these items have a ``Clothing Type''.
\item[Container:] This is all the stuff that stores items, from chests to sacks to plants. Its \textbf{Capacity} shows how much stuff you can put in the container. You can compare it to the maximum allowed load a player character can carry (who will get over-encumbered and unable to move if he crosses this threshold). A container, however, will just refuse to take the item in question when it gets ''over-encumbered''. \textbf{Organic Container}s are containers such as plants. Containers that \textbf{Respawn} are not safe to store stuff in. After a certain amount of time they will reset to their default contents, meaning that everything in it is gone forever.
\item[Creature:] These can be monsters, animals and the like.
\end{description}
\section{Record Types}
\subsection{Introduction}
A gameworld contains many items, such as chests, weapons and monsters. All these items are merely instances of templates that we call \textbf{Objects}. The OpenCS \textbf{Objects} table contains information about each of these template objects, eg. its value and weight in the case of items and an aggression level in the case of NPCs.
Let's go through all Record Types and discuss what you can tell OpenCS about them.
\begin{description}
\item[Activator:] When the player enters the same cell as this object, a script is started. Often it also has a \textbf{Script} attached to it, though it not mandatory. These scripts are small bits of code written in a special scripting language that OpenCS can read and interpret.
\item[Potion:] This is a potion that is not self-made. It has an \textbf{Icon} for your inventory, Aside from the self-explanatory \textbf{Weight} and \textbf{Coin Value}, it has an attribute called \textbf{Auto Calc} set to ``False''. This means that the effects of this potion are pre-configured. This does not happen when the player makes their own potion.
\item[Apparatus:] This is a tool to make potions. Again there's an icon for your inventory as well as a weight and a coin value. It also has a \textbf{Quality} value attached to it: higher the number, the better the effect on your potions will be. The \textbf{Apparatus Type} describes if the item is a Calcinator, Retort, Alembic or Mortar \& Pestle. Each has a different effect on the potion the player makes. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Alchemy#Tools}{UESP page on Alchemy Tools}.
\item[Armor:] This type of item adds \textbf{Enchantment Points} to the mix. Every piece of clothing or armor has a ''pool'' of potential Magicka that gets unlocked when you enchant it. Strong enchantments consume more Magicka from this pool: the stronger the enchantment, the more Enchantment Points each cast will take up. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Enchant}{Enchant page on UESP}. \textbf{Health} means the amount of hit points this piece of armor has. If it sustains enough damage, the armor will be destroyed. Finally, \textbf{Armor Value} tells the game how much points to add to the player character's Armor Rating.
\item[Book:] This includes scrolls and notes. For the game to make the distinction between books and scrolls, an extra property, \textbf{Scroll}, has been added. Under the \textbf{Skill} column a scroll or book can have an in-game skill listed. Reading this item will raise the player's level in that specific skill. For more information on this, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Skill_Books}{Skill Books page on UESP}.
\item[Clothing:] These items work just like Armors, but confer no protective properties. Rather than ``Armor Type'', these items have a ``Clothing Type''.
\item[Container:] This is all the stuff that stores items, from chests to sacks to plants. Its \textbf{Capacity} shows how much stuff you can put in the container. You can compare it to the maximum allowed load a player character can carry (who will get over-encumbered and unable to move if he crosses this threshold). A container, however, will just refuse to take the item in question when it gets ''over-encumbered''. \textbf{Organic Container}s are containers such as plants. Containers that \textbf{Respawn} are not safe to store stuff in. After a certain amount of time they will reset to their default contents, meaning that everything in it is gone forever.
\item[Creature:] These can be monsters, animals and the like.
\end{description}

@ -1,94 +1,94 @@
\section{Tables}
\subsection{Introduction}
If you have launched \OCS{} already and played around with it for a bit, you have probably gotten the impression that it contains lots of tables.
You'd be spot on: \OCS{} is built around using tables. This does not mean it works just like Microsoft Excel or Libre Office Calc, though.
Due to the vast amounts of information involved with \MW, tables just made the most sense. You have to be able to spot information quickly
and be able to change them on the fly.
Let's browse through the various screens and see what all these tables show.
\subsection{Used Terms}
\subsubsection{Glossary}
\begin{description}
\item[Record:] An entry in \OCS{} representing an item, location, sound, NPC or anything else.
\item[Instance, Object:] When an item is placed in the world, it isn't an isolated and unique object. For example, the game world might contain a lot of exquisite belts on different NPCs and in many crates, but they all refer to one specific record in the game's library: the Exquisite Belt record. In this case, all those belts in crates and on NPCs are \textbf{instances}. The central Exquisite Belt record is called a \textbf{object}. This allows modders to make changes to all items of the same type. For example, if you want all exquisite belts to have 4000 enchantment points rather than 400, you will only need to change the \textbf{object} Exquisite Belt rather than all exquisite belts \textbf{instances} individually.
\end{description}
\subsubsection{Recurring Terms}
Some columns are recurring throughout \OCS. They show up in (nearly) every table in \OCS.
\begin{description}
\item[ID] Many items in the OpenCS database have a unique identifier in both OpenCS and Morrowind. This is usually a very self-explanatory name. For example, the ID for the (unique) black pants of Caius Cosades is ``Caius\_pants''. This allows you to manipulate the game in many ways. For example, you could add these pants to your inventory by simply opening the console and write: ``player->addItem Caius\_pants''. Either way, in both Morrowind and OpenCS, the ID is the primary way to identify all these different parts of the game.
\item[Modified] This column shows what has happened (if something has happened) to this record. There are four possible states in which it can exist.
\item[Base] means that this record is part of the base game and is in its original state. Usually, if you create a mod, the base game is Morrowind with
optionally the Bloodmoon and Tribunal expansions.
\item[Added] means that this record was not in the base game and has been added by a~modder.
\item[Modified] means that the record is part of the base game, but has been changed in some way.
\item[Deleted] means that this record used to be part of the base game, but has been removed as an entry. This does not mean, however, that the occurrences
in the game itself have been removed! For example, if you remove the CharGen\_Bed entry from morrowind.esm, it does not mean the bedroll in the basement
of the Census and Excise Office in Seyda Neen is gone. You're going to have to delete that instance yourself or make sure that that object is replaced
by something that still exists otherwise you will get crashes in the worst case scenario.
\end{description}
\subsection{World Screens}
The contents of the game world can be changed by choosing one of the options in the appropriate menu at the top of the screen.
\subsubsection{Regions}
This describes the general areas of the gameworld. Each of these areas has different rules about things such as encounters and weather.
\begin{description}
\item[Name:] This is how the game will show your location in-game.
\item[Map Colour:] This is a six-digit hexadecimal representation of the color used to identify the region on the map available in
World > Region Map. If you do not have an application with a color picker, you can use your favorite search engine to find a color picker on-line.
\item[Sleep Encounter:] These are the rules for what kind of enemies you might encounter when you sleep outside in the wild.
\end{description}
\subsubsection{Cells}
Expansive worlds such as Vvardenfell, with all its items, NPCs, etc. have a lot going on simultaneously. But if you are in Balmora,
why would the computer need to keep track the exact locations of NPCs walking through the corridors in a Vivec canton? All that work would
be quite useless and bring your system to its knees! So the world has been divided up into squares we call "cells". Once your character enters a cell,
the game will load everything that is going on in that cell so you can interact with it.
In the original \MW{} this could be seen when you were traveling and you would see a small loading bar at the bottom of the screen;
you had just entered a new cell and the game would have to load all the items and NPCs. The Cells screen in \OCS{} provides you with a list of cells
in the game, both the interior cells (houses, dungeons, mines, etc.) and the exterior cells (the outside world).
\begin{description}
\item[Sleep Forbidden:] Can the player sleep on the floor? In most cities it is forbidden to sleep outside. Sleeping in the wild carries its
own risks of attack, though, and this entry lets you decide if a player should be allowed to sleep on the floor in this cell or not.
\item[Interior Water:] Should water be rendered in this interior cell? The game world consists of an endless ocean at height 0. Then the landscape
is added. If part of the landscape goes below height 0, the player will see water. (See illustration.)
Setting the cell's Interior Water to true tells the game that this cell is both an interior cell (inside a building, for example, rather than
in the open air) but that there still needs to be water at height 0. This is useful for dungeons or mines that have water in them.
Setting the cell's Interior Water to false tells the game that the water at height 0 should not be used. Remember that cells that are in
the outside world are exterior cells and should thus \textit{always} be set to false!
\item[Interior Sky:] Should this interior cell have a sky? This is a rather unique case. The \TB{} expansion took place in a city on
the mainland. Normally this would require the city to be composed of exterior cells so it has a sky, weather and the like. But if the player is
in an exterior cell and looks at his in-game map, he sees the map of the gameworld with an overview of all exterior cells. The player would have to see
the city's very own map, as if he was walking around in an interior cell.
So the developers decided to create a workaround and take a bit of both: The whole city would technically work exactly like an interior cell,
but it would need a sky as if it was an exterior cell. That is what this is. This is why the vast majority of the cells you will find in this screen
will have this option set to false: It is only meant for these "fake exteriors".
\item[Region:] To which Region does this cell belong? This has an impact on the way the game handles weather and encounters in this area.
It is also possible for a cell not to belong to any region.
\end{description}
\subsubsection{Objects}
This is a library of all the items, triggers, containers, NPCs, etc. in the game. There are several kinds of Record Types. Depending on which type
a record is, it will need specific information to function. For example, an NPC needs a value attached to its aggression level. A chest, of course,
does not. All Record Types contain at least a~model. How else would the player see them? Usually they also have a Name, which is what you see
when you hover your reticle over the object.
This is a library of all the items, triggers, containers, NPCs, etc. in the game. There are several kinds of Record Types. Depending on which type a record is, it will need specific information to function. For example, an NPC needs a value attached to its aggression level. A chest, of course, does not. All Record Types contain at least a model. How else would the player see them? Usually they also have a Name, which is what you see when you hover your reticle over the object.
Please refer to the Record Types section for an overview of what each type of object does and what you can tell OpenCS about these objects.
\section{Tables}
\subsection{Introduction}
If you have launched \OCS{} already and played around with it for a bit, you have probably gotten the impression that it contains lots of tables.
You'd be spot on: \OCS{} is built around using tables. This does not mean it works just like Microsoft Excel or Libre Office Calc, though.
Due to the vast amounts of information involved with \MW, tables just made the most sense. You have to be able to spot information quickly
and be able to change them on the fly.
Let's browse through the various screens and see what all these tables show.
\subsection{Used Terms}
\subsubsection{Glossary}
\begin{description}
\item[Record:] An entry in \OCS{} representing an item, location, sound, NPC or anything else.
\item[Instance, Object:] When an item is placed in the world, it isn't an isolated and unique object. For example, the game world might contain a lot of exquisite belts on different NPCs and in many crates, but they all refer to one specific record in the game's library: the Exquisite Belt record. In this case, all those belts in crates and on NPCs are \textbf{instances}. The central Exquisite Belt record is called a \textbf{object}. This allows modders to make changes to all items of the same type. For example, if you want all exquisite belts to have 4000 enchantment points rather than 400, you will only need to change the \textbf{object} Exquisite Belt rather than all exquisite belts \textbf{instances} individually.
\end{description}
\subsubsection{Recurring Terms}
Some columns are recurring throughout \OCS. They show up in (nearly) every table in \OCS.
\begin{description}
\item[ID] Many items in the OpenCS database have a unique identifier in both OpenCS and Morrowind. This is usually a very self-explanatory name. For example, the ID for the (unique) black pants of Caius Cosades is ``Caius\_pants''. This allows you to manipulate the game in many ways. For example, you could add these pants to your inventory by simply opening the console and write: ``player->addItem Caius\_pants''. Either way, in both Morrowind and OpenCS, the ID is the primary way to identify all these different parts of the game.
\item[Modified] This column shows what has happened (if something has happened) to this record. There are four possible states in which it can exist.
\item[Base] means that this record is part of the base game and is in its original state. Usually, if you create a mod, the base game is Morrowind with
optionally the Bloodmoon and Tribunal expansions.
\item[Added] means that this record was not in the base game and has been added by a~modder.
\item[Modified] means that the record is part of the base game, but has been changed in some way.
\item[Deleted] means that this record used to be part of the base game, but has been removed as an entry. This does not mean, however, that the occurrences
in the game itself have been removed! For example, if you remove the CharGen\_Bed entry from morrowind.esm, it does not mean the bedroll in the basement
of the Census and Excise Office in Seyda Neen is gone. You're going to have to delete that instance yourself or make sure that that object is replaced
by something that still exists otherwise you will get crashes in the worst case scenario.
\end{description}
\subsection{World Screens}
The contents of the game world can be changed by choosing one of the options in the appropriate menu at the top of the screen.
\subsubsection{Regions}
This describes the general areas of the gameworld. Each of these areas has different rules about things such as encounters and weather.
\begin{description}
\item[Name:] This is how the game will show your location in-game.
\item[Map Colour:] This is a six-digit hexadecimal representation of the color used to identify the region on the map available in
World > Region Map. If you do not have an application with a color picker, you can use your favorite search engine to find a color picker on-line.
\item[Sleep Encounter:] These are the rules for what kind of enemies you might encounter when you sleep outside in the wild.
\end{description}
\subsubsection{Cells}
Expansive worlds such as Vvardenfell, with all its items, NPCs, etc. have a lot going on simultaneously. But if you are in Balmora,
why would the computer need to keep track the exact locations of NPCs walking through the corridors in a Vivec canton? All that work would
be quite useless and bring your system to its knees! So the world has been divided up into squares we call "cells". Once your character enters a cell,
the game will load everything that is going on in that cell so you can interact with it.
In the original \MW{} this could be seen when you were traveling and you would see a small loading bar at the bottom of the screen;
you had just entered a new cell and the game would have to load all the items and NPCs. The Cells screen in \OCS{} provides you with a list of cells
in the game, both the interior cells (houses, dungeons, mines, etc.) and the exterior cells (the outside world).
\begin{description}
\item[Sleep Forbidden:] Can the player sleep on the floor? In most cities it is forbidden to sleep outside. Sleeping in the wild carries its
own risks of attack, though, and this entry lets you decide if a player should be allowed to sleep on the floor in this cell or not.
\item[Interior Water:] Should water be rendered in this interior cell? The game world consists of an endless ocean at height 0. Then the landscape
is added. If part of the landscape goes below height 0, the player will see water. (See illustration.)
Setting the cell's Interior Water to true tells the game that this cell is both an interior cell (inside a building, for example, rather than
in the open air) but that there still needs to be water at height 0. This is useful for dungeons or mines that have water in them.
Setting the cell's Interior Water to false tells the game that the water at height 0 should not be used. Remember that cells that are in
the outside world are exterior cells and should thus \textit{always} be set to false!
\item[Interior Sky:] Should this interior cell have a sky? This is a rather unique case. The \TB{} expansion took place in a city on
the mainland. Normally this would require the city to be composed of exterior cells so it has a sky, weather and the like. But if the player is
in an exterior cell and looks at his in-game map, he sees the map of the gameworld with an overview of all exterior cells. The player would have to see
the city's very own map, as if he was walking around in an interior cell.
So the developers decided to create a workaround and take a bit of both: The whole city would technically work exactly like an interior cell,
but it would need a sky as if it was an exterior cell. That is what this is. This is why the vast majority of the cells you will find in this screen
will have this option set to false: It is only meant for these "fake exteriors".
\item[Region:] To which Region does this cell belong? This has an impact on the way the game handles weather and encounters in this area.
It is also possible for a cell not to belong to any region.
\end{description}
\subsubsection{Objects}
This is a library of all the items, triggers, containers, NPCs, etc. in the game. There are several kinds of Record Types. Depending on which type
a record is, it will need specific information to function. For example, an NPC needs a value attached to its aggression level. A chest, of course,
does not. All Record Types contain at least a~model. How else would the player see them? Usually they also have a Name, which is what you see
when you hover your reticle over the object.
This is a library of all the items, triggers, containers, NPCs, etc. in the game. There are several kinds of Record Types. Depending on which type a record is, it will need specific information to function. For example, an NPC needs a value attached to its aggression level. A chest, of course, does not. All Record Types contain at least a model. How else would the player see them? Usually they also have a Name, which is what you see when you hover your reticle over the object.
Please refer to the Record Types section for an overview of what each type of object does and what you can tell OpenCS about these objects.

@ -1,54 +1,54 @@
\section{Windows}
\subsection{Introduction}
This section describes the multiple windows interface of the \OCS{} editor. This design principle was chosen in order
to extend the flexibility of the editor, especially on the multiple screens setups and on environments providing advanced
windows management features, like for instance: multiple desktops found commonly on many open source desktop environments.
However, it is enough to have a single large screen to see the advantages of this concept.
OpenCS windows interface is easy to describe and understand. In fact we decided to minimize use of many windows concepts
applied commonly in various applications. For instance dialog windows are really hard to find in the \OCS. You are free to try,
though.
Because of this, and the fact that we expect that user is familiar with other applications using windows this section is mostly
focused on practical ways of organizing work with the \OCS.
\subsection{Basics}
After starting \OCS{} and choosing content files to use a editor window should show up. It probably does not look surprising:
there is a menubar at the top, and there is a~large empty area. That is it: a brand new \OCS{} window contains only menubar
and statusbar. In order to make it a little bit more useful you probably want to enable some panels\footnote{Also known as widgets.}.
You are free to do so, just try to explore the menubar.
You probably founded out the way to enable and disable some interesting tables, but those will be described later. For now, let's
just focus on the windows itself.
\paragraph{Creating new windows}
is easy! Just visit view menu, and use the ``New View'' item. Suddenly, out of the blue a new window will show up. As you would expect,
it is also blank, and you are free to add any of the \OCS{} panels.
\paragraph{Closing opened window}
is also easy! Simply close that window decoration button. We suspect that you knew that already, but better to be sure.
Closing last \OCS{} window will also terminate application session.
\paragraph{Multi-everything}
is the main foundation of \OCS{} interface. You are free to create as many windows as you want to, free to populate it with
any panels you may want to, and move everything as you wish to -- even if it makes no sense at all. If you just got crazy idea and
you are wonder if you are able to have one hundred \OCS{} windows showing panels of the same type, well most likely you are
able to do so.
The principle behind this design decision is easy to see for \BS{} made editor, but maybe not so clear for users who are
just about to begin their wonderful journey of modding.
\subsection{Advanced}
So why? Why this is created in such manner. The answer is frankly simple: because it is effective. When creating a mod, you often
have to work only with just one table. For instance you are just balancing weapons damage and other statistics. It makes sense
to have all the space for just that one table. More often, you are required to work with two and switch them from time to time.
All major graphical environments commonly present in operating systems comes with switcher feature, that is a key shortcut to change
active window. It is very effective and fast when you have only two windows, each holding only one table. Sometimes you have to work
with two at the time, and with one from time to time. Here, you can have one window holding two tables, and second holding just one.
OpenCS is designed to simply make sense and do not slowdown users. It is as simple as possible (but not simpler), and uses one
flexible approach in all cases.
There is no point in digging deeper in the windows of \OCS. Let's explore panels, starting with tables.
\section{Windows}
\subsection{Introduction}
This section describes the multiple windows interface of the \OCS{} editor. This design principle was chosen in order
to extend the flexibility of the editor, especially on the multiple screens setups and on environments providing advanced
windows management features, like for instance: multiple desktops found commonly on many open source desktop environments.
However, it is enough to have a single large screen to see the advantages of this concept.
OpenCS windows interface is easy to describe and understand. In fact we decided to minimize use of many windows concepts
applied commonly in various applications. For instance dialog windows are really hard to find in the \OCS. You are free to try,
though.
Because of this, and the fact that we expect that user is familiar with other applications using windows this section is mostly
focused on practical ways of organizing work with the \OCS.
\subsection{Basics}
After starting \OCS{} and choosing content files to use a editor window should show up. It probably does not look surprising:
there is a menubar at the top, and there is a~large empty area. That is it: a brand new \OCS{} window contains only menubar
and statusbar. In order to make it a little bit more useful you probably want to enable some panels\footnote{Also known as widgets.}.
You are free to do so, just try to explore the menubar.
You probably founded out the way to enable and disable some interesting tables, but those will be described later. For now, let's
just focus on the windows itself.
\paragraph{Creating new windows}
is easy! Just visit view menu, and use the ``New View'' item. Suddenly, out of the blue a new window will show up. As you would expect,
it is also blank, and you are free to add any of the \OCS{} panels.
\paragraph{Closing opened window}
is also easy! Simply close that window decoration button. We suspect that you knew that already, but better to be sure.
Closing last \OCS{} window will also terminate application session.
\paragraph{Multi-everything}
is the main foundation of \OCS{} interface. You are free to create as many windows as you want to, free to populate it with
any panels you may want to, and move everything as you wish to -- even if it makes no sense at all. If you just got crazy idea and
you are wonder if you are able to have one hundred \OCS{} windows showing panels of the same type, well most likely you are
able to do so.
The principle behind this design decision is easy to see for \BS{} made editor, but maybe not so clear for users who are
just about to begin their wonderful journey of modding.
\subsection{Advanced}
So why? Why this is created in such manner. The answer is frankly simple: because it is effective. When creating a mod, you often
have to work only with just one table. For instance you are just balancing weapons damage and other statistics. It makes sense
to have all the space for just that one table. More often, you are required to work with two and switch them from time to time.
All major graphical environments commonly present in operating systems comes with switcher feature, that is a key shortcut to change
active window. It is very effective and fast when you have only two windows, each holding only one table. Sometimes you have to work
with two at the time, and with one from time to time. Here, you can have one window holding two tables, and second holding just one.
OpenCS is designed to simply make sense and do not slowdown users. It is as simple as possible (but not simpler), and uses one
flexible approach in all cases.
There is no point in digging deeper in the windows of \OCS. Let's explore panels, starting with tables.
%We should write some tips and tricks here.
Loading…
Cancel
Save