Merge remote-tracking branch 'origin/master'

openmw-37
Marc Zinnschlag 9 years ago
commit af5a1bc16b

@ -40,8 +40,8 @@ script:
- cd ./build
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && ["${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && ["${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
notifications:
recipients:
- corrmage+travis-ci@gmail.com

@ -20,7 +20,6 @@ MwIniImporter::MwIniImporter()
{
const char *map[][2] =
{
{ "fps", "General:Show FPS" },
{ "no-sound", "General:Disable Audio" },
{ 0, 0 }
};

@ -168,9 +168,6 @@ void OMW::Engine::frame(float frametime)
if (mEnvironment.getStateManager()->getState()!=
MWBase::StateManager::State_NoGame)
{
#if 0
mEnvironment.getWindowManager()->wmUpdateFps(fps);
#endif
mEnvironment.getWindowManager()->update();
}

@ -155,8 +155,6 @@ namespace MWBase
virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0;
virtual void wmUpdateFps(float fps) = 0;
/// Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0;
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value) = 0;

@ -153,6 +153,34 @@ struct TypesetBookImpl : TypesetBook
visitRuns (top, bottom, NULL, visitor);
}
/// hit test with a margin for error. only hits on interactive text fragments are reported.
StyleImpl * hitTestWithMargin (int left, int top)
{
StyleImpl * hit = hitTest(left, top);
if (hit && hit->mInteractiveId > 0)
return hit;
const int maxMargin = 10;
for (int margin=1; margin < maxMargin; ++margin)
{
for (int i=0; i<4; ++i)
{
if (i==0)
hit = hitTest(left, top-margin);
else if (i==1)
hit = hitTest(left, top+margin);
else if (i==2)
hit = hitTest(left-margin, top);
else
hit = hitTest(left+margin, top);
if (hit && hit->mInteractiveId > 0)
return hit;
}
}
return NULL;
}
StyleImpl * hitTest (int left, int top) const
{
for (Sections::const_iterator i = mSections.begin (); i != mSections.end (); ++i)
@ -916,15 +944,15 @@ public:
left -= mCroppedParent->getAbsoluteLeft ();
top -= mCroppedParent->getAbsoluteTop ();
Style * Hit = mBook->hitTest (left, mViewTop + top);
Style * hit = mBook->hitTestWithMargin (left, mViewTop + top);
if (mLastDown == MyGUI::MouseButton::None)
{
if (Hit != mFocusItem)
if (hit != mFocusItem)
{
dirtyFocusItem ();
mFocusItem = Hit;
mFocusItem = hit;
mItemActive = false;
dirtyFocusItem ();
@ -933,7 +961,7 @@ public:
else
if (mFocusItem != 0)
{
bool newItemActive = Hit == mFocusItem;
bool newItemActive = hit == mFocusItem;
if (newItemActive != mItemActive)
{
@ -949,12 +977,18 @@ public:
if (!mBook)
return;
left -= mCroppedParent->getAbsoluteLeft ();
top -= mCroppedParent->getAbsoluteTop ();
// work around inconsistency in MyGUI where the mouse press coordinates aren't
// transformed by the current Layer (even though mouse *move* events are).
MyGUI::IntPoint pos (left, top);
#if MYGUI_VERSION < MYGUI_DEFINE_VERSION(3,2,3)
pos = mNode->getLayer()->getPosition(left, top);
#endif
pos.left -= mCroppedParent->getAbsoluteLeft ();
pos.top -= mCroppedParent->getAbsoluteTop ();
if (mLastDown == MyGUI::MouseButton::None)
{
mFocusItem = mBook->hitTest (left, mViewTop + top);
mFocusItem = mBook->hitTestWithMargin (pos.left, mViewTop + pos.top);
mItemActive = true;
dirtyFocusItem ();
@ -968,14 +1002,21 @@ public:
if (!mBook)
return;
left -= mCroppedParent->getAbsoluteLeft ();
top -= mCroppedParent->getAbsoluteTop ();
// work around inconsistency in MyGUI where the mouse release coordinates aren't
// transformed by the current Layer (even though mouse *move* events are).
MyGUI::IntPoint pos (left, top);
#if MYGUI_VERSION < MYGUI_DEFINE_VERSION(3,2,3)
pos = mNode->getLayer()->getPosition(left, top);
#endif
pos.left -= mCroppedParent->getAbsoluteLeft ();
pos.top -= mCroppedParent->getAbsoluteTop ();
if (mLastDown == id)
{
Style * mItem = mBook->hitTest (left, mViewTop + top);
Style * item = mBook->hitTestWithMargin (pos.left, mViewTop + pos.top);
bool clicked = mFocusItem == mItem;
bool clicked = mFocusItem == item;
mItemActive = false;
@ -983,8 +1024,8 @@ public:
mLastDown = MyGUI::MouseButton::None;
if (clicked && mLinkClicked && mItem && mItem->mInteractiveId != 0)
mLinkClicked (mItem->mInteractiveId);
if (clicked && mLinkClicked && item && item->mInteractiveId != 0)
mLinkClicked (item->mInteractiveId);
}
}

@ -67,7 +67,7 @@ namespace MWGui
};
HUD::HUD(CustomMarkerCollection &customMarkers, bool showFps, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender)
HUD::HUD(CustomMarkerCollection &customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender)
: Layout("openmw_hud.layout")
, LocalMapBase(customMarkers, localMapRender)
, mHealth(NULL)
@ -85,8 +85,6 @@ namespace MWGui
, mCellNameBox(NULL)
, mDrowningFrame(NULL)
, mDrowningFlash(NULL)
, mFpsBox(NULL)
, mFpsCounter(NULL)
, mHealthManaStaminaBaseLeft(0)
, mWeapBoxBaseLeft(0)
, mSpellBoxBaseLeft(0)
@ -161,8 +159,6 @@ namespace MWGui
getWidget(mCrosshair, "Crosshair");
setFpsVisible(showFps);
LocalMapBase::init(mMinimap, mCompass, Settings::Manager::getInt("local map hud widget size", "Map"));
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
@ -181,28 +177,6 @@ namespace MWGui
delete mSpellIcons;
}
void HUD::setFpsVisible(const bool visible)
{
mFpsCounter = 0;
MyGUI::Widget* fps;
getWidget(fps, "FPSBox");
fps->setVisible(false);
if (visible)
{
getWidget(mFpsBox, "FPSBox");
//mFpsBox->setVisible(true);
getWidget(mFpsCounter, "FPSCounter");
}
}
void HUD::setFPS(float fps)
{
if (mFpsCounter)
mFpsCounter->setCaption(MyGUI::utility::toString((int)fps));
}
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
{
int current = std::max(0, static_cast<int>(value.getCurrent()));

@ -19,10 +19,9 @@ namespace MWGui
class HUD : public Layout, public LocalMapBase
{
public:
HUD(CustomMarkerCollection& customMarkers, bool fpsVisible, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender);
HUD(CustomMarkerCollection& customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender);
virtual ~HUD();
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setFPS(float fps);
/// Set time left for the player to start drowning
/// @param time time left to start drowning
@ -38,8 +37,6 @@ namespace MWGui
void setEffectVisible(bool visible);
void setMinimapVisible(bool visible);
void setFpsVisible(const bool visible);
void setSelectedSpell(const std::string& spellId, int successChancePercent);
void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent);
void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent);
@ -77,9 +74,6 @@ namespace MWGui
MyGUI::TextBox* mWeaponSpellBox;
MyGUI::Widget *mDrowningFrame, *mDrowningFlash;
MyGUI::Widget* mFpsBox;
MyGUI::TextBox* mFpsCounter;
// bottom left elements
int mHealthManaStaminaBaseLeft, mWeapBoxBaseLeft, mSpellBoxBaseLeft, mSneakBoxBaseLeft;
// bottom right elements

@ -282,7 +282,13 @@ namespace MWGui
MWBase::Environment::get().getInputManager()->update(0, true, true);
//osg::Timer timer;
mViewer->frame(mViewer->getFrameStamp()->getSimulationTime());
// at the time this function is called we are in the middle of a frame,
// so out of order calls are necessary to get a correct frameNumber for the next frame.
// refer to the advance() and frame() order in Engine::go()
mViewer->eventTraversal();
mViewer->updateTraversal();
mViewer->renderingTraversals();
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
//std::cout << "frame took " << timer.time_m() << std::endl;
//if (mViewer->getIncrementalCompileOperation())

@ -66,8 +66,8 @@ namespace MWGui
mFader->notifyOperationFinished();
}
ScreenFader::ScreenFader(const std::string & texturePath)
: WindowBase("openmw_screen_fader.layout")
ScreenFader::ScreenFader(const std::string & texturePath, const std::string& layout)
: WindowBase(layout)
, mCurrentAlpha(0.f)
, mFactor(1.f)
, mRepeat(false)

@ -36,7 +36,7 @@ namespace MWGui
class ScreenFader : public WindowBase
{
public:
ScreenFader(const std::string & texturePath);
ScreenFader(const std::string & texturePath, const std::string& layout = "openmw_screen_fader.layout");
void setTexture(const std::string & texturePath);

@ -166,7 +166,6 @@ namespace MWGui
getWidget(mFullscreenButton, "FullscreenButton");
getWidget(mVSyncButton, "VSyncButton");
getWidget(mWindowBorderButton, "WindowBorderButton");
getWidget(mFPSButton, "FPSButton");
getWidget(mFOVSlider, "FOVSlider");
getWidget(mAnisotropySlider, "AnisotropySlider");
getWidget(mTextureFilteringButton, "TextureFilteringButton");
@ -201,7 +200,6 @@ namespace MWGui
mSettingsTab->eventTabChangeSelect += MyGUI::newDelegate(this, &SettingsWindow::onTabChanged);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked);
mTextureFilteringButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringChanged);
mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled);
mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected);
mWaterTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterTextureSizeChanged);
@ -256,8 +254,6 @@ namespace MWGui
mShadowsEnabledButton->setEnabled(false);
}
mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD")));
MyGUI::TextBox* fovText;
getWidget(fovText, "FovText");
fovText->setCaption("Field of View (" + MyGUI::utility::toString(int(Settings::Manager::getInt("field of view", "General"))) + ")");
@ -427,14 +423,6 @@ namespace MWGui
}
}
void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender)
{
int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 2;
Settings::Manager::setInt("fps", "HUD", newLevel);
mFPSButton->setCaptionWithReplacing(fpsLevelToStr(newLevel));
apply();
}
void SettingsWindow::onTextureFilteringChanged(MyGUI::ComboBox* _sender, size_t pos)
{
Settings::Manager::setString("texture filtering", "General", Misc::StringUtils::lowerCase(_sender->getItemNameAt(pos)));

@ -30,7 +30,6 @@ namespace MWGui
MyGUI::Button* mFullscreenButton;
MyGUI::Button* mVSyncButton;
MyGUI::Button* mWindowBorderButton;
MyGUI::Button* mFPSButton;
MyGUI::ScrollBar* mFOVSlider;
MyGUI::ScrollBar* mDifficultySlider;
MyGUI::ScrollBar* mAnisotropySlider;
@ -53,7 +52,6 @@ namespace MWGui
void onTabChanged(MyGUI::TabControl* _sender, size_t index);
void onOkButtonClicked(MyGUI::Widget* _sender);
void onFpsToggled(MyGUI::Widget* _sender);
void onTextureFilteringChanged(MyGUI::ComboBox* _sender, size_t pos);
void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos);
void onButtonToggled(MyGUI::Widget* _sender);

@ -49,11 +49,13 @@ void WindowBase::center()
{
// Centre dialog
MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntSize layerSize = MyGUI::RenderManager::getInstance().getViewSize();
if (mMainWidget->getLayer())
layerSize = mMainWidget->getLayer()->getSize();
MyGUI::IntCoord coord = mMainWidget->getCoord();
coord.left = (gameWindowSize.width - coord.width)/2;
coord.top = (gameWindowSize.height - coord.height)/2;
coord.left = (layerSize.width - coord.width)/2;
coord.top = (layerSize.height - coord.height)/2;
mMainWidget->setCoord(coord);
}

@ -33,6 +33,9 @@
#include <components/translation/translation.hpp>
#include <components/myguiplatform/myguiplatform.hpp>
#include <components/myguiplatform/myguirendermanager.hpp>
#include <components/myguiplatform/additivelayer.hpp>
#include <components/myguiplatform/scalinglayer.hpp>
#include <components/vfs/manager.hpp>
@ -185,7 +188,6 @@ namespace MWGui
, mForceHidden(GW_None)
, mAllowed(GW_ALL)
, mRestAllowed(true)
, mFPS(0.0f)
, mFallbackMap(fallbackMap)
, mShowOwned(0)
, mVersionDescription(versionDescription)
@ -216,6 +218,8 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollBar>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<BackgroundImage>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<osgMyGUI::AdditiveLayer>("Layer");
MyGUI::FactoryManager::getInstance().registerFactory<osgMyGUI::ScalingLayer>("Layer");
BookPage::registerMyGUIComponents ();
ItemView::registerComponents();
ItemWidget::registerComponents();
@ -246,7 +250,7 @@ namespace MWGui
MyGUI::PointerManager::getInstance().setVisible(false);
mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal<MyGUI::ImageBox>("ImageBox", 0,0,1,1,
MyGUI::Align::Default, "Overlay");
MyGUI::Align::Default, "InputBlocker");
mVideoBackground->setImageTexture("black");
mVideoBackground->setVisible(false);
mVideoBackground->setNeedMouseFocus(true);
@ -296,7 +300,7 @@ namespace MWGui
trackWindow(mDialogueWindow, "dialogue");
mContainerWindow = new ContainerWindow(mDragAndDrop);
trackWindow(mContainerWindow, "container");
mHud = new HUD(mCustomMarkers, Settings::Manager::getInt("fps", "HUD"), mDragAndDrop, mLocalMapRender);
mHud = new HUD(mCustomMarkers, mDragAndDrop, mLocalMapRender);
mToolTips = new ToolTips();
mScrollWindow = new ScrollWindow();
mBookWindow = new BookWindow();
@ -327,12 +331,12 @@ namespace MWGui
// TODO: check if non-BM versions actually use player_hit_01.dds
if(!mResourceSystem->getVFS()->exists(hitFaderTexture))
hitFaderTexture = "textures\\player_hit_01.dds";
mHitFader = new ScreenFader(hitFaderTexture);
mHitFader = new ScreenFader(hitFaderTexture, "openmw_screen_fader_hit.layout");
mScreenFader = new ScreenFader("black");
mDebugWindow = new DebugWindow();
mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"Overlay");
mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"InputBlocker");
mHud->setVisible(mHudEnabled);
@ -464,8 +468,6 @@ namespace MWGui
{
cleanupGarbage();
mHud->setFPS(mFPS);
mHud->update();
}
@ -859,7 +861,13 @@ namespace MWGui
mMessageBoxManager->onFrame(0.f);
MWBase::Environment::get().getInputManager()->update(0, true, false);
mViewer->frame(mViewer->getFrameStamp()->getSimulationTime());
// at the time this function is called we are in the middle of a frame,
// so out of order calls are necessary to get a correct frameNumber for the next frame.
// refer to the advance() and frame() order in Engine::go()
mViewer->eventTraversal();
mViewer->updateTraversal();
mViewer->renderingTraversals();
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
}
}
}
@ -1132,7 +1140,6 @@ namespace MWGui
void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed)
{
mHud->setFpsVisible(static_cast<bool>(Settings::Manager::getInt("fps", "HUD")));
mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI"));
for (Settings::CategorySettingVector::const_iterator it = changed.begin();
@ -1316,11 +1323,6 @@ namespace MWGui
mConsole->executeFile (path);
}
void WindowManager::wmUpdateFps(float fps)
{
mFPS = fps;
}
MWGui::DialogueWindow* WindowManager::getDialogueWindow() { return mDialogueWindow; }
MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; }
MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; }
@ -1756,7 +1758,13 @@ namespace MWGui
{
MWBase::Environment::get().getInputManager()->update(0, true, false);
mViewer->frame(mViewer->getFrameStamp()->getSimulationTime());
// at the time this function is called we are in the middle of a frame,
// so out of order calls are necessary to get a correct frameNumber for the next frame.
// refer to the advance() and frame() order in Engine::go()
mViewer->eventTraversal();
mViewer->updateTraversal();
mViewer->renderingTraversals();
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
}
mVideoWidget->stop();

@ -180,8 +180,6 @@ namespace MWGui
virtual void setConsoleSelectedObject(const MWWorld::Ptr& object);
virtual void wmUpdateFps(float fps);
///< Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value);
@ -486,8 +484,6 @@ namespace MWGui
void updateMap();
float mFPS;
std::map<std::string, std::string> mFallbackMap;
int mShowOwned;

@ -240,8 +240,6 @@ namespace MWPhysics
const ESM::Position& refpos = ptr.getRefData().getPosition();
osg::Vec3f position(refpos.asVec3());
float collisionShapeOffset = physicActor->getPosition().z() - position.z();
// Early-out for totally static creatures
// (Not sure if gravity should still apply?)
if (!ptr.getClass().isMobile(ptr))
@ -258,11 +256,17 @@ namespace MWPhysics
}
btCollisionObject *colobj = physicActor->getCollisionObject();
position.z() += collisionShapeOffset;
osg::Vec3f halfExtents = physicActor->getHalfExtents();
// NOTE: here we don't account for the collision box translation (i.e. physicActor->getPosition() - refpos.pos).
// That means the collision shape used for moving this actor is in a different spot than the collision shape
// other actors are using to collide against this actor.
// While this is strictly speaking wrong, it's needed for MW compatibility.
position.z() += halfExtents.z();
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fSwimHeightScale")->getFloat();
float swimlevel = waterlevel + collisionShapeOffset - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
float swimlevel = waterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
ActorTracer tracer;
osg::Vec3f inertia = physicActor->getInertialForce();
@ -284,6 +288,11 @@ namespace MWPhysics
velocity = velocity + physicActor->getInertialForce();
}
}
// dead actors underwater will float to the surface
if (ptr.getClass().getCreatureStats(ptr).isDead() && position.z() < swimlevel)
velocity = osg::Vec3f(0,0,1) * 25;
ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0;
// Now that we have the effective movement vector, apply wind forces to it
@ -370,7 +379,7 @@ namespace MWPhysics
{
// don't let pure water creatures move out of water after stepMove
if (ptr.getClass().isPureWaterCreature(ptr)
&& newPosition.z() + physicActor->getHalfExtents().z() > waterlevel)
&& newPosition.z() + halfExtents.z() > waterlevel)
newPosition = oldPosition;
}
else
@ -451,7 +460,7 @@ namespace MWPhysics
}
physicActor->setOnGround(isOnGround);
newPosition.z() -= collisionShapeOffset; // remove what was added at the beginning
newPosition.z() -= halfExtents.z(); // remove what was added at the beginning
return newPosition;
}
};

@ -489,6 +489,15 @@ namespace MWRender
mutable bool mDone;
};
class NoTraverseCallback : public osg::NodeCallback
{
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
}
};
void RenderingManager::screenshot(osg::Image *image, int w, int h)
{
osg::ref_ptr<osg::Camera> rttCamera (new osg::Camera);
@ -512,6 +521,7 @@ namespace MWRender
image->setDataType(GL_UNSIGNED_BYTE);
image->setPixelFormat(texture->getInternalFormat());
rttCamera->setUpdateCallback(new NoTraverseCallback);
rttCamera->addChild(mLightRoot);
rttCamera->setCullMask(mViewer->getCamera()->getCullMask() & (~Mask_GUI));
@ -521,10 +531,18 @@ namespace MWRender
osg::ref_ptr<NotifyDrawCompletedCallback> callback (new NotifyDrawCompletedCallback);
rttCamera->setFinalDrawCallback(callback);
mViewer->frame(mViewer->getFrameStamp()->getSimulationTime());
// at the time this function is called we are in the middle of a frame,
// so out of order calls are necessary to get a correct frameNumber for the next frame.
// refer to the advance() and frame() order in Engine::go()
mViewer->eventTraversal();
mViewer->updateTraversal();
mViewer->renderingTraversals();
callback->waitTillDone();
// now that we've "used up" the current frame, get a fresh framenumber for the next frame() following after the screenshot is completed
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
rttCamera->removeChildren(0, rttCamera->getNumChildren());
rttCamera->setGraphicsContext(NULL);
mRootNode->removeChild(rttCamera);

@ -1563,17 +1563,15 @@ void SkyManager::setWeather(const WeatherResult& weather)
mCloudMesh2->setNodeMask(mCloudBlendFactor > 0.f ? ~0 : 0);
}
if (mCloudColour != weather.mSunColor)
if (mCloudColour != weather.mFogColor)
{
// FIXME: this doesn't look correct
osg::Vec4f clr( weather.mSunColor.r()*0.7f + weather.mAmbientColor.r()*0.7f,
weather.mSunColor.g()*0.7f + weather.mAmbientColor.g()*0.7f,
weather.mSunColor.b()*0.7f + weather.mAmbientColor.b()*0.7f, 1.f);
osg::Vec4f clr (weather.mFogColor);
clr += osg::Vec4f(0.13f, 0.13f, 0.13f, 0.f);
mCloudUpdater->setEmissionColor(clr);
mCloudUpdater2->setEmissionColor(clr);
mCloudColour = weather.mSunColor;
mCloudColour = weather.mFogColor;
}
if (mSkyColour != weather.mSkyColor)

@ -115,7 +115,7 @@ add_component_dir (loadinglistener
)
add_component_dir (myguiplatform
myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener
myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener additivelayer scalinglayer
)
add_component_dir (widgets

@ -34,19 +34,22 @@ namespace ESMTerrain
osg::Vec2f origin = center - osg::Vec2f(size/2.f, size/2.f);
assert(origin.x() == (int) origin.x());
assert(origin.y() == (int) origin.y());
int cellX = static_cast<int>(std::floor(origin.x()));
int cellY = static_cast<int>(std::floor(origin.y()));
int cellX = static_cast<int>(origin.x());
int cellY = static_cast<int>(origin.y());
int startRow = (origin.x() - cellX) * ESM::Land::LAND_SIZE;
int startColumn = (origin.y() - cellY) * ESM::Land::LAND_SIZE;
int endRow = startRow + size * (ESM::Land::LAND_SIZE-1) + 1;
int endColumn = startColumn + size * (ESM::Land::LAND_SIZE-1) + 1;
if (const ESM::Land::LandData *data = getLandData (cellX, cellY, ESM::Land::DATA_VHGT))
{
min = std::numeric_limits<float>::max();
max = -std::numeric_limits<float>::max();
for (int row=0; row<ESM::Land::LAND_SIZE; ++row)
for (int row=startRow; row<endRow; ++row)
{
for (int col=0; col<ESM::Land::LAND_SIZE; ++col)
for (int col=startColumn; col<endColumn; ++col)
{
float h = data->mHeights[col*ESM::Land::LAND_SIZE+row];
if (h > max)
@ -143,11 +146,9 @@ namespace ESMTerrain
size_t increment = 1 << lodLevel;
osg::Vec2f origin = center - osg::Vec2f(size/2.f, size/2.f);
assert(origin.x() == (int) origin.x());
assert(origin.y() == (int) origin.y());
int startX = static_cast<int>(origin.x());
int startY = static_cast<int>(origin.y());
int startCellX = static_cast<int>(std::floor(origin.x()));
int startCellY = static_cast<int>(std::floor(origin.y()));
size_t numVerts = static_cast<size_t>(size*(ESM::Land::LAND_SIZE - 1) / increment + 1);
@ -162,10 +163,10 @@ namespace ESMTerrain
float vertX = 0;
float vertY_ = 0; // of current cell corner
for (int cellY = startY; cellY < startY + std::ceil(size); ++cellY)
for (int cellY = startCellY; cellY < startCellY + std::ceil(size); ++cellY)
{
float vertX_ = 0; // of current cell corner
for (int cellX = startX; cellX < startX + std::ceil(size); ++cellX)
for (int cellX = startCellX; cellX < startCellX + std::ceil(size); ++cellX)
{
const ESM::Land::LandData *heightData = getLandData (cellX, cellY, ESM::Land::DATA_VHGT);
const ESM::Land::LandData *normalData = getLandData (cellX, cellY, ESM::Land::DATA_VNML);
@ -175,18 +176,31 @@ namespace ESMTerrain
int colStart = 0;
// Skip the first row / column unless we're at a chunk edge,
// since this row / column is already contained in a previous cell
// This is only relevant if we're creating a chunk spanning multiple cells
if (colStart == 0 && vertY_ != 0)
colStart += increment;
if (rowStart == 0 && vertX_ != 0)
rowStart += increment;
// Only relevant for chunks smaller than (contained in) one cell
rowStart += (origin.x() - startCellX) * ESM::Land::LAND_SIZE;
colStart += (origin.y() - startCellY) * ESM::Land::LAND_SIZE;
int rowEnd = rowStart + std::min(1.f, size) * (ESM::Land::LAND_SIZE-1) + 1;
int colEnd = colStart + std::min(1.f, size) * (ESM::Land::LAND_SIZE-1) + 1;
vertY = vertY_;
for (int col=colStart; col<ESM::Land::LAND_SIZE; col += increment)
for (int col=colStart; col<colEnd; col += increment)
{
vertX = vertX_;
for (int row=rowStart; row<ESM::Land::LAND_SIZE; row += increment)
for (int row=rowStart; row<rowEnd; row += increment)
{
int arrayIndex = col*ESM::Land::LAND_SIZE*3+row*3;
int srcArrayIndex = col*ESM::Land::LAND_SIZE*3+row*3;
assert(row >= 0 && row < ESM::Land::LAND_SIZE);
assert(col >= 0 && col < ESM::Land::LAND_SIZE);
assert (vertX < numVerts);
assert (vertY < numVerts);
float height = -2048;
if (heightData)
@ -200,7 +214,7 @@ namespace ESMTerrain
if (normalData)
{
for (int i=0; i<3; ++i)
normal[i] = normalData->mNormals[arrayIndex+i];
normal[i] = normalData->mNormals[srcArrayIndex+i];
normal.normalize();
}
@ -222,7 +236,7 @@ namespace ESMTerrain
if (colourData)
{
for (int i=0; i<3; ++i)
color[i] = colourData->mColours[arrayIndex+i] / 255.f;
color[i] = colourData->mColours[srcArrayIndex+i] / 255.f;
}
else
{
@ -305,8 +319,19 @@ namespace ESMTerrain
// and interpolate the rest of the cell by hand? :/
osg::Vec2f origin = chunkCenter - osg::Vec2f(chunkSize/2.f, chunkSize/2.f);
int cellX = static_cast<int>(origin.x());
int cellY = static_cast<int>(origin.y());
int cellX = static_cast<int>(std::floor(origin.x()));
int cellY = static_cast<int>(std::floor(origin.y()));
int realTextureSize = ESM::Land::LAND_TEXTURE_SIZE+1; // add 1 to wrap around next cell
int rowStart = (origin.x() - cellX) * realTextureSize;
int colStart = (origin.y() - cellY) * realTextureSize;
int rowEnd = rowStart + chunkSize * (realTextureSize-1) + 1;
int colEnd = colStart + chunkSize * (realTextureSize-1) + 1;
assert (rowStart >= 0 && colStart >= 0);
assert (rowEnd <= realTextureSize);
assert (colEnd <= realTextureSize);
// Save the used texture indices so we know the total number of textures
// and number of required blend maps
@ -317,8 +342,8 @@ namespace ESMTerrain
// So we're always adding _land_default.dds as the base layer here, even if it's not referenced in this cell.
textureIndices.insert(std::make_pair(0,0));
for (int y=0; y<ESM::Land::LAND_TEXTURE_SIZE+1; ++y)
for (int x=0; x<ESM::Land::LAND_TEXTURE_SIZE+1; ++x)
for (int y=colStart; y<colEnd; ++y)
for (int x=rowStart; x<rowEnd; ++x)
{
UniqueTextureId id = getVtexIndexAt(cellX, cellY, x, y);
textureIndices.insert(id);
@ -342,7 +367,7 @@ namespace ESMTerrain
int channels = pack ? 4 : 1;
// Second iteration - create and fill in the blend maps
const int blendmapSize = ESM::Land::LAND_TEXTURE_SIZE+1;
const int blendmapSize = (realTextureSize-1) * chunkSize + 1;
for (int i=0; i<numBlendmaps; ++i)
{
@ -356,7 +381,8 @@ namespace ESMTerrain
{
for (int x=0; x<blendmapSize; ++x)
{
UniqueTextureId id = getVtexIndexAt(cellX, cellY, x, y);
UniqueTextureId id = getVtexIndexAt(cellX, cellY, x+rowStart, y+colStart);
assert(textureIndicesMap.find(id) != textureIndicesMap.end());
int layerIndex = textureIndicesMap.find(id)->second;
int blendIndex = (pack ? static_cast<int>(std::floor((layerIndex - 1) / 4.f)) : layerIndex - 1);
int channel = pack ? std::max(0, (layerIndex-1) % 4) : 0;

@ -0,0 +1,33 @@
#include "additivelayer.hpp"
#include <osg/BlendFunc>
#include <osg/StateSet>
#include "myguirendermanager.hpp"
namespace osgMyGUI
{
AdditiveLayer::AdditiveLayer()
{
mStateSet = new osg::StateSet;
mStateSet->setAttributeAndModes(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE));
}
AdditiveLayer::~AdditiveLayer()
{
// defined in .cpp file since we can't delete incomplete types
}
void AdditiveLayer::renderToTarget(MyGUI::IRenderTarget *_target, bool _update)
{
RenderManager& renderManager = static_cast<RenderManager&>(MyGUI::RenderManager::getInstance());
renderManager.setInjectState(mStateSet.get());
MyGUI::OverlappedLayer::renderToTarget(_target, _update);
renderManager.setInjectState(NULL);
}
}

@ -0,0 +1,33 @@
#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_ADDITIVELAYER
#define OPENMW_COMPONENTS_MYGUIPLATFORM_ADDITIVELAYER
#include <MyGUI_OverlappedLayer.h>
#include <osg/ref_ptr>
namespace osg
{
class StateSet;
}
namespace osgMyGUI
{
/// @brief A Layer rendering with additive blend mode.
class AdditiveLayer : public MyGUI::OverlappedLayer
{
public:
MYGUI_RTTI_DERIVED( AdditiveLayer )
AdditiveLayer();
~AdditiveLayer();
virtual void renderToTarget(MyGUI::IRenderTarget* _target, bool _update);
private:
osg::ref_ptr<osg::StateSet> mStateSet;
};
}
#endif

@ -1,2 +1,64 @@
#include "myguiplatform.hpp"
#include "myguirendermanager.hpp"
#include "myguidatamanager.hpp"
#include "myguiloglistener.hpp"
namespace osgMyGUI
{
Platform::Platform(osgViewer::Viewer *viewer, osg::Group *guiRoot, Resource::TextureManager *textureManager, float uiScalingFactor)
: mRenderManager(nullptr)
, mDataManager(nullptr)
, mLogManager(nullptr)
, mLogFacility(nullptr)
{
mLogManager = new MyGUI::LogManager();
mRenderManager = new RenderManager(viewer, guiRoot, textureManager, uiScalingFactor);
mDataManager = new DataManager();
}
Platform::~Platform()
{
delete mRenderManager;
mRenderManager = nullptr;
delete mDataManager;
mDataManager = nullptr;
delete mLogManager;
mLogManager = nullptr;
delete mLogFacility;
mLogFacility = nullptr;
}
void Platform::initialise(const std::string &resourcePath, const std::string &_logName)
{
if (!_logName.empty() && !mLogFacility)
{
mLogFacility = new LogFacility(_logName, false);
mLogManager->addLogSource(mLogFacility->getSource());
}
mDataManager->setResourcePath(resourcePath);
mRenderManager->initialise();
mDataManager->initialise();
}
void Platform::shutdown()
{
mRenderManager->shutdown();
mDataManager->shutdown();
}
RenderManager *Platform::getRenderManagerPtr()
{
return mRenderManager;
}
DataManager *Platform::getDataManagerPtr()
{
return mDataManager;
}
}

@ -1,71 +1,46 @@
#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_MYGUIPLATFORM_H
#define OPENMW_COMPONENTS_MYGUIPLATFORM_MYGUIPLATFORM_H
#include "MyGUI_Prerequest.h"
#include "MyGUI_LogManager.h"
#include <string>
#include "myguirendermanager.hpp"
#include "myguidatamanager.hpp"
#include "myguiloglistener.hpp"
namespace osgViewer
{
class Viewer;
}
namespace osg
{
class Group;
}
namespace Resource
{
class TextureManager;
}
namespace MyGUI
{
class LogManager;
}
namespace osgMyGUI
{
class RenderManager;
class DataManager;
class LogFacility;
class Platform
{
public:
Platform(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::TextureManager* textureManager, float uiScalingFactor)
: mRenderManager(nullptr)
, mDataManager(nullptr)
, mLogManager(nullptr)
, mLogFacility(nullptr)
{
mLogManager = new MyGUI::LogManager();
mRenderManager = new RenderManager(viewer, guiRoot, textureManager, uiScalingFactor);
mDataManager = new DataManager();
}
~Platform()
{
delete mRenderManager;
mRenderManager = nullptr;
delete mDataManager;
mDataManager = nullptr;
delete mLogManager;
mLogManager = nullptr;
delete mLogFacility;
mLogFacility = nullptr;
}
void initialise(const std::string& resourcePath, const std::string& _logName = "MyGUI.log")
{
if (!_logName.empty() && !mLogFacility)
{
mLogFacility = new LogFacility(_logName, false);
mLogManager->addLogSource(mLogFacility->getSource());
}
Platform(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::TextureManager* textureManager, float uiScalingFactor);
mDataManager->setResourcePath(resourcePath);
~Platform();
mRenderManager->initialise();
mDataManager->initialise();
}
void initialise(const std::string& resourcePath, const std::string& _logName = "MyGUI.log");
void shutdown()
{
mRenderManager->shutdown();
mDataManager->shutdown();
}
void shutdown();
RenderManager* getRenderManagerPtr()
{
return mRenderManager;
}
RenderManager* getRenderManagerPtr();
DataManager* getDataManagerPtr()
{
return mDataManager;
}
DataManager* getDataManagerPtr();
private:
RenderManager* mRenderManager;

@ -45,6 +45,9 @@ namespace osgMyGUI
class Drawable : public osg::Drawable {
osgMyGUI::RenderManager *mParent;
osg::ref_ptr<osg::StateSet> mStateSet;
public:
// Stage 0: update widget animations and controllers. Run during the Update traversal.
class FrameUpdate : public osg::Drawable::UpdateCallback
@ -101,6 +104,10 @@ class Drawable : public osg::Drawable {
virtual void drawImplementation(osg::RenderInfo &renderInfo) const
{
osg::State *state = renderInfo.getState();
state->pushStateSet(mStateSet);
state->apply();
state->disableAllVertexArrays();
state->setClientActiveTextureUnit(0);
glEnableClientState(GL_VERTEX_ARRAY);
@ -113,6 +120,13 @@ class Drawable : public osg::Drawable {
{
const Batch& batch = *it;
osg::VertexBufferObject *vbo = batch.mVertexBuffer;
if (batch.mStateSet)
{
state->pushStateSet(batch.mStateSet);
state->apply();
}
osg::Texture2D* texture = batch.mTexture;
if(texture)
state->applyTextureAttribute(0, texture);
@ -135,12 +149,20 @@ class Drawable : public osg::Drawable {
}
glDrawArrays(GL_TRIANGLES, 0, batch.mVertexCount);
if (batch.mStateSet)
{
state->popStateSet();
state->apply();
}
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
state->popStateSet();
state->unbindVertexBufferObject();
state->dirtyAllVertexArrays();
state->disableAllVertexArrays();
@ -161,10 +183,17 @@ public:
osg::ref_ptr<FrameUpdate> frameUpdate = new FrameUpdate;
frameUpdate->setRenderManager(mParent);
setUpdateCallback(frameUpdate);
mStateSet = new osg::StateSet;
mStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
mStateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
mStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
mStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
}
Drawable(const Drawable &copy, const osg::CopyOp &copyop=osg::CopyOp::SHALLOW_COPY)
: osg::Drawable(copy, copyop)
, mParent(copy.mParent)
, mStateSet(copy.mStateSet)
, mWriteTo(0)
, mReadFrom(0)
{
@ -180,6 +209,9 @@ public:
// need to hold on to this too as the mVertexBuffer does not hold a ref to its own array
osg::ref_ptr<osg::UByteArray> mArray;
// optional
osg::ref_ptr<osg::StateSet> mStateSet;
size_t mVertexCount;
};
@ -321,6 +353,7 @@ RenderManager::RenderManager(osgViewer::Viewer *viewer, osg::Group *sceneroot, R
, mUpdate(false)
, mIsInitialise(false)
, mInvScalingFactor(1.f)
, mInjectState(NULL)
{
if (scalingFactor != 0.f)
mInvScalingFactor = 1.f / scalingFactor;
@ -364,12 +397,6 @@ void RenderManager::initialise()
camera->setViewMatrix(osg::Matrix::identity());
camera->setRenderOrder(osg::Camera::POST_RENDER);
camera->setClearMask(GL_NONE);
osg::StateSet *state = new osg::StateSet;
state->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
state->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
state->setMode(GL_BLEND, osg::StateAttribute::ON);
state->setAttribute(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
geode->setStateSet(state);
geode->setCullingActive(false);
camera->addChild(geode.get());
@ -418,10 +445,17 @@ void RenderManager::doRender(MyGUI::IVertexBuffer *buffer, MyGUI::ITexture *text
if (batch.mTexture->getDataVariance() == osg::Object::DYNAMIC)
mDrawable->setDataVariance(osg::Object::DYNAMIC); // only for this frame, reset in begin()
}
if (mInjectState)
batch.mStateSet = mInjectState;
mDrawable->addBatch(batch);
}
void RenderManager::setInjectState(osg::StateSet* stateSet)
{
mInjectState = stateSet;
}
void RenderManager::end()
{
}

@ -20,6 +20,7 @@ namespace osg
class Group;
class Camera;
class RenderInfo;
class StateSet;
}
namespace osgMyGUI
@ -48,6 +49,8 @@ class RenderManager : public MyGUI::RenderManager, public MyGUI::IRenderTarget
float mInvScalingFactor;
osg::StateSet* mInjectState;
void destroyAllResources();
public:
@ -95,6 +98,9 @@ public:
/** @see IRenderTarget::doRender */
virtual void doRender(MyGUI::IVertexBuffer *buffer, MyGUI::ITexture *texture, size_t count);
/** specify a StateSet to inject for rendering. The StateSet will be used by future doRender calls until you reset it to NULL again. */
void setInjectState(osg::StateSet* stateSet);
/** @see IRenderTarget::getInfo */
virtual const MyGUI::RenderTargetInfo& getInfo() { return mInfo; }

@ -0,0 +1,139 @@
#include "scalinglayer.hpp"
#include <MyGUI_RenderManager.h>
namespace osgMyGUI
{
/// @brief the ProxyRenderTarget allows to adjust the pixel scale and offset for a "source" render target.
class ProxyRenderTarget : public MyGUI::IRenderTarget
{
public:
/// @param target The target to render to.
/// @param viewSize The size of the underlying layer node to render.
/// @param hoffset The horizontal rendering offset, specified as an offset from the left screen edge in range 0-1.
/// @param voffset The vertical rendering offset, specified as an offset from the top screen edge in range 0-1.
ProxyRenderTarget(MyGUI::IRenderTarget* target, MyGUI::IntSize viewSize, float hoffset, float voffset)
: mTarget(target)
, mViewSize(viewSize)
, mHOffset(hoffset)
, mVOffset(voffset)
{
}
virtual void begin()
{
mTarget->begin();
}
virtual void end()
{
mTarget->end();
}
virtual void doRender(MyGUI::IVertexBuffer* _buffer, MyGUI::ITexture* _texture, size_t _count)
{
mTarget->doRender(_buffer, _texture, _count);
}
virtual const MyGUI::RenderTargetInfo& getInfo()
{
mInfo = mTarget->getInfo();
mInfo.hOffset = mHOffset;
mInfo.vOffset = mVOffset;
mInfo.pixScaleX = 1.f / mViewSize.width;
mInfo.pixScaleY = 1.f / mViewSize.height;
return mInfo;
}
private:
MyGUI::IRenderTarget* mTarget;
MyGUI::IntSize mViewSize;
float mHOffset, mVOffset;
MyGUI::RenderTargetInfo mInfo;
};
MyGUI::ILayerItem *ScalingLayer::getLayerItemByPoint(int _left, int _top) const
{
screenToLayerCoords(_left, _top);
return OverlappedLayer::getLayerItemByPoint(_left, _top);
}
void ScalingLayer::screenToLayerCoords(int& _left, int& _top) const
{
float scale = getScaleFactor();
if (scale <= 0.f)
return;
MyGUI::IntSize globalViewSize = MyGUI::RenderManager::getInstance().getViewSize();
_left -= globalViewSize.width/2;
_top -= globalViewSize.height/2;
_left /= scale;
_top /= scale;
_left += mViewSize.width/2;
_top += mViewSize.height/2;
}
float ScalingLayer::getScaleFactor() const
{
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
float w = viewSize.width;
float h = viewSize.height;
float heightScale = (h / mViewSize.height);
float widthScale = (w / mViewSize.width);
return std::min(widthScale, heightScale);
}
MyGUI::IntPoint ScalingLayer::getPosition(int _left, int _top) const
{
screenToLayerCoords(_left, _top);
return MyGUI::IntPoint(_left, _top);
}
void ScalingLayer::renderToTarget(MyGUI::IRenderTarget *_target, bool _update)
{
MyGUI::IntSize globalViewSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntSize viewSize = globalViewSize;
float scale = getScaleFactor();
viewSize.width /= scale;
viewSize.height /= scale;
float hoffset = (globalViewSize.width - mViewSize.width*getScaleFactor())/2.f / static_cast<float>(globalViewSize.width);
float voffset = (globalViewSize.height - mViewSize.height*getScaleFactor())/2.f / static_cast<float>(globalViewSize.height);
ProxyRenderTarget proxy(_target, viewSize, hoffset, voffset);
MyGUI::OverlappedLayer::renderToTarget(&proxy, _update);
}
void ScalingLayer::resizeView(const MyGUI::IntSize &_viewSize)
{
// do nothing
}
void ScalingLayer::deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version)
{
MyGUI::OverlappedLayer::deserialization(_node, _version);
MyGUI::xml::ElementEnumerator info = _node->getElementEnumerator();
while (info.next())
{
if (info->getName() == "Property")
{
const std::string& key = info->findAttribute("key");
const std::string& value = info->findAttribute("value");
if (key == "Size")
{
mViewSize = MyGUI::IntSize::parse(value);
}
}
}
}
}

@ -0,0 +1,31 @@
#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_SCALINGLAYER
#define OPENMW_COMPONENTS_MYGUIPLATFORM_SCALINGLAYER
#include <MyGUI_OverlappedLayer.h>
namespace osgMyGUI
{
///@brief A Layer that lays out and renders widgets in screen-relative coordinates. The "Size" property determines the size of the virtual screen,
/// which is then upscaled to the real screen size during rendering. The aspect ratio is kept intact, adding blanks to the sides when necessary.
class ScalingLayer : public MyGUI::OverlappedLayer
{
public:
MYGUI_RTTI_DERIVED(ScalingLayer)
virtual void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version);
virtual MyGUI::ILayerItem* getLayerItemByPoint(int _left, int _top) const;
virtual MyGUI::IntPoint getPosition(int _left, int _top) const;
virtual void renderToTarget(MyGUI::IRenderTarget* _target, bool _update);
virtual void resizeView(const MyGUI::IntSize& _viewSize);
private:
void screenToLayerCoords(int& _left, int& _top) const;
float getScaleFactor() const;
};
}
#endif

@ -76,7 +76,7 @@ namespace SceneUtil
struct LightSourceTransform
{
osg::ref_ptr<LightSource> mLightSource;
LightSource* mLightSource;
osg::Matrix mWorldMatrix;
};
@ -84,7 +84,7 @@ namespace SceneUtil
struct LightSourceViewBound
{
osg::ref_ptr<LightSource> mLightSource;
LightSource* mLightSource;
osg::BoundingSphere mViewBound;
};

@ -11,7 +11,7 @@ namespace Terrain
{
FixedFunctionTechnique::FixedFunctionTechnique(const std::vector<osg::ref_ptr<osg::Texture2D> >& layers,
const std::vector<osg::ref_ptr<osg::Texture2D> >& blendmaps)
const std::vector<osg::ref_ptr<osg::Texture2D> >& blendmaps, int blendmapScale, float layerTileSize)
{
bool firstLayer = true;
int i=0;
@ -36,7 +36,7 @@ namespace Terrain
// This is to map corner vertices directly to the center of a blendmap texel.
osg::Matrixf texMat;
float scale = (16/(16.f+1.f));
float scale = (blendmapScale/(static_cast<float>(blendmapScale)+1.f));
texMat.preMultTranslate(osg::Vec3f(0.5f, 0.5f, 0.f));
texMat.preMultScale(osg::Vec3f(scale, scale, 1.f));
texMat.preMultTranslate(osg::Vec3f(-0.5f, -0.5f, 0.f));
@ -57,8 +57,7 @@ namespace Terrain
stateset->setTextureAttributeAndModes(texunit, tex.get());
osg::ref_ptr<osg::TexMat> texMat (new osg::TexMat);
float scale = 16.f;
texMat->setMatrix(osg::Matrix::scale(osg::Vec3f(scale,scale,1.f)));
texMat->setMatrix(osg::Matrix::scale(osg::Vec3f(layerTileSize,layerTileSize,1.f)));
stateset->setTextureAttributeAndModes(texunit, texMat, osg::StateAttribute::ON);
firstLayer = false;
@ -67,9 +66,12 @@ namespace Terrain
}
}
Effect::Effect(const std::vector<osg::ref_ptr<osg::Texture2D> > &layers, const std::vector<osg::ref_ptr<osg::Texture2D> > &blendmaps)
Effect::Effect(const std::vector<osg::ref_ptr<osg::Texture2D> > &layers, const std::vector<osg::ref_ptr<osg::Texture2D> > &blendmaps,
int blendmapScale, float layerTileSize)
: mLayers(layers)
, mBlendmaps(blendmaps)
, mBlendmapScale(blendmapScale)
, mLayerTileSize(layerTileSize)
{
osg::ref_ptr<osg::Material> material (new osg::Material);
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
@ -80,7 +82,7 @@ namespace Terrain
bool Effect::define_techniques()
{
addTechnique(new FixedFunctionTechnique(mLayers, mBlendmaps));
addTechnique(new FixedFunctionTechnique(mLayers, mBlendmaps, mBlendmapScale, mLayerTileSize));
return true;
}

@ -19,7 +19,7 @@ namespace Terrain
public:
FixedFunctionTechnique(
const std::vector<osg::ref_ptr<osg::Texture2D> >& layers,
const std::vector<osg::ref_ptr<osg::Texture2D> >& blendmaps);
const std::vector<osg::ref_ptr<osg::Texture2D> >& blendmaps, int blendmapScale, float layerTileSize);
protected:
virtual void define_passes() {}
@ -30,7 +30,7 @@ namespace Terrain
public:
Effect(
const std::vector<osg::ref_ptr<osg::Texture2D> >& layers,
const std::vector<osg::ref_ptr<osg::Texture2D> >& blendmaps);
const std::vector<osg::ref_ptr<osg::Texture2D> >& blendmaps, int blendmapScale, float layerTileSize);
virtual bool define_techniques();
@ -50,6 +50,8 @@ namespace Terrain
private:
std::vector<osg::ref_ptr<osg::Texture2D> > mLayers;
std::vector<osg::ref_ptr<osg::Texture2D> > mBlendmaps;
int mBlendmapScale;
float mLayerTileSize;
};
}

@ -7,6 +7,8 @@
#include <components/sceneutil/lightmanager.hpp>
#include <components/esm/loadland.hpp>
#include <osg/PositionAttitudeTransform>
#include <osg/Geometry>
#include <osg/Geode>
@ -45,8 +47,10 @@ namespace Terrain
TerrainGrid::TerrainGrid(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUtil::IncrementalCompileOperation* ico,
Storage* storage, int nodeMask)
: Terrain::World(parent, resourceSystem, ico, storage, nodeMask)
, mNumSplits(4)
, mKdTreeBuilder(new osg::KdTreeBuilder)
{
mCache = BufferCache((storage->getCellVertices()-1)/static_cast<float>(mNumSplits) + 1);
}
TerrainGrid::~TerrainGrid()
@ -60,108 +64,144 @@ TerrainGrid::~TerrainGrid()
class GridElement
{
public:
osg::ref_ptr<osg::PositionAttitudeTransform> mNode;
osg::ref_ptr<osg::Node> mNode;
};
void TerrainGrid::loadCell(int x, int y)
osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter)
{
if (mGrid.find(std::make_pair(x, y)) != mGrid.end())
return; // already loaded
if (chunkSize * mNumSplits > 1.f)
{
// keep splitting
osg::ref_ptr<osg::Group> group (new osg::Group);
if (parent)
parent->addChild(group);
float newChunkSize = chunkSize/2.f;
buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, newChunkSize/2.f));
buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, -newChunkSize/2.f));
buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize/2.f, newChunkSize/2.f));
buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize/2.f, -newChunkSize/2.f));
return group;
}
else
{
float minH, maxH;
if (!mStorage->getMinMaxHeights(chunkSize, chunkCenter, minH, maxH))
return NULL; // no terrain defined
osg::Vec2f center(x+0.5f, y+0.5f);
float minH, maxH;
if (!mStorage->getMinMaxHeights(1, center, minH, maxH))
return; // no terrain defined
osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize();
osg::ref_ptr<osg::PositionAttitudeTransform> transform (new osg::PositionAttitudeTransform);
transform->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f));
std::auto_ptr<GridElement> element (new GridElement);
if (parent)
parent->addChild(transform);
osg::Vec2f worldCenter = center*mStorage->getCellWorldSize();
element->mNode = new osg::PositionAttitudeTransform;
element->mNode->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f));
mTerrainRoot->addChild(element->mNode);
osg::ref_ptr<osg::Vec3Array> positions (new osg::Vec3Array);
osg::ref_ptr<osg::Vec3Array> normals (new osg::Vec3Array);
osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array);
osg::ref_ptr<osg::Vec3Array> positions (new osg::Vec3Array);
osg::ref_ptr<osg::Vec3Array> normals (new osg::Vec3Array);
osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array);
osg::ref_ptr<osg::VertexBufferObject> vbo (new osg::VertexBufferObject);
positions->setVertexBufferObject(vbo);
normals->setVertexBufferObject(vbo);
colors->setVertexBufferObject(vbo);
osg::ref_ptr<osg::VertexBufferObject> vbo (new osg::VertexBufferObject);
positions->setVertexBufferObject(vbo);
normals->setVertexBufferObject(vbo);
colors->setVertexBufferObject(vbo);
mStorage->fillVertexBuffers(0, chunkSize, chunkCenter, positions, normals, colors);
mStorage->fillVertexBuffers(0, 1, center, positions, normals, colors);
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
geometry->setVertexArray(positions);
geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
geometry->setUseDisplayList(false);
geometry->setUseVertexBufferObjects(true);
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
geometry->setVertexArray(positions);
geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
geometry->setUseDisplayList(false);
geometry->setUseVertexBufferObjects(true);
geometry->addPrimitiveSet(mCache.getIndexBuffer(0));
geometry->addPrimitiveSet(mCache.getIndexBuffer(0));
// we already know the bounding box, so no need to let OSG compute it.
osg::Vec3f min(-0.5f*mStorage->getCellWorldSize()*chunkSize,
-0.5f*mStorage->getCellWorldSize()*chunkSize,
minH);
osg::Vec3f max (0.5f*mStorage->getCellWorldSize()*chunkSize,
0.5f*mStorage->getCellWorldSize()*chunkSize,
maxH);
osg::BoundingBox bounds(min, max);
geometry->setComputeBoundingBoxCallback(new StaticBoundingBoxCallback(bounds));
// we already know the bounding box, so no need to let OSG compute it.
osg::Vec3f min(-0.5f*mStorage->getCellWorldSize(),
-0.5f*mStorage->getCellWorldSize(),
minH);
osg::Vec3f max (0.5f*mStorage->getCellWorldSize(),
0.5f*mStorage->getCellWorldSize(),
maxH);
osg::BoundingBox bounds(min, max);
geometry->setComputeBoundingBoxCallback(new StaticBoundingBoxCallback(bounds));
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
geode->addDrawable(geometry);
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
geode->addDrawable(geometry);
// build a kdtree to speed up intersection tests with the terrain
// Note, the build could be optimized using a custom kdtree builder, since we know that the terrain can be represented by a quadtree
geode->accept(*mKdTreeBuilder);
std::vector<LayerInfo> layerList;
std::vector<osg::ref_ptr<osg::Image> > blendmaps;
mStorage->getBlendmaps(chunkSize, chunkCenter, false, blendmaps, layerList);
std::vector<LayerInfo> layerList;
std::vector<osg::ref_ptr<osg::Image> > blendmaps;
mStorage->getBlendmaps(1.f, center, false, blendmaps, layerList);
// For compiling textures, I don't think the osgFX::Effect does it correctly
osg::ref_ptr<osg::Node> textureCompileDummy (new osg::Node);
// For compiling textures, I don't think the osgFX::Effect does it correctly
osg::ref_ptr<osg::Node> textureCompileDummy (new osg::Node);
std::vector<osg::ref_ptr<osg::Texture2D> > layerTextures;
for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it)
{
layerTextures.push_back(mResourceSystem->getTextureManager()->getTexture2D(it->mDiffuseMap, osg::Texture::REPEAT, osg::Texture::REPEAT));
textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back());
}
std::vector<osg::ref_ptr<osg::Texture2D> > layerTextures;
for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it)
{
layerTextures.push_back(mResourceSystem->getTextureManager()->getTexture2D(it->mDiffuseMap, osg::Texture::REPEAT, osg::Texture::REPEAT));
textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back());
}
std::vector<osg::ref_ptr<osg::Texture2D> > blendmapTextures;
for (std::vector<osg::ref_ptr<osg::Image> >::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it)
{
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D);
texture->setImage(*it);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
texture->setResizeNonPowerOfTwoHint(false);
blendmapTextures.push_back(texture);
textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back());
}
std::vector<osg::ref_ptr<osg::Texture2D> > blendmapTextures;
for (std::vector<osg::ref_ptr<osg::Image> >::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it)
{
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D);
texture->setImage(*it);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
texture->setResizeNonPowerOfTwoHint(false);
blendmapTextures.push_back(texture);
textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back());
}
// use texture coordinates for both texture units, the layer texture and blend texture
for (unsigned int i=0; i<2; ++i)
geometry->setTexCoordArray(i, mCache.getUVBuffer());
// use texture coordinates for both texture units, the layer texture and blend texture
for (unsigned int i=0; i<2; ++i)
geometry->setTexCoordArray(i, mCache.getUVBuffer());
float blendmapScale = ESM::Land::LAND_TEXTURE_SIZE*chunkSize;
osg::ref_ptr<osgFX::Effect> effect (new Terrain::Effect(layerTextures, blendmapTextures, blendmapScale, blendmapScale));
osg::ref_ptr<osgFX::Effect> effect (new Terrain::Effect(layerTextures, blendmapTextures));
effect->addCullCallback(new SceneUtil::LightListCallback);
effect->addCullCallback(new SceneUtil::LightListCallback);
transform->addChild(effect);
effect->addChild(geode);
effect->addChild(geode);
element->mNode->addChild(effect);
if (mIncrementalCompileOperation)
{
mIncrementalCompileOperation->add(geode);
mIncrementalCompileOperation->add(textureCompileDummy);
}
if (mIncrementalCompileOperation)
{
mIncrementalCompileOperation->add(geode);
mIncrementalCompileOperation->add(textureCompileDummy);
return transform;
}
}
void TerrainGrid::loadCell(int x, int y)
{
if (mGrid.find(std::make_pair(x, y)) != mGrid.end())
return; // already loaded
osg::Vec2f center(x+0.5f, y+0.5f);
osg::ref_ptr<osg::Node> terrainNode = buildTerrain(NULL, 1.f, center);
if (!terrainNode)
return; // no terrain defined
std::auto_ptr<GridElement> element (new GridElement);
element->mNode = terrainNode;
mTerrainRoot->addChild(element->mNode);
// kdtree probably not needed with mNumSplits=4
/*
// build a kdtree to speed up intersection tests with the terrain
// Note, the build could be optimized using a custom kdtree builder, since we know that the terrain can be represented by a quadtree
geode->accept(*mKdTreeBuilder);
*/
mGrid[std::make_pair(x,y)] = element.release();
}

@ -1,6 +1,8 @@
#ifndef COMPONENTS_TERRAIN_TERRAINGRID_H
#define COMPONENTS_TERRAIN_TERRAINGRID_H
#include <osg/Vec2f>
#include "world.hpp"
#include "material.hpp"
@ -26,6 +28,11 @@ namespace Terrain
virtual void unloadCell(int x, int y);
private:
osg::ref_ptr<osg::Node> buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter);
// split each ESM::Cell into mNumSplits*mNumSplits terrain chunks
unsigned int mNumSplits;
typedef std::map<std::pair<int, int>, GridElement*> Grid;
Grid mGrid;

@ -80,6 +80,7 @@ set(MYGUI_FILES
openmw_savegame_dialog.layout
openmw_recharge_dialog.layout
openmw_screen_fader.layout
openmw_screen_fader_hit.layout
openmw_edit_note.layout
openmw_debug_window.layout
openmw_debug_window.skin.xml

@ -2,7 +2,7 @@
<MyGUI type="Layout">
<Widget type="Window" skin="" layer="Windows" align="Left Top" position="0 0 584 398" name="_Main">
<Widget type="Window" skin="" layer="JournalBooks" align="Left Top" position="0 0 584 398" name="_Main">
<Widget type="ImageBox" skin="ImageBox" position="-71 0 728 398" align="Left Top" name="JImage">
<Property key="ImageTexture" value="textures\tx_menubook.dds"/>

@ -125,11 +125,5 @@
<Widget type="ImageBox" skin="HUD_Crosshair" position="0 0 32 32" align="Center Center" name="Crosshair">
</Widget>
<!-- Basic FPSCounter box -->
<Widget type="Widget" skin="" position="12 12 32 26" align="Left Top" name="FPSBox">
<Property key="Visible" value="false"/>
<Widget type="TextBox" skin="NumFPS" position="3 3 25 17" align="Center" name="FPSCounter"/>
</Widget>
</Widget>
</MyGUI>

@ -2,7 +2,7 @@
<MyGUI type="Layout">
<Widget type="Window" skin="" layer="Windows" align="Left|Top" position="0 0 565 390" name="_Main">
<Widget type="Window" skin="" layer="JournalBooks" align="Left|Top" position="0 0 565 390" name="_Main">
<!-- pages -->
<Widget type="ImageBox" skin="ImageBox" position="-70 0 705 390" align="Top|Right" name="JImage">
<Property key="ImageTexture" value="textures\tx_menubook.dds"/>

@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layer" version="1.0">
<Layer name="Render" overlapped="false" pick="false"/>
<Layer name="Overlay" overlapped="false" pick="false"/>
<Layer name="AdditiveOverlay" type="AdditiveLayer" pick="false"/>
<Layer name="HUD" overlapped="false" pick="true"/>
<Layer name="Menu" overlapped="false" pick="false"/>
<Layer name="Windows" overlapped="true" pick="true"/>
<Layer name="JournalBooks" type="ScalingLayer" pick="true">
<Property key="Size" value="600 520"/>
</Layer>
<Layer name="Console" overlapped="false" pick="true"/>
<Layer name="Debug" overlapped="true" pick="true"/>
<Layer name="Notification" overlapped="false" pick="false"/>
@ -12,6 +16,6 @@
<Layer name="DragAndDrop" overlapped="false" pick="false"/>
<Layer name="LoadingScreen" overlapped="false" pick="true"/>
<Layer name="MessageBox" overlapped="false" pick="true"/>
<Layer name="Overlay" overlapped="false" pick="true"/>
<Layer name="InputBlocker" overlapped="false" pick="true"/>
<Layer name="Pointer" overlapped="false" pick="false"/>
</MyGUI>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="ImageBox" skin="ImageBox" layer="Render" position="0 0 300 200" name="_Main" align="Stretch">
<Widget type="ImageBox" skin="ImageBox" layer="Overlay" position="0 0 300 200" name="_Main" align="Stretch">
<Property key="ImageTexture" value="black"/>
</Widget>
</MyGUI>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="ImageBox" skin="ImageBox" layer="AdditiveOverlay" position="0 0 300 200" name="_Main" align="Stretch">
<Property key="ImageTexture" value="black"/>
</Widget>
</MyGUI>

@ -2,24 +2,24 @@
<MyGUI type="Layout">
<Widget type="Window" skin="" layer="Windows" position="0 0 512 512" name="_Main">
<Widget type="Window" skin="" layer="JournalBooks" position="0 0 512 372" name="_Main">
<Widget type="ImageBox" skin="ImageBox" position_real="0 0 1 1" name="ScrollImage">
<Property key="ImageTexture" value="textures\scroll.dds"/>
<Widget type="ImageButton" skin="ImageBox" position="12 18 128 32" name="TakeButton">
<Widget type="ImageButton" skin="ImageBox" position="12 14 128 32" name="TakeButton">
<Property key="ImageHighlighted" value="textures\tx_menubook_take_over.dds"/>
<Property key="ImageNormal" value="textures\tx_menubook_take_idle.dds"/>
<Property key="ImagePushed" value="textures\tx_menubook_take_pressed.dds"/>
</Widget>
<Widget type="ImageButton" skin="ImageBox" position="415 24 128 32" name="CloseButton">
<Widget type="ImageButton" skin="ImageBox" position="415 20 128 32" name="CloseButton">
<Property key="ImageHighlighted" value="textures\tx_menubook_close_over.dds"/>
<Property key="ImageNormal" value="textures\tx_menubook_close_idle.dds"/>
<Property key="ImagePushed" value="textures\tx_menubook_close_pressed.dds"/>
</Widget>
<Widget type="ScrollView" skin="MW_ScrollView" position="60 130 410 300" name="TextView">
<Widget type="ScrollView" skin="MW_ScrollView" position="60 84 410 235" name="TextView">
<Property key="CanvasSize" value="410 900"/>
</Widget>

@ -255,13 +255,9 @@
<Property key="Caption" value="Window border"/>
</Widget>
</Widget>
<Widget type="HBox" skin="" position="182 94 300 24">
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 24 24" align="Left Top" name="FPSButton"/>
<Widget type="AutoSizedTextBox" skin="SandText" position="28 4 32 16" align="Left Top">
<Property key="Caption" value="FPS"/>
</Widget>
</Widget>
<Widget type="HBox" skin="" position="182 124 300 24">
<Property key="Visible" value="false"/>
<UserString key="Hidden" value="true"/>
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 24 24" align="Left Top" name="ShadersButton">
<UserString key="SettingCategory" value="Objects"/>
<UserString key="SettingName" value="shaders"/>
@ -271,6 +267,12 @@
<Property key="Caption" value="Object shaders"/>
</Widget>
</Widget>
<Widget type="TextBox" skin="SandText" position="182 94 300 32" align="Left Top">
<Property key="MultiLine" value="true"/>
<Property key="Caption" value="Hint: press F3 to show \nthe current frame rate."/>
</Widget>
<Widget type="TextBox" skin="NormalText" position="0 198 329 18" align="Left Top" name="FovText">
<Property key="Caption" value="Field of View"/>
</Widget>
@ -392,7 +394,11 @@
</Widget>
</Widget>
<!--
<Widget type="TabItem" skin="" position="0 28 352 268">
-->
<Widget type="Widget" skin="" position="0 28 352 268">
<Property key="Visible" value="false"/>
<Property key="Caption" value=" Shadows "/>
<Widget type="HBox" skin="" position="4 4 350 24">
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 24 24" align="Left Top" name="ShadowsEnabledButton">

@ -18,15 +18,6 @@ color_misc=0,205,205 # ????
</BasisSkin>
</Resource>
<Resource type="ResourceSkin" name="NumFPS" size="16 16">
<Property key="FontName" value="MonoFont"/>
<Property key="TextAlign" value="HCenter Bottom"/>
<Property key="TextColour" value="1 1 1"/>
<Property key="TextShadow" value="true"/>
<BasisSkin type="SimpleText" offset="0 0 16 16" align="Stretch"/>
</Resource>
<Resource type="ResourceSkin" name="SandText" size="16 16">
<Property key="FontName" value="Default"/>
<Property key="TextAlign" value="Left Bottom"/>

@ -84,11 +84,6 @@ fade start = 0.8
debug = false
[HUD]
# FPS counter
# 0: not visible
# 1: FPS display
fps = 0
crosshair = true
[Objects]

Loading…
Cancel
Save