Merge remote-tracking branch 'origin/master' into createfix

This commit is contained in:
Marc Zinnschlag 2016-03-01 11:21:25 +01:00
commit e4f341d4ba
15 changed files with 124 additions and 107 deletions

View file

@ -278,8 +278,12 @@ namespace MWBase
virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0;
virtual MWWorld::Ptr safePlaceObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos) = 0;
///< place an object in a "safe" location (ie not in the void, etc).
virtual MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos) = 0;
///< Place an object. Makes a copy of the Ptr.
virtual MWWorld::Ptr safePlaceObject (const MWWorld::ConstPtr& ptr, const MWWorld::ConstPtr& referenceObject, MWWorld::CellStore* referenceCell, int direction, float distance) = 0;
///< Place an object in a safe place next to \a referenceObject. \a direction and \a distance specify the wanted placement
/// relative to \a referenceObject (but the object may be placed somewhere else if the wanted location is obstructed).
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
const = 0;

View file

@ -120,7 +120,7 @@ namespace MWClass
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
MWWorld::ManualRef ref(store, id);
ref.getPtr().getCellRef().setPosition(ptr.getCellRef().getPosition());
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().getPosition());
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().getPosition());
customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId();
customData.mSpawn = false;
}

View file

@ -67,46 +67,29 @@ namespace MWGui
{
MWMechanics::Alchemy::Result result = mAlchemy->create (mNameEdit->getCaption ());
if (result == MWMechanics::Alchemy::Result_NoName)
switch (result)
{
case MWMechanics::Alchemy::Result_NoName:
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage37}");
return;
}
// check if mortar & pestle is available (always needed)
if (result == MWMechanics::Alchemy::Result_NoMortarAndPestle)
{
break;
case MWMechanics::Alchemy::Result_NoMortarAndPestle:
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage45}");
return;
}
// make sure 2 or more ingredients were selected
if (result == MWMechanics::Alchemy::Result_LessThanTwoIngredients)
{
break;
case MWMechanics::Alchemy::Result_LessThanTwoIngredients:
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage6a}");
return;
}
if (result == MWMechanics::Alchemy::Result_NoEffects)
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage8}");
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
return;
}
if (result == MWMechanics::Alchemy::Result_Success)
{
break;
case MWMechanics::Alchemy::Result_Success:
MWBase::Environment::get().getWindowManager()->messageBox("#{sPotionSuccess}");
MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f);
}
else if (result == MWMechanics::Alchemy::Result_RandomFailure)
{
// potion failed
break;
case MWMechanics::Alchemy::Result_NoEffects:
case MWMechanics::Alchemy::Result_RandomFailure:
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage8}");
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
break;
}
// reduce count of the ingredients
// remove ingredient slots that have been fully used up
for (int i=0; i<4; ++i)
if (mIngredients[i]->isUserString("ToolTipType"))
{

View file

@ -114,31 +114,16 @@ namespace MWMechanics
bool found = creatureMap.find(std::make_pair(it->first, it->second)) != creatureMap.end();
if (!found)
{
ESM::Position ipos = mActor.getRefData().getPosition();
osg::Vec3f pos(ipos.asVec3());
osg::Quat rot (-ipos.rot[2], osg::Vec3f(0,0,1));
const float distance = 50;
pos = pos + (rot * osg::Vec3f(0,1,0)) * distance;
ipos.pos[0] = pos.x();
ipos.pos[1] = pos.y();
ipos.pos[2] = pos.z();
ipos.rot[0] = 0;
ipos.rot[1] = 0;
ipos.rot[2] = 0;
const std::string& creatureGmst = summonMap[it->first];
std::string creatureID =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(creatureGmst)->getString();
if (!creatureID.empty())
{
MWWorld::CellStore* store = mActor.getCell();
int creatureActorId = -1;
try
{
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1);
ref.getPtr().getCellRef().setPosition(ipos);
MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr());
@ -147,7 +132,7 @@ namespace MWMechanics
summonedCreatureStats.getAiSequence().stack(package, ref.getPtr());
creatureActorId = summonedCreatureStats.getActorId();
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos);
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), mActor, mActor.getCell(), 0, 120.f);
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(placed);
if (anim)

View file

@ -1353,9 +1353,24 @@ namespace MWRender
if (found != getNodeMap().end())
{
osg::MatrixTransform* node = found->second;
mHeadController = new RotateController(mObjectRoot.get());
node->addUpdateCallback(mHeadController);
mActiveControllers.insert(std::make_pair(node, mHeadController));
bool foundKeyframeCtrl = false;
osg::Callback* cb = node->getUpdateCallback();
while (cb)
{
if (dynamic_cast<NifOsg::KeyframeController*>(cb))
{
foundKeyframeCtrl = true;
break;
}
}
if (foundKeyframeCtrl)
{
mHeadController = new RotateController(mObjectRoot.get());
node->addUpdateCallback(mHeadController);
mActiveControllers.insert(std::make_pair(node, mHeadController));
}
}
}
}

View file

@ -9,7 +9,6 @@
#include <osg/Geometry>
#include <osg/Material>
#include <osg/PositionAttitudeTransform>
#include <osg/Depth>
#include <osg/ClipNode>
#include <osg/MatrixTransform>
#include <osg/FrontFace>

View file

@ -434,7 +434,7 @@ namespace MWScript
pos.rot[2] = osg::DegreesToRadians(zRotDegrees);
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
ref.getPtr().getCellRef().setPosition(pos);
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos);
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(),store,pos);
placed.getClass().adjustPosition(placed, true);
}
}
@ -482,7 +482,7 @@ namespace MWScript
pos.rot[2] = osg::DegreesToRadians(zRotDegrees);
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
ref.getPtr().getCellRef().setPosition(pos);
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos);
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(),store,pos);
placed.getClass().adjustPosition(placed, true);
}
};
@ -516,38 +516,10 @@ namespace MWScript
for (int i=0; i<count; ++i)
{
ESM::Position ipos = actor.getRefData().getPosition();
osg::Vec3f pos(ipos.asVec3());
osg::Quat rot(ipos.rot[2], osg::Vec3f(0,0,-1));
if(direction == 0) pos = pos + (rot * osg::Vec3f(0,1,0)) * distance;
else if(direction == 1) pos = pos - (rot * osg::Vec3f(0,1,0)) * distance;
else if(direction == 2) pos = pos - (rot * osg::Vec3f(1,0,0)) * distance;
else if(direction == 3) pos = pos + (rot * osg::Vec3f(1,0,0)) * distance;
else throw std::runtime_error ("direction must be 0,1,2 or 3");
ipos.pos[0] = pos.x();
ipos.pos[1] = pos.y();
ipos.pos[2] = pos.z();
if (actor.getClass().isActor())
{
// TODO: should this depend on the 'direction' parameter?
ipos.rot[0] = 0;
ipos.rot[1] = 0;
ipos.rot[2] = 0;
}
else
{
ipos.rot[0] = actor.getRefData().getPosition().rot[0];
ipos.rot[1] = actor.getRefData().getPosition().rot[1];
ipos.rot[2] = actor.getRefData().getPosition().rot[2];
}
// create item
MWWorld::CellStore* store = actor.getCell();
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1);
ref.getPtr().getCellRef().setPosition(ipos);
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos);
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), actor, actor.getCell(), direction, distance);
}
}
};

View file

@ -268,6 +268,13 @@ namespace MWWorld
mPhysics->addHeightField (data->mHeights, cell->getCell()->getGridX(), cell->getCell()->getGridY(),
worldsize / (verts-1), verts);
}
else
{
static std::vector<float> defaultHeight;
defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT);
mPhysics->addHeightField (&defaultHeight[0], cell->getCell()->getGridX(), cell->getCell()->getGridY(),
worldsize / (verts-1), verts);
}
}
// register local scripts

View file

@ -1325,11 +1325,50 @@ namespace MWWorld
rotateObjectImp(ptr, osg::Vec3f(x, y, z), adjust);
}
MWWorld::Ptr World::safePlaceObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos)
MWWorld::Ptr World::placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos)
{
return copyObjectToCell(ptr,cell,pos,ptr.getRefData().getCount(),false);
}
MWWorld::Ptr World::safePlaceObject(const ConstPtr &ptr, const ConstPtr &referenceObject, MWWorld::CellStore* referenceCell, int direction, float distance)
{
ESM::Position ipos = referenceObject.getRefData().getPosition();
osg::Vec3f pos(ipos.asVec3());
osg::Quat orientation(ipos.rot[2], osg::Vec3f(0,0,-1));
int fallbackDirections[4] = {direction, (direction+3)%4, (direction+2)%4, (direction+1)%4};
for (int i=0; i<4; ++i)
{
direction = fallbackDirections[i];
// check if spawn point is safe, fall back to another direction if not
osg::Vec3f spawnPoint = pos;
if (direction == 0) spawnPoint = pos + (orientation * osg::Vec3f(0,1,0)) * distance;
else if(direction == 1) spawnPoint = pos - (orientation * osg::Vec3f(0,1,0)) * distance;
else if(direction == 2) spawnPoint = pos - (orientation * osg::Vec3f(1,0,0)) * distance;
else if(direction == 3) spawnPoint = pos + (orientation * osg::Vec3f(1,0,0)) * distance;
spawnPoint.z() += 30; // move up a little to account for slopes, will snap down later
if (!castRay(spawnPoint.x(), spawnPoint.y(), spawnPoint.z(),
pos.x(), pos.y(), pos.z() + 20))
{
// safe
ipos.pos[0] = spawnPoint.x();
ipos.pos[1] = spawnPoint.y();
ipos.pos[2] = spawnPoint.z();
break;
}
}
ipos.rot[0] = referenceObject.getRefData().getPosition().rot[0];
ipos.rot[1] = referenceObject.getRefData().getPosition().rot[1];
ipos.rot[2] = referenceObject.getRefData().getPosition().rot[2];
MWWorld::Ptr placed = copyObjectToCell(ptr, referenceCell, ipos, ptr.getRefData().getCount(), false);
placed.getClass().adjustPosition(placed, true); // snap to ground
return placed;
}
void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const
{
const int cellSize = 8192;
@ -3025,23 +3064,9 @@ namespace MWWorld
if (selectedCreature.empty())
return;
ESM::Position ipos = mPlayer->getPlayer().getRefData().getPosition();
osg::Vec3f pos(ipos.asVec3());
osg::Quat rot(-ipos.rot[2], osg::Vec3f(0,0,1));
const float distance = 50;
pos = pos + (rot * osg::Vec3f(0,1,0)) * distance;
ipos.pos[0] = pos.x();
ipos.pos[1] = pos.y();
ipos.pos[2] = pos.z();
ipos.rot[0] = 0;
ipos.rot[1] = 0;
ipos.rot[2] = 0;
MWWorld::CellStore* cell = mPlayer->getPlayer().getCell();
MWWorld::ManualRef ref(getStore(), selectedCreature, 1);
ref.getPtr().getCellRef().setPosition(ipos);
safePlaceObject(ref.getPtr(), cell, ipos);
safePlaceObject(ref.getPtr(), getPlayerPtr(), getPlayerPtr().getCell(), 0, 220.f);
}
}

View file

@ -367,8 +367,12 @@ namespace MWWorld
/// \param adjust indicates rotation should be set or adjusted
virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false);
virtual MWWorld::Ptr safePlaceObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos);
///< place an object in a "safe" location (ie not in the void, etc). Makes a copy of the Ptr.
virtual MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos);
///< Place an object. Makes a copy of the Ptr.
virtual MWWorld::Ptr safePlaceObject (const MWWorld::ConstPtr& ptr, const MWWorld::ConstPtr& referenceObject, MWWorld::CellStore* referenceCell, int direction, float distance);
///< Place an object in a safe place next to \a referenceObject. \a direction and \a distance specify the wanted placement
/// relative to \a referenceObject (but the object may be placed somewhere else if the wanted location is obstructed).
virtual float getMaxActivationDistance();

View file

@ -46,6 +46,9 @@ struct Land
DATA_VTEX = 16
};
// default height to use in case there is no Land record
static const int DEFAULT_HEIGHT = -2048;
// number of vertices per side
static const int LAND_SIZE = 65;

View file

@ -16,7 +16,7 @@
namespace ESMTerrain
{
const float defaultHeight = -2048;
const float defaultHeight = ESM::Land::DEFAULT_HEIGHT;
Storage::Storage(const VFS::Manager *vfs, const std::string& normalMapPattern, bool autoUseNormalMaps, const std::string& specularMapPattern, bool autoUseSpecularMaps)
: mVFS(vfs)

View file

@ -56,9 +56,18 @@ namespace SceneUtil
CopyRigVisitor copyVisitor(handle, filter);
toAttach->accept(copyVisitor);
master->asGroup()->addChild(handle);
return handle;
if (handle->getNumChildren() == 1)
{
osg::ref_ptr<osg::Node> newHandle = handle->getChild(0);
handle->removeChild(newHandle);
master->asGroup()->addChild(newHandle);
return newHandle;
}
else
{
master->asGroup()->addChild(handle);
return handle;
}
}
else
{

View file

@ -38,6 +38,8 @@ Skeleton::Skeleton()
, mNeedToUpdateBoneMatrices(true)
, mActive(true)
, mLastFrameNumber(0)
, mTraversedEvenFrame(false)
, mTraversedOddFrame(false)
{
}
@ -48,6 +50,8 @@ Skeleton::Skeleton(const Skeleton &copy, const osg::CopyOp &copyop)
, mNeedToUpdateBoneMatrices(true)
, mActive(copy.mActive)
, mLastFrameNumber(0)
, mTraversedEvenFrame(false)
, mTraversedOddFrame(false)
{
}
@ -111,6 +115,11 @@ void Skeleton::updateBoneMatrices(osg::NodeVisitor* nv)
mLastFrameNumber = nv->getTraversalNumber();
if (mLastFrameNumber % 2 == 0)
mTraversedEvenFrame = true;
else
mTraversedOddFrame = true;
if (mNeedToUpdateBoneMatrices)
{
if (mRootBone.get())
@ -140,7 +149,7 @@ void Skeleton::traverse(osg::NodeVisitor& nv)
if (!getActive() && nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR
// need to process at least 2 frames before shutting off update, since we need to have both frame-alternating RigGeometries initialized
// this would be more naturally handled if the double-buffering was implemented in RigGeometry itself rather than in a FrameSwitch decorator node
&& mLastFrameNumber != 0 && mLastFrameNumber+2 <= nv.getTraversalNumber())
&& mLastFrameNumber != 0 && mTraversedEvenFrame && mTraversedOddFrame)
return;
osg::Group::traverse(nv);
}

View file

@ -69,6 +69,8 @@ namespace SceneUtil
bool mActive;
unsigned int mLastFrameNumber;
bool mTraversedEvenFrame;
bool mTraversedOddFrame;
};
}