Merge branch 'master' into preview
@ -1,93 +0,0 @@
|
||||
Copyright (c) 2010, 2011 Georg Duffner (http://www.georgduffner.at)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
@ -1,98 +1,663 @@
|
||||
|
||||
#include "dialoguesubview.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QSize>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QSpinBox>
|
||||
#include <QLineEdit>
|
||||
#include <QEvent>
|
||||
#include <QDataWidgetMapper>
|
||||
#include <QCheckBox>
|
||||
#include <QLineEdit>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QComboBox>
|
||||
#include <QScrollArea>
|
||||
#include <QPushButton>
|
||||
#include <QToolButton>
|
||||
|
||||
#include "../../model/world/columnbase.hpp"
|
||||
#include "../../model/world/idtable.hpp"
|
||||
#include "../../model/world/columns.hpp"
|
||||
#include "../../model/world/record.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
#include "../../model/doc/document.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
|
||||
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
|
||||
bool createAndDelete)
|
||||
: SubView (id)
|
||||
#include "recordstatusdelegate.hpp"
|
||||
#include "util.hpp"
|
||||
#include "tablebottombox.hpp"
|
||||
/*
|
||||
==============================NotEditableSubDelegate==========================================
|
||||
*/
|
||||
CSVWorld::NotEditableSubDelegate::NotEditableSubDelegate(const CSMWorld::IdTable* table, QObject * parent) :
|
||||
QAbstractItemDelegate(parent),
|
||||
mTable(table)
|
||||
{}
|
||||
|
||||
void CSVWorld::NotEditableSubDelegate::setEditorData (QLabel* editor, const QModelIndex& index) const
|
||||
{
|
||||
QVariant v = index.data(Qt::EditRole);
|
||||
if (!v.isValid())
|
||||
{
|
||||
v = index.data(Qt::DisplayRole);
|
||||
if (!v.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (QVariant::String == v.type())
|
||||
{
|
||||
editor->setText(v.toString());
|
||||
} else //else we are facing enums
|
||||
{
|
||||
int data = v.toInt();
|
||||
std::vector<std::string> enumNames (CSMWorld::Columns::getEnums (static_cast<CSMWorld::Columns::ColumnId> (mTable->getColumnId (index.column()))));
|
||||
editor->setText(QString::fromUtf8(enumNames.at(data).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::NotEditableSubDelegate::setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
|
||||
{
|
||||
//not editable widgets will not save model data
|
||||
}
|
||||
|
||||
void CSVWorld::NotEditableSubDelegate::paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
//does nothing
|
||||
}
|
||||
|
||||
QSize CSVWorld::NotEditableSubDelegate::sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
return QSize();
|
||||
}
|
||||
|
||||
QWidget* CSVWorld::NotEditableSubDelegate::createEditor (QWidget *parent,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index,
|
||||
CSMWorld::ColumnBase::Display display) const
|
||||
{
|
||||
return new QLabel(parent);
|
||||
}
|
||||
|
||||
/*
|
||||
==============================DialogueDelegateDispatcherProxy==========================================
|
||||
*/
|
||||
CSVWorld::DialogueDelegateDispatcherProxy::refWrapper::refWrapper(const QModelIndex& index) :
|
||||
mIndex(index)
|
||||
{}
|
||||
|
||||
CSVWorld::DialogueDelegateDispatcherProxy::DialogueDelegateDispatcherProxy(QWidget* editor, CSMWorld::ColumnBase::Display display) :
|
||||
mEditor(editor),
|
||||
mDisplay(display),
|
||||
mIndexWrapper(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueDelegateDispatcherProxy::editorDataCommited()
|
||||
{
|
||||
if (mIndexWrapper.get())
|
||||
{
|
||||
emit editorDataCommited(mEditor, mIndexWrapper->mIndex, mDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueDelegateDispatcherProxy::setIndex(const QModelIndex& index)
|
||||
{
|
||||
mIndexWrapper.reset(new refWrapper(index));
|
||||
}
|
||||
|
||||
QWidget* CSVWorld::DialogueDelegateDispatcherProxy::getEditor() const
|
||||
{
|
||||
return mEditor;
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data, const CSMDoc::Document* document)
|
||||
{
|
||||
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(mEditor);
|
||||
{
|
||||
if (!lineEdit or !mIndexWrapper.get())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < data.size(); ++i)
|
||||
{
|
||||
if (mDisplay == CSMWorld::TableMimeData::convertEnums(data[i].getType()))
|
||||
{
|
||||
emit tableMimeDataDropped(mEditor, mIndexWrapper->mIndex, data[i], document);
|
||||
emit editorDataCommited(mEditor, mIndexWrapper->mIndex, mDisplay);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
==============================DialogueDelegateDispatcher==========================================
|
||||
*/
|
||||
|
||||
CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, QUndoStack& undoStack) :
|
||||
mParent(parent),
|
||||
mTable(table),
|
||||
mUndoStack(undoStack),
|
||||
mNotEditableDelegate(table, parent)
|
||||
{
|
||||
}
|
||||
|
||||
CSVWorld::CommandDelegate* CSVWorld::DialogueDelegateDispatcher::makeDelegate(CSMWorld::ColumnBase::Display display)
|
||||
{
|
||||
CommandDelegate *delegate = NULL;
|
||||
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
|
||||
if (delegateIt == mDelegates.end())
|
||||
{
|
||||
delegate = CommandDelegateFactoryCollection::get().makeDelegate (
|
||||
display, mUndoStack, mParent);
|
||||
mDelegates.insert(std::make_pair<int, CommandDelegate*>(display, delegate));
|
||||
} else
|
||||
{
|
||||
delegate = delegateIt->second;
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueDelegateDispatcher::editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display)
|
||||
{
|
||||
setModelData(editor, mTable, index, display);
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueDelegateDispatcher::setEditorData (QWidget* editor, const QModelIndex& index) const
|
||||
{
|
||||
QWidget *widget = new QWidget (this);
|
||||
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
|
||||
(mTable->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
|
||||
|
||||
QLabel* label = qobject_cast<QLabel*>(editor);
|
||||
if(label)
|
||||
{
|
||||
mNotEditableDelegate.setEditorData(label, index);
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
|
||||
if (delegateIt != mDelegates.end())
|
||||
{
|
||||
delegateIt->second->setEditorData(editor, index, true);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < mProxys.size(); ++i)
|
||||
{
|
||||
if (mProxys[i]->getEditor() == editor)
|
||||
{
|
||||
mProxys[i]->setIndex(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setWidget (widget);
|
||||
void CSVWorld::DialogueDelegateDispatcher::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
|
||||
{
|
||||
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
|
||||
if (delegateIt != mDelegates.end())
|
||||
{
|
||||
delegateIt->second->setModelData(editor, model, index);
|
||||
}
|
||||
}
|
||||
|
||||
QGridLayout *layout = new QGridLayout;
|
||||
void CSVWorld::DialogueDelegateDispatcher::paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
//Does nothing
|
||||
}
|
||||
|
||||
widget->setLayout (layout);
|
||||
QSize CSVWorld::DialogueDelegateDispatcher::sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
return QSize(); //silencing warning, otherwise does nothing
|
||||
}
|
||||
|
||||
QAbstractItemModel *model = document.getData().getTableModel (id);
|
||||
QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::Display display, const QModelIndex& index)
|
||||
{
|
||||
QVariant variant = index.data();
|
||||
if (!variant.isValid())
|
||||
{
|
||||
variant = index.data(Qt::DisplayRole);
|
||||
if (!variant.isValid())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int columns = model->columnCount();
|
||||
QWidget* editor = NULL;
|
||||
if (! (mTable->flags (index) & Qt::ItemIsEditable))
|
||||
{
|
||||
return mNotEditableDelegate.createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display);
|
||||
}
|
||||
|
||||
std::map<int, CommandDelegate*>::iterator delegateIt(mDelegates.find(display));
|
||||
if (delegateIt != mDelegates.end())
|
||||
{
|
||||
editor = delegateIt->second->createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display);
|
||||
DialogueDelegateDispatcherProxy* proxy = new DialogueDelegateDispatcherProxy(editor, display);
|
||||
|
||||
bool skip = false;
|
||||
if (qobject_cast<DropLineEdit*>(editor))
|
||||
{
|
||||
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
|
||||
connect(editor, SIGNAL(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*)),
|
||||
proxy, SLOT(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*)));
|
||||
connect(proxy, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
|
||||
this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
|
||||
skip = true;
|
||||
}
|
||||
if(!skip && qobject_cast<QCheckBox*>(editor))
|
||||
{
|
||||
connect(editor, SIGNAL(stateChanged(int)), proxy, SLOT(editorDataCommited()));
|
||||
skip = true;
|
||||
}
|
||||
if(!skip && qobject_cast<QPlainTextEdit*>(editor))
|
||||
{
|
||||
connect(editor, SIGNAL(textChanged()), proxy, SLOT(editorDataCommited()));
|
||||
skip = true;
|
||||
}
|
||||
if(!skip && qobject_cast<QComboBox*>(editor))
|
||||
{
|
||||
connect(editor, SIGNAL(currentIndexChanged (int)), proxy, SLOT(editorDataCommited()));
|
||||
skip = true;
|
||||
}
|
||||
if(!skip && qobject_cast<QAbstractSpinBox*>(editor))
|
||||
{
|
||||
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
|
||||
skip = true;
|
||||
}
|
||||
|
||||
connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)));
|
||||
mProxys.push_back(proxy); //deleted in the destructor
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher()
|
||||
{
|
||||
for (unsigned i = 0; i < mProxys.size(); ++i)
|
||||
{
|
||||
delete mProxys[i]; //unique_ptr could be handy
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================EditWidget=====================================================
|
||||
*/
|
||||
|
||||
CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, QUndoStack& undoStack, bool createAndDelete) :
|
||||
mDispatcher(this, table, undoStack),
|
||||
QScrollArea(parent),
|
||||
mWidgetMapper(NULL),
|
||||
mMainWidget(NULL),
|
||||
mUndoStack(undoStack),
|
||||
mTable(table)
|
||||
{
|
||||
remake (row);
|
||||
connect(&mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
|
||||
}
|
||||
|
||||
void CSVWorld::EditWidget::remake(int row)
|
||||
{
|
||||
if (mMainWidget)
|
||||
{
|
||||
delete mMainWidget;
|
||||
}
|
||||
mMainWidget = new QWidget (this);
|
||||
|
||||
//not sure if widget mapper can handle deleting the widgets that were mapped
|
||||
if (mWidgetMapper)
|
||||
{
|
||||
delete mWidgetMapper;
|
||||
}
|
||||
mWidgetMapper = new QDataWidgetMapper (this);
|
||||
mWidgetMapper->setModel (model);
|
||||
mWidgetMapper->setModel(mTable);
|
||||
mWidgetMapper->setItemDelegate(&mDispatcher);
|
||||
|
||||
QFrame* line = new QFrame(mMainWidget);
|
||||
line->setObjectName(QString::fromUtf8("line"));
|
||||
line->setGeometry(QRect(320, 150, 118, 3));
|
||||
line->setFrameShape(QFrame::HLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(mMainWidget);
|
||||
QGridLayout *unlockedLayout = new QGridLayout();
|
||||
QGridLayout *lockedLayout = new QGridLayout();
|
||||
mainLayout->addLayout(lockedLayout, 0);
|
||||
mainLayout->addWidget(line, 1);
|
||||
mainLayout->addLayout(unlockedLayout, 2);
|
||||
mainLayout->addStretch(1);
|
||||
|
||||
int unlocked = 0;
|
||||
int locked = 0;
|
||||
const int columns = mTable->columnCount();
|
||||
for (int i=0; i<columns; ++i)
|
||||
{
|
||||
int flags = model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
|
||||
int flags = mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
|
||||
|
||||
if (flags & CSMWorld::ColumnBase::Flag_Dialogue)
|
||||
{
|
||||
layout->addWidget (new QLabel (model->headerData (i, Qt::Horizontal).toString()), i, 0);
|
||||
|
||||
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
|
||||
(model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
|
||||
(mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
|
||||
|
||||
QWidget *widget = 0;
|
||||
mDispatcher.makeDelegate(display);
|
||||
QWidget *editor = mDispatcher.makeEditor(display, (mTable->index (row, i)));
|
||||
|
||||
if (model->flags (model->index (0, i)) & Qt::ItemIsEditable)
|
||||
if (editor)
|
||||
{
|
||||
switch (display)
|
||||
mWidgetMapper->addMapping (editor, i);
|
||||
QLabel* label = new QLabel(mTable->headerData (i, Qt::Horizontal).toString(), mMainWidget);
|
||||
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
editor->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||
if (! (mTable->flags (mTable->index (row, i)) & Qt::ItemIsEditable))
|
||||
{
|
||||
case CSMWorld::ColumnBase::Display_String:
|
||||
lockedLayout->addWidget (label, locked, 0);
|
||||
lockedLayout->addWidget (editor, locked, 1);
|
||||
++locked;
|
||||
} else
|
||||
{
|
||||
unlockedLayout->addWidget (label, unlocked, 0);
|
||||
unlockedLayout->addWidget (editor, unlocked, 1);
|
||||
++unlocked;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layout->addWidget (widget = new QLineEdit, i, 1);
|
||||
break;
|
||||
mWidgetMapper->setCurrentModelIndex(mTable->index(row, 0));
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Integer:
|
||||
this->setMinimumWidth(325); //TODO find better way to set the width or make it customizable
|
||||
this->setWidget(mMainWidget);
|
||||
this->setWidgetResizable(true);
|
||||
}
|
||||
|
||||
/// \todo configure widget properly (range)
|
||||
layout->addWidget (widget = new QSpinBox, i, 1);
|
||||
break;
|
||||
/*
|
||||
==============================DialogueSubView==========================================
|
||||
*/
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Float:
|
||||
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
|
||||
const CreatorFactoryBase& creatorFactory, bool sorting) :
|
||||
|
||||
/// \todo configure widget properly (range, format?)
|
||||
layout->addWidget (widget = new QDoubleSpinBox, i, 1);
|
||||
break;
|
||||
SubView (id),
|
||||
mEditWidget(0),
|
||||
mMainLayout(NULL),
|
||||
mUndoStack(document.getUndoStack()),
|
||||
mTable(dynamic_cast<CSMWorld::IdTable*>(document.getData().getTableModel(id))),
|
||||
mRow (-1),
|
||||
mLocked(false),
|
||||
mDocument(document)
|
||||
|
||||
default: break; // silence warnings for other times for now
|
||||
}
|
||||
{
|
||||
connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&)));
|
||||
mRow = mTable->getModelIndex (id.getId(), 0).row();
|
||||
QWidget *mainWidget = new QWidget(this);
|
||||
|
||||
QHBoxLayout *buttonsLayout = new QHBoxLayout;
|
||||
QToolButton* prevButton = new QToolButton(mainWidget);
|
||||
prevButton->setIcon(QIcon(":/go-previous.png"));
|
||||
QToolButton* nextButton = new QToolButton(mainWidget);
|
||||
nextButton->setIcon(QIcon(":/go-next.png"));
|
||||
buttonsLayout->addWidget(prevButton, 0);
|
||||
buttonsLayout->addWidget(nextButton, 1);
|
||||
buttonsLayout->addStretch(2);
|
||||
|
||||
QToolButton* cloneButton = new QToolButton(mainWidget);
|
||||
cloneButton->setIcon(QIcon(":/edit-clone.png"));
|
||||
QToolButton* addButton = new QToolButton(mainWidget);
|
||||
addButton->setIcon(QIcon(":/add.png"));
|
||||
QToolButton* deleteButton = new QToolButton(mainWidget);
|
||||
deleteButton->setIcon(QIcon(":/edit-delete.png"));
|
||||
QToolButton* revertButton = new QToolButton(mainWidget);
|
||||
revertButton->setIcon(QIcon(":/edit-undo.png"));
|
||||
|
||||
if (mTable->hasPreview())
|
||||
{
|
||||
QToolButton* previewButton = new QToolButton(mainWidget);
|
||||
previewButton->setIcon(QIcon(":/edit-preview.png"));
|
||||
buttonsLayout->addWidget(previewButton);
|
||||
connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview()));
|
||||
}
|
||||
|
||||
if (mTable->getViewing()!=CSMWorld::IdTable::Viewing_None)
|
||||
{
|
||||
QToolButton* viewButton = new QToolButton(mainWidget);
|
||||
viewButton->setIcon(QIcon(":/cell.png"));
|
||||
buttonsLayout->addWidget(viewButton);
|
||||
connect(viewButton, SIGNAL(clicked()), this, SLOT(viewRecord()));
|
||||
}
|
||||
|
||||
buttonsLayout->addWidget(cloneButton);
|
||||
buttonsLayout->addWidget(addButton);
|
||||
buttonsLayout->addWidget(deleteButton);
|
||||
buttonsLayout->addWidget(revertButton);
|
||||
|
||||
connect(nextButton, SIGNAL(clicked()), this, SLOT(nextId()));
|
||||
connect(prevButton, SIGNAL(clicked()), this, SLOT(prevId()));
|
||||
connect(cloneButton, SIGNAL(clicked()), this, SLOT(cloneRequest()));
|
||||
connect(revertButton, SIGNAL(clicked()), this, SLOT(revertRecord()));
|
||||
connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteRecord()));
|
||||
|
||||
mMainLayout = new QVBoxLayout(mainWidget);
|
||||
|
||||
mEditWidget = new EditWidget(mainWidget, mRow, mTable, mUndoStack, false);
|
||||
connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
|
||||
this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
|
||||
|
||||
mMainLayout->addWidget(mEditWidget);
|
||||
mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
mMainLayout->addWidget (mBottom =
|
||||
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this));
|
||||
|
||||
mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
|
||||
connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&)));
|
||||
connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest()));
|
||||
|
||||
if(!mBottom->canCreateAndDelete())
|
||||
{
|
||||
cloneButton->setDisabled(true);
|
||||
addButton->setDisabled(true);
|
||||
deleteButton->setDisabled(true);
|
||||
}
|
||||
|
||||
dataChanged(mTable->index(mRow, 0));
|
||||
mMainLayout->addLayout(buttonsLayout);
|
||||
setWidget(mainWidget);
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::prevId()
|
||||
{
|
||||
int newRow = mRow - 1;
|
||||
if (newRow < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (newRow >= 0)
|
||||
{
|
||||
QModelIndex newIndex(mTable->index(newRow, 0));
|
||||
|
||||
if (!newIndex.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (newRow, 1)).toInt());
|
||||
if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased))
|
||||
{
|
||||
mEditWidget->remake(newRow);
|
||||
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (mTable->data (mTable->index (newRow, 2)).toInt()),
|
||||
mTable->data (mTable->index (newRow, 0)).toString().toStdString()));
|
||||
mRow = newRow;
|
||||
mEditWidget->setDisabled(mLocked);
|
||||
return;
|
||||
}
|
||||
--newRow;
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::nextId()
|
||||
{
|
||||
int newRow = mRow + 1;
|
||||
|
||||
if (newRow >= mTable->rowCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (newRow < mTable->rowCount())
|
||||
{
|
||||
QModelIndex newIndex(mTable->index(newRow, 0));
|
||||
|
||||
if (!newIndex.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (newRow, 1)).toInt());
|
||||
if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased))
|
||||
{
|
||||
mEditWidget->remake(newRow);
|
||||
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (mTable->data (mTable->index (newRow, 2)).toInt()),
|
||||
mTable->data (mTable->index (newRow, 0)).toString().toStdString()));
|
||||
mRow = newRow;
|
||||
mEditWidget->setDisabled(mLocked);
|
||||
return;
|
||||
}
|
||||
++newRow;
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::setEditLock (bool locked)
|
||||
{
|
||||
mLocked = locked;
|
||||
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
|
||||
if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)
|
||||
{
|
||||
mEditWidget->setDisabled(true);
|
||||
} else
|
||||
{
|
||||
mEditWidget->setDisabled(mLocked);
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index)
|
||||
{
|
||||
if (index.row() == mRow)
|
||||
{
|
||||
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
|
||||
if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)
|
||||
{
|
||||
mEditWidget->setDisabled(true);
|
||||
} else
|
||||
{
|
||||
mEditWidget->setDisabled(mLocked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::tableMimeDataDropped(QWidget* editor,
|
||||
const QModelIndex& index,
|
||||
const CSMWorld::UniversalId& id,
|
||||
const CSMDoc::Document* document)
|
||||
{
|
||||
if (document == &mDocument)
|
||||
{
|
||||
qobject_cast<DropLineEdit*>(editor)->setText(id.getId().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::revertRecord()
|
||||
{
|
||||
int rows = mTable->rowCount();
|
||||
if (!mLocked && mTable->columnCount() > 0 && mRow < mTable->rowCount() )
|
||||
{
|
||||
CSMWorld::RecordBase::State state =
|
||||
static_cast<CSMWorld::RecordBase::State> (mTable->data (mTable->index (mRow, 1)).toInt());
|
||||
|
||||
if (state!=CSMWorld::RecordBase::State_BaseOnly)
|
||||
{
|
||||
mUndoStack.push(new CSMWorld::RevertCommand(*mTable, mTable->data(mTable->index (mRow, 0)).toString().toStdString()));
|
||||
}
|
||||
if (rows != mTable->rowCount())
|
||||
{
|
||||
if (mTable->rowCount() == 0)
|
||||
{
|
||||
mEditWidget->setDisabled(true); //closing the editor is other option
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (mRow >= mTable->rowCount())
|
||||
{
|
||||
switch (display)
|
||||
{
|
||||
case CSMWorld::ColumnBase::Display_String:
|
||||
case CSMWorld::ColumnBase::Display_Integer:
|
||||
case CSMWorld::ColumnBase::Display_Float:
|
||||
prevId();
|
||||
} else {
|
||||
dataChanged(mTable->index(mRow, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layout->addWidget (widget = new QLabel, i, 1);
|
||||
break;
|
||||
void CSVWorld::DialogueSubView::deleteRecord()
|
||||
{
|
||||
int rows = mTable->rowCount();
|
||||
|
||||
default: break; // silence warnings for other times for now
|
||||
}
|
||||
}
|
||||
//easier than disabling the button
|
||||
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
|
||||
bool deledetedOrErased = (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased);
|
||||
|
||||
if (widget)
|
||||
mWidgetMapper->addMapping (widget, i);
|
||||
if (!mLocked &&
|
||||
mTable->columnCount() > 0 &&
|
||||
!deledetedOrErased &&
|
||||
mRow < rows &&
|
||||
mBottom->canCreateAndDelete())
|
||||
{
|
||||
mUndoStack.push(new CSMWorld::DeleteCommand(*mTable, mTable->data(mTable->index (mRow, 0)).toString().toStdString()));
|
||||
if (rows != mTable->rowCount())
|
||||
{
|
||||
if (mTable->rowCount() == 0)
|
||||
{
|
||||
mEditWidget->setDisabled(true); //closing the editor is other option
|
||||
return;
|
||||
}
|
||||
if (mRow >= mTable->rowCount())
|
||||
{
|
||||
prevId();
|
||||
} else {
|
||||
dataChanged(mTable->index(mRow, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mWidgetMapper->setCurrentModelIndex (
|
||||
dynamic_cast<CSMWorld::IdTable&> (*model).getModelIndex (id.getId(), 0));
|
||||
void CSVWorld::DialogueSubView::requestFocus (const std::string& id)
|
||||
{
|
||||
mRow = mTable->getModelIndex (id, 0).row();
|
||||
mEditWidget->remake(mRow);
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::setEditLock (bool locked)
|
||||
void CSVWorld::DialogueSubView::cloneRequest ()
|
||||
{
|
||||
mBottom->cloneRequest(mTable->data(mTable->index (mRow, 0)).toString().toStdString(),
|
||||
static_cast<CSMWorld::UniversalId::Type>(mTable->data(mTable->index(mRow, 2)).toInt()));
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::showPreview ()
|
||||
{
|
||||
if (mTable->hasPreview() && mRow < mTable->rowCount())
|
||||
{
|
||||
emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mTable->data(mTable->index (mRow, 0)).toString().toStdString()), "");
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::viewRecord()
|
||||
{
|
||||
if (mRow < mTable->rowCount())
|
||||
{
|
||||
std::pair<CSMWorld::UniversalId, std::string> params = mTable->view (mRow);
|
||||
|
||||
if (params.first.getType()!=CSMWorld::UniversalId::Type_None)
|
||||
emit focusId (params.first, params.second);
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
#include "weaponanimation.hpp"
|
||||
|
||||
#include <OgreEntity.h>
|
||||
#include <OgreBone.h>
|
||||
#include <OgreSceneNode.h>
|
||||
#include <OgreSkeletonInstance.h>
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
#include "animation.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
float WeaponAnimationTime::getValue() const
|
||||
{
|
||||
if (mWeaponGroup.empty())
|
||||
return 0;
|
||||
float current = mAnimation->getCurrentTime(mWeaponGroup);
|
||||
if (current == -1)
|
||||
return 0;
|
||||
return current - mStartTime;
|
||||
}
|
||||
|
||||
void WeaponAnimationTime::setGroup(const std::string &group)
|
||||
{
|
||||
mWeaponGroup = group;
|
||||
mStartTime = mAnimation->getStartTime(mWeaponGroup);
|
||||
}
|
||||
|
||||
void WeaponAnimationTime::updateStartTime()
|
||||
{
|
||||
setGroup(mWeaponGroup);
|
||||
}
|
||||
|
||||
void WeaponAnimation::attachArrow(MWWorld::Ptr actor)
|
||||
{
|
||||
MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor);
|
||||
MWWorld::ContainerStoreIterator weaponSlot = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
if (weaponSlot != inv.end() && weaponSlot->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanThrown)
|
||||
showWeapon(true);
|
||||
else
|
||||
{
|
||||
NifOgre::ObjectScenePtr weapon = getWeapon();
|
||||
|
||||
MWWorld::ContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition);
|
||||
if (ammo == inv.end())
|
||||
return;
|
||||
std::string model = ammo->getClass().getModel(*ammo);
|
||||
|
||||
mAmmunition = NifOgre::Loader::createObjects(weapon->mSkelBase, "ArrowBone", weapon->mSkelBase->getParentSceneNode(), model);
|
||||
configureAddedObject(mAmmunition, *ammo, MWWorld::InventoryStore::Slot_Ammunition);
|
||||
}
|
||||
}
|
||||
|
||||
void WeaponAnimation::releaseArrow(MWWorld::Ptr actor)
|
||||
{
|
||||
MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor);
|
||||
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
if (weapon == inv.end())
|
||||
return;
|
||||
|
||||
// The orientation of the launched projectile. Always the same as the actor orientation, even if the ArrowBone's orientation dictates otherwise.
|
||||
Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
|
||||
Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X);
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
// Reduce fatigue
|
||||
// somewhat of a guess, but using the weapon weight makes sense
|
||||
const float fFatigueAttackBase = gmst.find("fFatigueAttackBase")->getFloat();
|
||||
const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat();
|
||||
const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat();
|
||||
MWMechanics::CreatureStats& attackerStats = actor.getClass().getCreatureStats(actor);
|
||||
MWMechanics::DynamicStat<float> fatigue = attackerStats.getFatigue();
|
||||
const float normalizedEncumbrance = actor.getClass().getEncumbrance(actor) / actor.getClass().getCapacity(actor);
|
||||
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
|
||||
if (!weapon->isEmpty())
|
||||
fatigueLoss += weapon->getClass().getWeight(*weapon) * attackerStats.getAttackStrength() * fWeaponFatigueMult;
|
||||
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
|
||||
attackerStats.setFatigue(fatigue);
|
||||
|
||||
if (weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanThrown)
|
||||
{
|
||||
// Thrown weapons get detached now
|
||||
NifOgre::ObjectScenePtr objects = getWeapon();
|
||||
|
||||
Ogre::Vector3 launchPos(0,0,0);
|
||||
if (objects->mSkelBase)
|
||||
{
|
||||
launchPos = objects->mSkelBase->getParentNode()->_getDerivedPosition();
|
||||
}
|
||||
else if (objects->mEntities.size())
|
||||
{
|
||||
objects->mEntities[0]->getParentNode()->needUpdate(true);
|
||||
launchPos = objects->mEntities[0]->getParentNode()->_getDerivedPosition();
|
||||
}
|
||||
|
||||
float fThrownWeaponMinSpeed = gmst.find("fThrownWeaponMinSpeed")->getFloat();
|
||||
float fThrownWeaponMaxSpeed = gmst.find("fThrownWeaponMaxSpeed")->getFloat();
|
||||
float speed = fThrownWeaponMinSpeed + (fThrownWeaponMaxSpeed - fThrownWeaponMinSpeed) *
|
||||
actor.getClass().getCreatureStats(actor).getAttackStrength();
|
||||
|
||||
MWBase::Environment::get().getWorld()->launchProjectile(actor, *weapon, launchPos, orient, *weapon, speed);
|
||||
|
||||
showWeapon(false);
|
||||
|
||||
inv.remove(*weapon, 1, actor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// With bows and crossbows only the used arrow/bolt gets detached
|
||||
MWWorld::ContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition);
|
||||
if (ammo == inv.end())
|
||||
return;
|
||||
|
||||
Ogre::Vector3 launchPos(0,0,0);
|
||||
if (mAmmunition->mSkelBase)
|
||||
{
|
||||
launchPos = mAmmunition->mSkelBase->getParentNode()->_getDerivedPosition();
|
||||
}
|
||||
else if (mAmmunition->mEntities.size())
|
||||
{
|
||||
mAmmunition->mEntities[0]->getParentNode()->needUpdate(true);
|
||||
launchPos = mAmmunition->mEntities[0]->getParentNode()->_getDerivedPosition();
|
||||
}
|
||||
|
||||
float fProjectileMinSpeed = gmst.find("fProjectileMinSpeed")->getFloat();
|
||||
float fProjectileMaxSpeed = gmst.find("fProjectileMaxSpeed")->getFloat();
|
||||
float speed = fProjectileMinSpeed + (fProjectileMaxSpeed - fProjectileMinSpeed) * actor.getClass().getCreatureStats(actor).getAttackStrength();
|
||||
|
||||
MWBase::Environment::get().getWorld()->launchProjectile(actor, *ammo, launchPos, orient, *weapon, speed);
|
||||
|
||||
inv.remove(*ammo, 1, actor);
|
||||
mAmmunition.setNull();
|
||||
}
|
||||
}
|
||||
|
||||
void WeaponAnimation::pitchSkeleton(float xrot, Ogre::SkeletonInstance* skel)
|
||||
{
|
||||
if (mPitchFactor == 0)
|
||||
return;
|
||||
|
||||
float pitch = xrot * mPitchFactor;
|
||||
Ogre::Node *node = skel->getBone("Bip01 Spine2");
|
||||
node->pitch(Ogre::Radian(-pitch/2), Ogre::Node::TS_WORLD);
|
||||
node = skel->getBone("Bip01 Spine1");
|
||||
node->pitch(Ogre::Radian(-pitch/2), Ogre::Node::TS_WORLD);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
#ifndef OPENMW_MWRENDER_WEAPONANIMATION_H
|
||||
#define OPENMW_MWRENDER_WEAPONANIMATION_H
|
||||
|
||||
#include <OgreController.h>
|
||||
|
||||
#include <components/nifogre/ogrenifloader.hpp>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
class Animation;
|
||||
|
||||
class WeaponAnimationTime : public Ogre::ControllerValue<Ogre::Real>
|
||||
{
|
||||
private:
|
||||
Animation* mAnimation;
|
||||
std::string mWeaponGroup;
|
||||
float mStartTime;
|
||||
public:
|
||||
WeaponAnimationTime(Animation* animation) : mAnimation(animation), mStartTime(0) {}
|
||||
void setGroup(const std::string& group);
|
||||
void updateStartTime();
|
||||
|
||||
virtual Ogre::Real getValue() const;
|
||||
virtual void setValue(Ogre::Real value)
|
||||
{ }
|
||||
};
|
||||
|
||||
/// Handles attach & release of projectiles for ranged weapons
|
||||
class WeaponAnimation
|
||||
{
|
||||
public:
|
||||
WeaponAnimation() : mPitchFactor(0) {}
|
||||
|
||||
virtual void attachArrow(MWWorld::Ptr actor);
|
||||
virtual void releaseArrow(MWWorld::Ptr actor);
|
||||
|
||||
protected:
|
||||
NifOgre::ObjectScenePtr mAmmunition;
|
||||
|
||||
virtual NifOgre::ObjectScenePtr getWeapon() = 0;
|
||||
virtual void showWeapon(bool show) = 0;
|
||||
virtual void configureAddedObject(NifOgre::ObjectScenePtr object, MWWorld::Ptr ptr, int slot) = 0;
|
||||
|
||||
/// A relative factor (0-1) that decides if and how much the skeleton should be pitched
|
||||
/// to indicate the facing orientation of the character, for ranged weapon aiming.
|
||||
float mPitchFactor;
|
||||
|
||||
void pitchSkeleton(float xrot, Ogre::SkeletonInstance* skel);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
After Width: | Height: | Size: 520 B |
After Width: | Height: | Size: 472 B |
After Width: | Height: | Size: 680 B |
After Width: | Height: | Size: 525 B |
After Width: | Height: | Size: 650 B |
After Width: | Height: | Size: 676 B |
After Width: | Height: | Size: 655 B |