mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 01:49:41 +00:00
use a raycast to determine where to place object, if distance is too far
drop it on the ground
This commit is contained in:
parent
7fbee0d488
commit
b18ee198b4
11 changed files with 142 additions and 18 deletions
|
@ -244,7 +244,7 @@ void ContainerBase::Update()
|
|||
if(mDragAndDrop->mIsOnDragAndDrop)
|
||||
{
|
||||
if(mDragAndDrop->mDraggedWidget)
|
||||
mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition() - MyGUI::IntPoint(21, 21));
|
||||
mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition());
|
||||
else mDragAndDrop->mIsOnDragAndDrop = false; //If this happens, there is a bug.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
|
|||
LocalMapBase::init(minimap, this);
|
||||
|
||||
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
|
||||
mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
|
||||
}
|
||||
|
||||
void HUD::setFpsLevel(int level)
|
||||
|
@ -261,16 +262,19 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
|||
// drop item into the gameworld
|
||||
MWWorld::Ptr object = *mDragAndDrop->mStore.begin();
|
||||
|
||||
float* playerPos;
|
||||
playerPos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition().pos;
|
||||
MWWorld::Ptr::CellStore* cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); /// \todo this might be a different cell
|
||||
MWWorld::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
ESM::Position& pos = object.getRefData().getPosition();
|
||||
pos.pos[0] = playerPos[0];
|
||||
pos.pos[1] = playerPos[1];
|
||||
pos.pos[2] = playerPos[2];
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
||||
float mouseX = cursorPosition.left / float(viewSize.width);
|
||||
float mouseY = cursorPosition.top / float(viewSize.height);
|
||||
|
||||
MWBase::Environment::get().getWorld()->insertObject(object, cell);
|
||||
if (world->canPlaceObject(mouseX, mouseY))
|
||||
world->placeObject(object, mouseX, mouseY);
|
||||
else
|
||||
world->dropObjectOnGround(object);
|
||||
|
||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
||||
|
||||
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
|
@ -284,3 +288,30 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
|||
}
|
||||
}
|
||||
|
||||
void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y)
|
||||
{
|
||||
if (mDragAndDrop->mIsOnDragAndDrop)
|
||||
{
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
||||
float mouseX = cursorPosition.left / float(viewSize.width);
|
||||
float mouseY = cursorPosition.top / float(viewSize.height);
|
||||
|
||||
MWWorld::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
// if we can't drop the object at the wanted position, show the "drop on ground" cursor.
|
||||
bool canDrop = world->canPlaceObject(mouseX, mouseY);
|
||||
|
||||
if (!canDrop)
|
||||
MyGUI::PointerManager::getInstance().setPointer("drop_ground");
|
||||
else
|
||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
||||
/// \todo make it possible to pick up objects with the mouse, if inventory or container window is open
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,5 +52,6 @@ namespace MWGui
|
|||
DragAndDrop* mDragAndDrop;
|
||||
|
||||
void onWorldClicked(MyGUI::Widget* _sender);
|
||||
void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -576,5 +576,4 @@ void WindowManager::setDragDrop(bool dragDrop)
|
|||
{
|
||||
mToolTips->setEnabled(!dragDrop);
|
||||
MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop);
|
||||
setMouseVisible(!dragDrop);
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace MWWorld
|
|||
Ray centerRay = mRender.getCamera()->getCameraToViewportRay(
|
||||
mRender.getViewport()->getWidth()/2,
|
||||
mRender.getViewport()->getHeight()/2);
|
||||
btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y);
|
||||
btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,29 @@ namespace MWWorld
|
|||
return !(result.first == "");
|
||||
}
|
||||
|
||||
std::pair<bool, Ogre::Vector3> PhysicsSystem::castRay(float mouseX, float mouseY)
|
||||
{
|
||||
Ogre::Ray ray = mRender.getCamera()->getCameraToViewportRay(
|
||||
mouseX,
|
||||
mouseY);
|
||||
Ogre::Vector3 from = ray.getOrigin();
|
||||
Ogre::Vector3 to = ray.getPoint(200); /// \todo make this distance (ray length) configurable
|
||||
|
||||
btVector3 _from, _to;
|
||||
// OGRE to MW coordinates
|
||||
_from = btVector3(from.x, -from.z, from.y);
|
||||
_to = btVector3(to.x, -to.z, to.y);
|
||||
|
||||
std::pair<std::string, float> result = mEngine->rayTest(_from, _to);
|
||||
|
||||
if (result.first == "")
|
||||
return std::make_pair(false, Ogre::Vector3());
|
||||
else
|
||||
{
|
||||
return std::make_pair(true, ray.getPoint(200*result.second)); /// \todo make this distance (ray length) configurable
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::doPhysics(float dt, const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
|
||||
{
|
||||
//set the DebugRenderingMode. To disable it,set it to 0
|
||||
|
|
|
@ -53,6 +53,9 @@ namespace MWWorld
|
|||
// cast ray, return true if it hit something
|
||||
bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to);
|
||||
|
||||
std::pair<bool, Ogre::Vector3> castRay(float mouseX, float mouseY);
|
||||
///< cast ray from the mouse, return true if it hit something and the first result (in OGRE coordinates)
|
||||
|
||||
void insertObjectPhysics(const MWWorld::Ptr& ptr, std::string model);
|
||||
|
||||
void insertActorPhysics(const MWWorld::Ptr&, std::string model);
|
||||
|
|
|
@ -965,9 +965,57 @@ namespace MWWorld
|
|||
mRendering->toggleWater();
|
||||
}
|
||||
|
||||
void World::insertObject(MWWorld::Ptr ptr, Ptr::CellStore* cell)
|
||||
bool World::placeObject(MWWorld::Ptr object, float cursorX, float cursorY)
|
||||
{
|
||||
mWorldScene->insertObject(ptr, cell);
|
||||
std::pair<bool, Ogre::Vector3> result = mPhysics->castRay(cursorX, cursorY);
|
||||
|
||||
if (!result.first)
|
||||
return false;
|
||||
|
||||
MWWorld::Ptr::CellStore* cell;
|
||||
if (isCellExterior())
|
||||
{
|
||||
int cellX, cellY;
|
||||
positionToIndex(result.second[0], -result.second[2], cellX, cellY);
|
||||
cell = mCells.getExterior(cellX, cellY);
|
||||
}
|
||||
else
|
||||
cell = getPlayer().getPlayer().getCell();
|
||||
|
||||
ESM::Position& pos = object.getRefData().getPosition();
|
||||
pos.pos[0] = result.second[0];
|
||||
pos.pos[1] = -result.second[2];
|
||||
pos.pos[2] = result.second[1];
|
||||
|
||||
mWorldScene->insertObject(object, cell);
|
||||
|
||||
/// \todo retrieve the bounds of the object and translate it accordingly
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool World::canPlaceObject(float cursorX, float cursorY)
|
||||
{
|
||||
std::pair<bool, Ogre::Vector3> result = mPhysics->castRay(cursorX, cursorY);
|
||||
|
||||
/// \todo also check if the wanted position is on a flat surface, and not e.g. against a vertical wall!
|
||||
|
||||
if (!result.first)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void World::dropObjectOnGround(MWWorld::Ptr object)
|
||||
{
|
||||
MWWorld::Ptr::CellStore* cell = getPlayer().getPlayer().getCell();
|
||||
|
||||
float* playerPos = getPlayer().getPlayer().getRefData().getPosition().pos;
|
||||
|
||||
ESM::Position& pos = object.getRefData().getPosition();
|
||||
pos.pos[0] = playerPos[0];
|
||||
pos.pos[1] = playerPos[1];
|
||||
pos.pos[2] = playerPos[2];
|
||||
|
||||
mWorldScene->insertObject(object, cell);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -263,9 +263,17 @@ namespace MWWorld
|
|||
|
||||
void update (float duration);
|
||||
|
||||
void insertObject (MWWorld::Ptr ptr, Ptr::CellStore* cell);
|
||||
///< insert object in a given cell
|
||||
/// \note this method is only meant for dropping items into the gameworld from a container
|
||||
bool placeObject(MWWorld::Ptr object, float cursorX, float cursorY);
|
||||
///< place an object into the gameworld at the specified cursor position
|
||||
/// @param object
|
||||
/// @param cursor X (relative 0-1)
|
||||
/// @param cursor Y (relative 0-1)
|
||||
/// @return true if the object was placed, or false if it was rejected because the position is too far away
|
||||
|
||||
void dropObjectOnGround(MWWorld::Ptr object);
|
||||
|
||||
bool canPlaceObject(float cursorX, float cursorY);
|
||||
///< @return true if it is possible to place on object at specified cursor location
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -26,4 +26,9 @@
|
|||
<Property key="Size" value="32 32"/>
|
||||
<Property key="Resource" value="DResize2PointerImage"/>
|
||||
</Resource>
|
||||
<Resource type="ResourceImageSetPointer" name="drop_ground">
|
||||
<Property key="Point" value="0 24"/>
|
||||
<Property key="Size" value="32 32"/>
|
||||
<Property key="Resource" value="DropGroundPointerImage"/>
|
||||
</Resource>
|
||||
</MyGUI>
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
<Layer name="MainMenu" overlapped="false" peek="false"/>
|
||||
<Layer name="Console" overlapped="false" peek="true"/>
|
||||
<Layer name="Popup" overlapped="true" peek="true"/>
|
||||
<Layer name="DragAndDrop" overlapped="false" peek="true"/>
|
||||
<Layer name="Pointer" overlapped="false" peek="false"/>
|
||||
<Layer name="Statistic" overlapped="false" peek="false"/>
|
||||
<Layer name="DragAndDrop" overlapped="false" peek="true"/>
|
||||
</MyGUI>
|
||||
|
|
|
@ -36,6 +36,13 @@
|
|||
</Index>
|
||||
</Group>
|
||||
</Resource>
|
||||
<Resource type="ResourceImageSet" name="DropGroundPointerImage">
|
||||
<Group name="Pointer" texture="textures\cursor_drop_ground.dds" size="32 32">
|
||||
<Index name="Pointer" >
|
||||
<Frame point="0 0"/>
|
||||
</Index>
|
||||
</Group>
|
||||
</Resource>
|
||||
|
||||
<Resource type="ResourceImageSet" name="MenuBook_Close">
|
||||
<Group name="States" texture="mwgui1" size="96 24">
|
||||
|
|
Loading…
Reference in a new issue