forked from teamnwah/openmw-tes3coop
Companion UI
This commit is contained in:
parent
69099c11a2
commit
b0199c703c
23 changed files with 130 additions and 27 deletions
|
@ -31,7 +31,7 @@ add_openmw_dir (mwgui
|
|||
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
|
||||
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
|
||||
enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons
|
||||
merchantrepair repair soulgemdialog
|
||||
merchantrepair repair soulgemdialog companionwindow
|
||||
)
|
||||
|
||||
add_openmw_dir (mwdialogue
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace MWBase
|
|||
|
||||
virtual ~DialogueManager() {}
|
||||
|
||||
virtual bool isInChoice() const = 0;
|
||||
|
||||
virtual void startDialogue (const MWWorld::Ptr& actor) = 0;
|
||||
|
||||
virtual void addTopic (const std::string& topic) = 0;
|
||||
|
|
|
@ -201,6 +201,7 @@ namespace MWBase
|
|||
///< Hides dialog and schedules dialog to be deleted.
|
||||
|
||||
virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons = std::vector<std::string>()) = 0;
|
||||
|
||||
virtual void enterPressed () = 0;
|
||||
virtual int readPressedButton() = 0;
|
||||
///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
|
||||
|
@ -235,6 +236,7 @@ namespace MWBase
|
|||
virtual bool getPlayerSleeping() = 0;
|
||||
virtual void wakeUpPlayer() = 0;
|
||||
|
||||
virtual void showCompanionWindow(MWWorld::Ptr actor) = 0;
|
||||
virtual void startSpellMaking(MWWorld::Ptr actor) = 0;
|
||||
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
|
||||
virtual void startSelfEnchanting(MWWorld::Ptr soulgem) = 0;
|
||||
|
|
|
@ -117,6 +117,8 @@ namespace MWDialogue
|
|||
|
||||
void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
|
||||
{
|
||||
mLastTopic = "";
|
||||
|
||||
mChoice = -1;
|
||||
mIsInChoice = false;
|
||||
|
||||
|
@ -127,6 +129,9 @@ namespace MWDialogue
|
|||
|
||||
mActorKnownTopics.clear();
|
||||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor));
|
||||
|
||||
//setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI
|
||||
updateTopics();
|
||||
|
||||
|
@ -145,8 +150,6 @@ namespace MWDialogue
|
|||
{
|
||||
//initialise the GUI
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue);
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor));
|
||||
|
||||
creatureStats.talkedToPlayer();
|
||||
|
||||
|
@ -160,7 +163,7 @@ namespace MWDialogue
|
|||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||
win->addText (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||
executeScript (info->mResultScript);
|
||||
mLastTopic = it->mId;
|
||||
mLastTopic = Misc::StringUtils::lowerCase(it->mId);
|
||||
mLastDialogue = *info;
|
||||
break;
|
||||
}
|
||||
|
@ -398,6 +401,11 @@ namespace MWDialogue
|
|||
updateTopics();
|
||||
}
|
||||
|
||||
bool DialogueManager::isInChoice() const
|
||||
{
|
||||
return mIsInChoice;
|
||||
}
|
||||
|
||||
void DialogueManager::goodbyeSelected()
|
||||
{
|
||||
// Do not close the dialogue window if the player has to answer a question
|
||||
|
@ -424,15 +432,13 @@ namespace MWDialogue
|
|||
|
||||
if (mDialogueMap.find(mLastTopic) != mDialogueMap.end())
|
||||
{
|
||||
if (mDialogueMap[mLastTopic].mType == ESM::Dialogue::Topic)
|
||||
{
|
||||
Filter filter (mActor, mChoice, mTalkedTo);
|
||||
Filter filter (mActor, mChoice, mTalkedTo);
|
||||
|
||||
if (mDialogueMap[mLastTopic].mType == ESM::Dialogue::Topic
|
||||
|| mDialogueMap[mLastTopic].mType == ESM::Dialogue::Greeting)
|
||||
{
|
||||
if (const ESM::DialInfo *info = filter.search (mDialogueMap[mLastTopic], true))
|
||||
{
|
||||
mChoiceMap.clear();
|
||||
mChoice = -1;
|
||||
mIsInChoice = false;
|
||||
std::string text = info->mResponse;
|
||||
parseText (text);
|
||||
|
||||
|
@ -440,10 +446,12 @@ namespace MWDialogue
|
|||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (Interpreter::fixDefinesDialog(text, interpreterContext));
|
||||
MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId);
|
||||
executeScript (info->mResultScript);
|
||||
mLastTopic = mLastTopic;
|
||||
mLastDialogue = *info;
|
||||
}
|
||||
}
|
||||
mChoiceMap.clear();
|
||||
mChoice = -1;
|
||||
mIsInChoice = false;
|
||||
}
|
||||
|
||||
updateTopics();
|
||||
|
|
|
@ -54,6 +54,8 @@ namespace MWDialogue
|
|||
|
||||
DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose, Translation::Storage& translationDataStorage);
|
||||
|
||||
virtual bool isInChoice() const;
|
||||
|
||||
virtual void startDialogue (const MWWorld::Ptr& actor);
|
||||
|
||||
virtual void addTopic (const std::string& topic);
|
||||
|
|
|
@ -340,6 +340,9 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
|
|||
drawItems();
|
||||
mDragAndDrop->mDraggedFrom->drawItems();
|
||||
|
||||
mDragAndDrop->mDraggedFrom->notifyItemDragged(object, -mDragAndDrop->mDraggedCount);
|
||||
notifyItemDragged(object, mDragAndDrop->mDraggedCount);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setDragDrop(false);
|
||||
|
||||
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
|
||||
|
|
|
@ -82,6 +82,10 @@ namespace MWGui
|
|||
void setFilter(int filter); ///< set category filter
|
||||
void drawItems();
|
||||
|
||||
/// fired when an item was moved by drag&drop. \n
|
||||
/// if it was removed from this container, count will be negative.
|
||||
virtual void notifyItemDragged(MWWorld::Ptr item, int count) {}
|
||||
|
||||
protected:
|
||||
bool mDisplayEquippedItems;
|
||||
bool mHighlightEquippedItems;
|
||||
|
|
|
@ -228,7 +228,8 @@ void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
|
|||
|
||||
void DialogueWindow::onSelectTopic(const std::string& topic, int id)
|
||||
{
|
||||
if (!mEnabled) return;
|
||||
if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
||||
return;
|
||||
|
||||
int separatorPos = 0;
|
||||
for (unsigned int i=0; i<mTopicsList->getItemCount(); ++i)
|
||||
|
@ -248,6 +249,11 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id)
|
|||
{
|
||||
mPersuasionDialog.setVisible(true);
|
||||
}
|
||||
else if (topic == gmst.find("sCompanionShare")->getString())
|
||||
{
|
||||
mWindowManager.pushGuiMode(GM_Companion);
|
||||
mWindowManager.showCompanionWindow(mPtr);
|
||||
}
|
||||
else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused())
|
||||
{
|
||||
if (topic == gmst.find("sBarter")->getString())
|
||||
|
@ -306,7 +312,10 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
|||
{
|
||||
mTopicsList->clear();
|
||||
|
||||
bool anyService = mServices > 0;
|
||||
bool isCompanion = !MWWorld::Class::get(mPtr).getScript(mPtr).empty()
|
||||
&& mPtr.getRefData().getLocals().getIntVar(MWWorld::Class::get(mPtr).getScript(mPtr), "companion");
|
||||
|
||||
bool anyService = mServices > 0 || isCompanion || mPtr.getTypeName() == typeid(ESM::NPC).name();
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
@ -335,9 +344,13 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
|||
if (mServices & Service_Repair)
|
||||
mTopicsList->addItem(gmst.find("sRepair")->getString());
|
||||
|
||||
if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name())
|
||||
if (isCompanion)
|
||||
mTopicsList->addItem(gmst.find("sCompanionShare")->getString());
|
||||
|
||||
if (anyService)
|
||||
mTopicsList->addSeparator();
|
||||
|
||||
|
||||
for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); ++it)
|
||||
{
|
||||
mTopicsList->addItem(*it);
|
||||
|
|
|
@ -234,7 +234,8 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
|||
mDragAndDrop->mDraggedWidget = 0;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setDragDrop(false);
|
||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems();
|
||||
mDragAndDrop->mDraggedFrom->drawItems();
|
||||
mDragAndDrop->mDraggedFrom->notifyItemDragged(object, -mDragAndDrop->mDraggedCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -43,7 +43,6 @@ namespace MWGui
|
|||
getWidget(mAvatar, "Avatar");
|
||||
getWidget(mAvatarImage, "AvatarImage");
|
||||
getWidget(mEncumbranceBar, "EncumbranceBar");
|
||||
getWidget(mEncumbranceText, "EncumbranceBarT");
|
||||
getWidget(mFilterAll, "AllButton");
|
||||
getWidget(mFilterWeapon, "WeaponButton");
|
||||
getWidget(mFilterApparel, "ApparelButton");
|
||||
|
@ -240,9 +239,7 @@ namespace MWGui
|
|||
|
||||
float capacity = MWWorld::Class::get(player).getCapacity(player);
|
||||
float encumbrance = MWWorld::Class::get(player).getEncumbrance(player);
|
||||
mEncumbranceBar->setProgressRange(capacity);
|
||||
mEncumbranceBar->setProgressPosition(encumbrance);
|
||||
mEncumbranceText->setCaption( boost::lexical_cast<std::string>(int(encumbrance)) + "/" + boost::lexical_cast<std::string>(int(capacity)) );
|
||||
mEncumbranceBar->setValue(encumbrance, capacity);
|
||||
}
|
||||
|
||||
void InventoryWindow::onFrame()
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "container.hpp"
|
||||
#include "window_pinnable_base.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
@ -36,8 +37,7 @@ namespace MWGui
|
|||
MyGUI::Widget* mAvatar;
|
||||
MyGUI::ImageBox* mAvatarImage;
|
||||
MyGUI::TextBox* mArmorRating;
|
||||
MyGUI::ProgressBar* mEncumbranceBar;
|
||||
MyGUI::TextBox* mEncumbranceText;
|
||||
Widgets::MWDynamicStat* mEncumbranceBar;
|
||||
|
||||
MyGUI::Widget* mLeftPane;
|
||||
MyGUI::Widget* mRightPane;
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace MWGui
|
|||
GM_Settings, // Settings window
|
||||
GM_Inventory, // Inventory mode
|
||||
GM_Container,
|
||||
GM_Companion,
|
||||
GM_MainMenu, // Main menu mode
|
||||
|
||||
GM_Console, // Console mode
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "merchantrepair.hpp"
|
||||
#include "repair.hpp"
|
||||
#include "soulgemdialog.hpp"
|
||||
#include "companionwindow.hpp"
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
|
@ -96,6 +97,7 @@ WindowManager::WindowManager(
|
|||
, mMerchantRepair(NULL)
|
||||
, mRepair(NULL)
|
||||
, mSoulgemDialog(NULL)
|
||||
, mCompanionWindow(NULL)
|
||||
, mPlayerName()
|
||||
, mPlayerRaceId()
|
||||
, mPlayerAttributes()
|
||||
|
@ -189,6 +191,7 @@ WindowManager::WindowManager(
|
|||
mMerchantRepair = new MerchantRepair(*this);
|
||||
mRepair = new Repair(*this);
|
||||
mSoulgemDialog = new SoulgemDialog(mMessageBoxManager);
|
||||
mCompanionWindow = new CompanionWindow(*this, mDragAndDrop, mMessageBoxManager);
|
||||
|
||||
mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this);
|
||||
mLoadingScreen->onResChange (w,h);
|
||||
|
@ -317,6 +320,7 @@ void WindowManager::updateVisible()
|
|||
mTrainingWindow->setVisible(false);
|
||||
mMerchantRepair->setVisible(false);
|
||||
mRepair->setVisible(false);
|
||||
mCompanionWindow->setVisible(false);
|
||||
|
||||
mHud->setVisible(mHudEnabled);
|
||||
|
||||
|
@ -417,6 +421,10 @@ void WindowManager::updateVisible()
|
|||
mContainerWindow->setVisible(true);
|
||||
mInventoryWindow->setVisible(true);
|
||||
break;
|
||||
case GM_Companion:
|
||||
mCompanionWindow->setVisible(true);
|
||||
mInventoryWindow->setVisible(true);
|
||||
break;
|
||||
case GM_Dialogue:
|
||||
mDialogueWindow->setVisible(true);
|
||||
break;
|
||||
|
@ -676,6 +684,7 @@ void WindowManager::onFrame (float frameDuration)
|
|||
mSpellCreationDialog->checkReferenceAvailable();
|
||||
mEnchantingDialog->checkReferenceAvailable();
|
||||
mContainerWindow->checkReferenceAvailable();
|
||||
mCompanionWindow->checkReferenceAvailable();
|
||||
mConsole->checkReferenceAvailable();
|
||||
}
|
||||
|
||||
|
@ -1167,6 +1176,11 @@ const Translation::Storage& WindowManager::getTranslationDataStorage() const
|
|||
return mTranslationDataStorage;
|
||||
}
|
||||
|
||||
void WindowManager::showCompanionWindow(MWWorld::Ptr actor)
|
||||
{
|
||||
mCompanionWindow->open(actor);
|
||||
}
|
||||
|
||||
void WindowManager::changePointer(const std::string &name)
|
||||
{
|
||||
mCursor->onCursorChange(name);
|
||||
|
|
|
@ -77,6 +77,7 @@ namespace MWGui
|
|||
class MerchantRepair;
|
||||
class Repair;
|
||||
class SoulgemDialog;
|
||||
class CompanionWindow;
|
||||
|
||||
class WindowManager : public MWBase::WindowManager
|
||||
{
|
||||
|
@ -229,6 +230,7 @@ namespace MWGui
|
|||
virtual bool getPlayerSleeping();
|
||||
virtual void wakeUpPlayer();
|
||||
|
||||
virtual void showCompanionWindow(MWWorld::Ptr actor);
|
||||
virtual void startSpellMaking(MWWorld::Ptr actor);
|
||||
virtual void startEnchanting(MWWorld::Ptr actor);
|
||||
virtual void startSelfEnchanting(MWWorld::Ptr soulgem);
|
||||
|
@ -279,6 +281,7 @@ namespace MWGui
|
|||
MerchantRepair* mMerchantRepair;
|
||||
SoulgemDialog* mSoulgemDialog;
|
||||
Repair* mRepair;
|
||||
CompanionWindow* mCompanionWindow;
|
||||
|
||||
Translation::Storage& mTranslationDataStorage;
|
||||
Cursor* mCursor;
|
||||
|
|
|
@ -21,8 +21,16 @@
|
|||
#include "../mwbase/soundmanager.hpp"
|
||||
|
||||
MWMechanics::NpcStats::NpcStats()
|
||||
: mMovementFlags (0), mDrawState (DrawState_Nothing), mBounty (0)
|
||||
, mLevelProgress(0), mDisposition(0), mVampire (0), mReputation(0), mWerewolf (false), mWerewolfKills (0)
|
||||
: mMovementFlags (0)
|
||||
, mDrawState (DrawState_Nothing)
|
||||
, mBounty (0)
|
||||
, mLevelProgress(0)
|
||||
, mDisposition(0)
|
||||
, mVampire (0)
|
||||
, mReputation(0)
|
||||
, mWerewolf (false)
|
||||
, mWerewolfKills (0)
|
||||
, mProfit(0)
|
||||
{
|
||||
mSkillIncreases.resize (ESM::Attribute::Length);
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
|
@ -354,3 +362,13 @@ int MWMechanics::NpcStats::getWerewolfKills() const
|
|||
{
|
||||
return mWerewolfKills;
|
||||
}
|
||||
|
||||
int MWMechanics::NpcStats::getProfit() const
|
||||
{
|
||||
return mProfit;
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::modifyProfit(int diff)
|
||||
{
|
||||
mProfit += diff;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace MWMechanics
|
|||
int mReputation;
|
||||
bool mWerewolf;
|
||||
int mWerewolfKills;
|
||||
int mProfit;
|
||||
|
||||
int mLevelProgress; // 0-10
|
||||
|
||||
|
@ -64,6 +65,10 @@ namespace MWMechanics
|
|||
|
||||
NpcStats();
|
||||
|
||||
/// for mercenary companions. starts out as 0, and changes when items are added or removed through the UI.
|
||||
int getProfit() const;
|
||||
void modifyProfit(int diff);
|
||||
|
||||
DrawState_ getDrawState() const;
|
||||
|
||||
void setDrawState (DrawState_ state);
|
||||
|
|
|
@ -15,6 +15,30 @@ namespace MWScript
|
|||
mFloats.clear();
|
||||
mFloats.resize (script.mData.mNumFloats, 0);
|
||||
}
|
||||
|
||||
int Locals::getIntVar(const std::string &script, const std::string &var)
|
||||
{
|
||||
Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||
int index = locals.getIndex(var);
|
||||
char type = locals.getType(var);
|
||||
if(index != -1)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case 's':
|
||||
return mShorts.at (index);
|
||||
|
||||
case 'l':
|
||||
return mLongs.at (index);
|
||||
|
||||
case 'f':
|
||||
return mFloats.at (index);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Locals::setVarByInt(const std::string& script, const std::string& var, int val)
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace MWScript
|
|||
|
||||
void configure (const ESM::Script& script);
|
||||
bool setVarByInt(const std::string& script, const std::string& var, int val);
|
||||
int getIntVar (const std::string& script, const std::string& var); ///< if var does not exist, returns 0
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ namespace MWScript
|
|||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "exeution of script " << name << " failed." << std::endl;
|
||||
std::cerr << "execution of script " << name << " failed." << std::endl;
|
||||
|
||||
if (mVerbose)
|
||||
std::cerr << "(" << e.what() << ")" << std::endl;
|
||||
|
|
|
@ -80,6 +80,7 @@ set(MYGUI_FILES
|
|||
openmw_persuasion_dialog.layout
|
||||
openmw_merchantrepair.layout
|
||||
openmw_repair.layout
|
||||
openmw_companion_window.layout
|
||||
smallbars.png
|
||||
DejaVuLGCSansMono.ttf
|
||||
markers.png
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<MyGUI type="Layout">
|
||||
<Widget type="Window" skin="MW_Window" layer="Windows" position="900 500 600 300" name="_Main">
|
||||
<Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 600 300" name="_Main">
|
||||
|
||||
<!-- Items -->
|
||||
<Widget type="Widget" skin="MW_Box" position="5 5 575 225" name="box" align="Left Top Stretch">
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
<Widget type="Widget" skin="" position="0 0 224 223" align="Left Top" name="LeftPane">
|
||||
|
||||
<!-- Player encumbrance -->
|
||||
<Widget type="ProgressBar" skin="MW_Progress_Blue" position="8 8 212 24" name="EncumbranceBar" align="Left Top HStretch">
|
||||
<Widget type="TextBox" skin="ProgressText" position="0 0 212 24" align="Center Stretch" name="EncumbranceBarT"/>
|
||||
<Widget type="MWDynamicStat" skin="MW_ChargeBar_Blue" position="8 8 212 24" name="EncumbranceBar" align="Left Top HStretch">
|
||||
</Widget>
|
||||
|
||||
<!-- Avatar -->
|
||||
|
|
|
@ -158,6 +158,11 @@
|
|||
<Child type="TextBox" skin="SandTextC" offset = "0 0 204 18" align = "ALIGN_RIGHT ALIGN_TOP ALIGN_STRETCH" name = "BarText" />
|
||||
</Skin>
|
||||
|
||||
<Skin name = "MW_ChargeBar_Blue" size = "204 18">
|
||||
<Child type="ProgressBar" skin="MW_Progress_Blue" offset = "0 0 204 18" align = "ALIGN_RIGHT ALIGN_TOP ALIGN_STRETCH" name = "Bar" />
|
||||
<Child type="TextBox" skin="SandTextC" offset = "0 0 204 18" align = "ALIGN_RIGHT ALIGN_TOP ALIGN_STRETCH" name = "BarText" />
|
||||
</Skin>
|
||||
|
||||
<Skin name = "MW_DynamicStat_Red" size = "204 18">
|
||||
<Child type="TextBox" skin="SandText" offset = "0 0 100 18" align = "ALIGN_LEFT ALIGN_TOP" name = "Text" />
|
||||
<Child type="ProgressBar" skin="MW_Progress_Red" offset = "74 0 130 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "Bar" />
|
||||
|
|
Loading…
Reference in a new issue