You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Sandbox/Editor/Material/MaterialImageListCtrl.cpp

835 lines
24 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorDefs.h"
#include "MaterialImageListCtrl.h"
// Qt
#include <QMenu>
// Editor
#include "Material.h"
#include "MaterialManager.h"
#include "MaterialPreviewModelView.h"
#include "MaterialBrowser.h"
#include "Util/Image.h"
#define ME_BG_TEXTURE "Materials/Stripes.dds"
#define MATERIAL_EDITOR_SPHERE_MODEL_FILE "Objects/MtlSphere.cgf"
#define MATERIAL_EDITOR_SPHERE_CAMERA_RADIUS 1.6f
#define MATERIAL_EDITOR_SPHERE_CAMERA_FROM_DIRECTION Vec3(0.1f, -1.0f, -0.1f)
#define MATERIAL_EDITOR_BOX_MODEL_FILE "Objects/MtlBox.cgf"
#define MATERIAL_EDITOR_BOX_CAMERA_RADIUS 2.0f
#define MATERIAL_EDITOR_BOX_CAMERA_FROM_DIRECTION Vec3(0.75f, -0.75f, -0.5f)
#define MATERIAL_EDITOR_TEAPOT_MODEL_FILE "Objects/MtlTeapot.cgf"
#define MATERIAL_EDITOR_TEAPOT_CAMERA_RADIUS 1.6f
#define MATERIAL_EDITOR_TEAPOT_CAMERA_FROM_DIRECTION Vec3(0.1f, -0.75f, -0.25f)
#define MATERIAL_EDITOR_PLANE_MODEL_FILE "Objects/MtlPlane.cgf"
#define MATERIAL_EDITOR_PLANE_CAMERA_RADIUS 1.6f
#define MATERIAL_EDITOR_PLANE_CAMERA_FROM_DIRECTION Vec3(-0.5f, 0.5f, -0.5f)
#define MATERIAL_EDITOR_SWATCH_MODEL_FILE "Objects/MtlSwatch.cgf"
#define MATERIAL_EDITOR_SWATCH_CAMERA_RADIUS 1.0f
#define MATERIAL_EDITOR_SWATCH_CAMERA_FROM_DIRECTION Vec3(0.0f, 0.0f, -1.0f)
_smart_ptr<CMaterial> ResolveTerrainLayerPreviewMaterial(_smart_ptr<CMaterial> material, _smart_ptr<CMaterial> pMatPreview)
{
if (!QString::compare(material->GetShaderName(), "Terrain.Layer"))
{
XmlNodeRef node = XmlHelpers::CreateXmlNode("Material");
CBaseLibraryItem::SerializeContext ctx(node, false);
material->Serialize(ctx);
if (!pMatPreview)
{
int flags = 0;
if (node->getAttr("MtlFlags", flags))
{
flags |= MTL_FLAG_UIMATERIAL;
node->setAttr("MtlFlags", flags);
}
pMatPreview = GetIEditor()->GetMaterialManager()->CreateMaterial("_NewPreview_", node);
}
else
{
CBaseLibraryItem::SerializeContext ctx2(node, true);
pMatPreview->Serialize(ctx2);
}
pMatPreview->SetShaderName("Illum");
pMatPreview->Update();
return pMatPreview;
}
else
{
return material;
}
}
struct QMaterialImageListModel::Item
{
QImage image;
void* pUserData;
QPoint position;
QSize size;
_smart_ptr<CMaterial> pMaterial;
QStringList vVisibleTextures;
};
//////////////////////////////////////////////////////////////////////////
void CMaterialImageListCtrl::OnCreate()
{
// m_largePreviewCtrl is used to draw the 3D preview for the selected material
m_largePreviewCtrl.reset(new MaterialPreviewModelView(this));
m_largePreviewCtrl->hide();
// m_renderCtrl is used to draw all the sub-materials
m_renderCtrl.reset(new MaterialPreviewModelView(this, false /* disable idle updates since this is only used to create the preview list images */));
m_renderCtrl->UnSetFlag(CPreviewModelView::PreviewModelViewFlag::SHOW_GRID);
m_renderCtrl->UnSetFlag(CPreviewModelView::PreviewModelViewFlag::SHOW_GRID_AXIS);
if (gEnv->pSystem)
{
gEnv->pSystem->GetISystemEventDispatcher()->RegisterListener(this);
}
// m_resizeTimer is used to stall updateGeometries being called via resizeEvents until RESIZE_TIMEOUT ms after resizing
// This prevents an Editor freeze caused by constant resizing of the Material Editor when viewing
// a high sub-material count material (LY-58389)
m_resizeTimer = new QTimer(this);
connect(m_resizeTimer, &QTimer::timeout, this, &CMaterialImageListCtrl::ResizeTimeout);
}
void CMaterialImageListCtrl::resizeEvent([[maybe_unused]] QResizeEvent* event)
{
m_resizeTimer->stop();
m_resizeTimer->start(RESIZE_TIMEOUT);
}
void CMaterialImageListCtrl::ResizeTimeout()
{
m_resizeTimer->stop();
updateGeometries();
}
//////////////////////////////////////////////////////////////////////////
void CMaterialImageListCtrl::OnDestroy()
{
if (gEnv->pSystem)
{
gEnv->pSystem->GetISystemEventDispatcher()->RemoveListener(this);
}
}
//////////////////////////////////////////////////////////////////////////
CMaterialImageListCtrl::CMaterialImageListCtrl(QWidget* parent)
: CImageListCtrl(parent)
{
OnCreate();
}
//////////////////////////////////////////////////////////////////////////
CMaterialImageListCtrl::~CMaterialImageListCtrl()
{
OnDestroy();
}
//////////////////////////////////////////////////////////////////////////
QModelIndex QMaterialImageListModel::AddMaterial(CMaterial* pMaterial, void* pUserData)
{
Item* pItem = new Item;
pItem->pMaterial = pMaterial;
pItem->pUserData = pUserData;
pMaterial->GetAnyTextureFilenames(pItem->vVisibleTextures);
const int row = m_items.count();
beginInsertRows(QModelIndex(), row, row);
m_items.insert(row, pItem);
endInsertRows();
return index(row, 0);
}
//////////////////////////////////////////////////////////////////////////
void QMaterialImageListModel::SetMaterial(int nItemIndex, CMaterial* pMaterial, void* pUserData)
{
assert(nItemIndex <= (int)m_items.size());
Item* pItem = m_items.at(nItemIndex);
pItem->vVisibleTextures.clear();
pItem->pMaterial = pMaterial;
pItem->pUserData = pUserData;
pMaterial->GetAnyTextureFilenames(pItem->vVisibleTextures);
pItem->image = QImage();
QModelIndex idx = index(nItemIndex, 0);
emit dataChanged(idx, idx, QVector<int>() << Qt::DisplayRole << Qt::DecorationRole);
}
//////////////////////////////////////////////////////////////////////////
QModelIndex QMaterialImageListModel::FindMaterial(CMaterial* const pMaterial)
{
for (int i = 0; i < m_items.count(); i++)
{
Item* item = m_items[i];
if (pMaterial == item->pMaterial)
{
return index(i, 0);
}
}
return QModelIndex();
}
//////////////////////////////////////////////////////////////////////////
void CMaterialImageListCtrl::SelectMaterial(CMaterial* pMaterial)
{
// Force the material to load the highest resolution textures
pMaterial->GetMatInfo()->DisableTextureStreaming();
selectionModel()->clearSelection();
QMaterialImageListModel* materialModel = qobject_cast<QMaterialImageListModel*>(model());
Q_ASSERT(materialModel);
QModelIndex index = materialModel->FindMaterial(pMaterial);
if (index.isValid())
{
selectionModel()->select(index, QItemSelectionModel::SelectCurrent);
m_largePreviewMaterial = pMaterial;
}
else
{
// If the parent material was selected, set the first sub-material as the large preview's material so it has something to render
if (pMaterial->GetSubMaterialCount() > 0)
{
m_largePreviewMaterial = pMaterial->GetSubMaterial(0);
}
}
GenerateAllImages();
}
//////////////////////////////////////////////////////////////////////////
void QMaterialImageListModel::InvalidateMaterial(CMaterial* pMaterial)
{
QModelIndex idx = FindMaterial(pMaterial);
Item* pItem = ItemFromIndex(idx);
if ((pItem) && (m_renderCtrl))
{
if (pMaterial)
{
// Ensure the full resolution textures are loaded for the material editor
pMaterial->GetMatInfo()->DisableTextureStreaming();
}
pItem->vVisibleTextures.clear();
pMaterial->GetAnyTextureFilenames(pItem->vVisibleTextures);
pItem->image = QImage();
GenerateImage(pItem);
emit dataChanged(idx, idx, QVector<int>() << Qt::DecorationRole);
}
}
//////////////////////////////////////////////////////////////////////////
void QMaterialImageListModel::DeleteAllItems()
{
if (m_renderCtrl)
{
m_renderCtrl->SetMaterial(nullptr);
}
beginResetModel();
qDeleteAll(m_items);
m_items.clear();
endResetModel();
}
//////////////////////////////////////////////////////////////////////////
void QMaterialImageListModel::GenerateImage(Item* pItem)
{
// Make a bitmap from image.
Q_ASSERT(pItem);
if (!m_renderCtrl || !pItem->size.isValid())
{
return;
}
if (pItem->image.size() == pItem->size)
{
return;
}
Item* pMtlItem = pItem;
CImageEx image;
bool bPreview = false;
if (pMtlItem->pMaterial)
{
if (!(pMtlItem->pMaterial->GetFlags() & MTL_FLAG_NOPREVIEW))
{
if (!m_renderCtrl->GetStaticModel())
{
AZ_Warning("Material Editor", false, "Preview renderer has no object loaded!");
return;
}
// keep m_renderCtrl off screen, but visible
m_renderCtrl->setGeometry(QRect(-QPoint(pItem->size.width(), pItem->size.height()), pItem->size));
_smart_ptr<CMaterial> matPreview = ResolveTerrainLayerPreviewMaterial(pItem->pMaterial, m_pMatPreview);
m_renderCtrl->SetMaterial(matPreview->GetMatInfo());
m_renderCtrl->GetImageOffscreen(image, pMtlItem->size);
}
bPreview = true;
}
if (!bPreview)
{
image.Allocate(pItem->size.width(), pItem->size.height());
image.Clear();
}
pItem->image = QImage(image.GetWidth(), image.GetHeight(), QImage::Format_RGB32);
memcpy(pItem->image.bits(), image.GetData(), image.GetSize());
}
#define MENU_USE_DEFAULT 1
#define MENU_USE_BOX 2
#define MENU_USE_PLANE 3
#define MENU_USE_SPHERE 4
#define MENU_USE_TEAPOT 5
#define MENU_BG_BLACK 6
#define MENU_BG_GRAY 7
#define MENU_BG_WHITE 8
#define MENU_BG_TEXTURE 9
#define MENU_USE_BACKLIGHT 10
//////////////////////////////////////////////////////////////////////////
void CMaterialImageListCtrl::contextMenuEvent(QContextMenuEvent* event)
{
QAction* action;
QMenu menu;
action = menu.addAction(tr("Use Default Object"));
action->setData(ModelDefault);
action->setCheckable(true);
action->setChecked(m_modelType == ModelType::Default);
action = menu.addAction(tr("Use Plane"));
action->setData(ModelPlane);
action->setCheckable(true);
action->setChecked(m_modelType == ModelType::Plane);
action = menu.addAction(tr("Use Box"));
action->setData(ModelBox);
action->setCheckable(true);
action->setChecked(m_modelType == ModelType::Box);
action = menu.addAction(tr("Use Sphere"));
action->setData(ModelSphere);
action->setCheckable(true);
action->setChecked(m_modelType == ModelType::Sphere);
action = menu.addAction(tr("Use Teapot"));
action->setData(ModelTeapot);
action->setCheckable(true);
action->setChecked(m_modelType == ModelType::Teapot);
menu.addSeparator();
// If there is a currently selected material
if (m_materialBrowserWidget && m_largePreviewMaterial)
{
// Add context menu actions that are common to both the material browser and the preview swatches
m_materialBrowserWidget->AddContextMenuActionsSingleSelection(menu, m_largePreviewMaterial);
}
action = menu.exec(mapToGlobal(event->pos()));
if (!action)
{
return;
}
int cmd = action->data().toInt();
switch (cmd)
{
case ModelDefault:
m_modelType = ModelType::Default;
LoadModel();
break;
case ModelPlane:
m_modelType = ModelType::Plane;
LoadModel();
break;
case ModelBox:
m_modelType = ModelType::Box;
LoadModel();
break;
case ModelSphere:
m_modelType = ModelType::Sphere;
LoadModel();
break;
case ModelTeapot:
m_modelType = ModelType::Teapot;
LoadModel();
break;
default:
// If there is a currently selected material
if (m_materialBrowserWidget && m_largePreviewMaterial)
{
// Handle context menu actions that are common to both the material browser and the preview swatches
m_materialBrowserWidget->OnContextMenuAction(cmd, m_largePreviewMaterial);
}
break;
}
QMaterialImageListModel* materialModel =
qobject_cast<QMaterialImageListModel*>(model());
Q_ASSERT(materialModel);
materialModel->GenerateImages();
update();
}
//////////////////////////////////////////////////////////////////////////
void CMaterialImageListCtrl::LoadModel()
{
switch (m_modelType)
{
case ModelType::Default:
case ModelType::Sphere:
m_largePreviewCtrl->LoadModelFile(MATERIAL_EDITOR_SPHERE_MODEL_FILE);
m_largePreviewCtrl->SetCameraLookAt(MATERIAL_EDITOR_SPHERE_CAMERA_RADIUS, MATERIAL_EDITOR_SPHERE_CAMERA_FROM_DIRECTION);
break;
case ModelType::Box:
m_largePreviewCtrl->LoadModelFile(MATERIAL_EDITOR_BOX_MODEL_FILE);
m_largePreviewCtrl->SetCameraLookAt(MATERIAL_EDITOR_BOX_CAMERA_RADIUS, MATERIAL_EDITOR_BOX_CAMERA_FROM_DIRECTION);
break;
case ModelType::Teapot:
m_largePreviewCtrl->LoadModelFile(MATERIAL_EDITOR_TEAPOT_MODEL_FILE);
m_largePreviewCtrl->SetCameraLookAt(MATERIAL_EDITOR_TEAPOT_CAMERA_RADIUS, MATERIAL_EDITOR_TEAPOT_CAMERA_FROM_DIRECTION);
break;
case ModelType::Plane:
m_largePreviewCtrl->LoadModelFile(MATERIAL_EDITOR_PLANE_MODEL_FILE);
m_largePreviewCtrl->SetCameraLookAt(MATERIAL_EDITOR_PLANE_CAMERA_RADIUS, MATERIAL_EDITOR_PLANE_CAMERA_FROM_DIRECTION);
break;
}
GenerateAllImages();
}
//////////////////////////////////////////////////////////////////////////
void CMaterialImageListCtrl::updateGeometries()
{
ClearItemGeometries();
m_updatingGeometries = true;
if (!model())
{
return;
}
const int rowCount = model()->rowCount();
if (!rowCount)
{
m_largePreviewCtrl->hide();
m_largePreviewMaterial = nullptr;
return;
}
m_largePreviewCtrl->setParent(nullptr);
m_largePreviewCtrl->setParent(this);
m_largePreviewCtrl->show();
const int bwidth = BorderSize().width();
const int bheight = BorderSize().height();
m_largePreviewCtrl->move(bwidth, bheight);
QRect rc = viewport()->contentsRect()
.adjusted(bwidth, bheight, -bwidth, -bheight);
int cy = rc.height();
// Preview item is big.
if (model()->rowCount() > 0)
{
QSize size(cy, rc.height());
m_largePreviewCtrl->SetSize(size);
m_largePreviewCtrl->resize(size);
rc.setLeft(rc.left() + cy + bwidth * 2);
m_largePreviewCtrl->show();
}
int cx = rc.width() - bwidth;
int itemSize = cy;
// Adjust all other bitmaps as tight as possible.
int numItems = model()->rowCount();
int div = 0;
for (div = 1; div < 1000 && itemSize > 0; div++)
{
int nX = cx / (itemSize + 2);
if (nX >= numItems)
{
break;
}
if (nX > 0)
{
int nY = numItems / nX + 1;
if (nY * (itemSize + 2) < cy)
{
//itemSize = itemSize -= 2;
break;
}
}
itemSize = itemSize -= 2;
}
if (itemSize < 0)
{
itemSize = 0;
}
QPoint pos(rc.topLeft());
const QSize size(itemSize, itemSize);
m_renderCtrl->SetSize(size);
for (int row = 0; row < numItems; ++row)
{
QModelIndex index = model()->index(row, 0);
SetItemGeometry(index, QRect(pos, size));
model()->setData(index, pos, QMaterialImageListModel::PositionRole);
model()->setData(index, size, Qt::SizeHintRole);
pos.rx() += itemSize + 2;
if (pos.rx() + itemSize >= rc.right())
{
pos.rx() = rc.left();
pos.ry() += itemSize + 2;
}
}
m_updatingGeometries = false;
update();
}
//////////////////////////////////////////////////////////////////////////
void CMaterialImageListCtrl::setModel(QAbstractItemModel* model)
{
QMaterialImageListModel* materialModel = qobject_cast<QMaterialImageListModel*>(model);
if (materialModel)
{
materialModel->SetPreviewModelCtrl(m_renderCtrl.data());
}
CImageListCtrl::setModel(model);
auto delegate = qobject_cast<QImageListDelegate*>(itemDelegate());
// in case the delegate misses a pixmap we can generate it (done only once not at every painting)
connect(delegate, SIGNAL(invalidPixmapGenerated(const QModelIndex&)), materialModel, SLOT(GenerateImage(const QModelIndex&)));
connect(model, &QAbstractItemModel::dataChanged, this, &CMaterialImageListCtrl::ModelDataChanged);
}
void CMaterialImageListCtrl::ModelDataChanged(const QModelIndex& index)
{
// Prevent the hundreads of resize calls done in a row
// to trigger a new image computation that we already have
if (m_updatingGeometries)
{
return;
}
GenerateImage(index);
}
//////////////////////////////////////////////////////////////////////////
void CMaterialImageListCtrl::showEvent(QShowEvent* event)
{
CImageListCtrl::showEvent(event);
if (!m_largePreviewCtrl->GetStaticModel())
{
LoadModel();
}
if (!m_renderCtrl->GetStaticModel())
{
m_renderCtrl->LoadModelFile(MATERIAL_EDITOR_SWATCH_MODEL_FILE);
m_renderCtrl->SetCameraLookAt(MATERIAL_EDITOR_SWATCH_CAMERA_RADIUS, MATERIAL_EDITOR_SWATCH_CAMERA_FROM_DIRECTION);
}
}
//////////////////////////////////////////////////////////////////////////
void CMaterialImageListCtrl::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, [[maybe_unused]] UINT_PTR lparam)
{
switch (event)
{
// Toggle visibility of this control whenever the main editor window has a change of focus.
case ESYSTEM_EVENT_CHANGE_FOCUS:
{
setAttribute(Qt::WA_WState_Visible, (wparam != 0));
break;
}
}
;
}
void CMaterialImageListCtrl::UpdateLargePreview()
{
if (m_largePreviewMaterial)
{
m_largePreviewCtrl->SetMaterial(ResolveTerrainLayerPreviewMaterial(m_largePreviewMaterial, m_tempTerrainMaterial)->GetMatInfo());
m_largePreviewCtrl->show();
m_largePreviewCtrl->update();
}
}
void CMaterialImageListCtrl::GenerateImage(const QModelIndex& index)
{
QMaterialImageListModel* materialModel =
qobject_cast<QMaterialImageListModel*>(model());
Q_ASSERT(materialModel);
if (m_largePreviewMaterial == materialModel->MaterialFromIndex(index))
{
UpdateLargePreview();
}
materialModel->SetPreviewModelCtrl(m_renderCtrl.data());
materialModel->GenerateImage(index);
update();
}
void CMaterialImageListCtrl::GenerateAllImages()
{
QMaterialImageListModel* materialModel =
qobject_cast<QMaterialImageListModel*>(model());
Q_ASSERT(materialModel);
UpdateLargePreview();
materialModel->SetPreviewModelCtrl(m_renderCtrl.data());
materialModel->GenerateImages();
update();
}
//////////////////////////////////////////////////////////////////////////
QMaterialImageListModel::QMaterialImageListModel(QObject* parent)
: QAbstractListModel(parent)
, m_renderCtrl(nullptr)
{
BusConnect(AZ_CRC("dds", 0x780234cb));
}
//////////////////////////////////////////////////////////////////////////
QMaterialImageListModel::~QMaterialImageListModel()
{
BusDisconnect();
qDeleteAll(m_items);
}
//////////////////////////////////////////////////////////////////////////
MaterialPreviewModelView* QMaterialImageListModel::PreviewModelCtrl() const
{
return m_renderCtrl;
}
//////////////////////////////////////////////////////////////////////////
void QMaterialImageListModel::SetPreviewModelCtrl(MaterialPreviewModelView* ctrl)
{
if (m_renderCtrl)
{
disconnect(m_renderCtrl, &MaterialPreviewModelView::destroyed,
this, &QMaterialImageListModel::ClearPreviewModelCtrl);
}
m_renderCtrl = ctrl;
if (m_renderCtrl)
{
connect(m_renderCtrl, &MaterialPreviewModelView::destroyed,
this, &QMaterialImageListModel::ClearPreviewModelCtrl);
}
}
//////////////////////////////////////////////////////////////////////////
void QMaterialImageListModel::ClearPreviewModelCtrl()
{
m_renderCtrl = nullptr;
}
//////////////////////////////////////////////////////////////////////////
int QMaterialImageListModel::rowCount(const QModelIndex& parent) const
{
if (parent.isValid())
{
return 0;
}
return m_items.count();
}
//////////////////////////////////////////////////////////////////////////
QVariant QMaterialImageListModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
{
return QVariant();
}
Item* pItem = m_items.at(index.row());
Q_ASSERT(pItem);
switch (role)
{
case Qt::DisplayRole:
return pItem->pMaterial->GetShortName();
case Qt::DecorationRole:
return QPixmap::fromImage(pItem->image);
case PositionRole:
return pItem->position;
case Qt::SizeHintRole:
return pItem->size;
default:
break;
}
return QVariant();
}
//////////////////////////////////////////////////////////////////////////
bool QMaterialImageListModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!index.isValid())
{
return false;
}
Item* pItem = ItemFromIndex(index);
if (!pItem)
{
return false;
}
if (Qt::SizeHintRole == role)
{
pItem->size = value.toSize();
emit dataChanged(index, index, QVector<int>() << Qt::DecorationRole << Qt::SizeHintRole);
return true;
}
if (PositionRole == role)
{
pItem->position = value.toPoint();
}
return false;
}
//////////////////////////////////////////////////////////////////////////
Qt::ItemFlags QMaterialImageListModel::flags(const QModelIndex& index) const
{
return QAbstractListModel::flags(index);
}
//////////////////////////////////////////////////////////////////////////
CMaterial* QMaterialImageListModel::MaterialFromIndex(QModelIndex index) const
{
Item* pItem = ItemFromIndex(index);
if (!pItem)
{
return nullptr;
}
return pItem->pMaterial;
}
//////////////////////////////////////////////////////////////////////////
void* QMaterialImageListModel::UserDataFromIndex(QModelIndex index) const
{
Item* pItem = ItemFromIndex(index);
if (!pItem)
{
return nullptr;
}
return pItem->pUserData;
}
//////////////////////////////////////////////////////////////////////////
void QMaterialImageListModel::GenerateImages()
{
if ((!m_renderCtrl) || (m_items.isEmpty()))
{
return;
}
for (Item* materialImageListItem : m_items)
{
GenerateImage(materialImageListItem);
}
}
void QMaterialImageListModel::GenerateImage(const QModelIndex& index)
{
if ((!m_renderCtrl) || (m_items.isEmpty()))
{
return;
}
GenerateImage(ItemFromIndex(index));
}
//////////////////////////////////////////////////////////////////////////
QMaterialImageListModel::Item* QMaterialImageListModel::ItemFromIndex(QModelIndex index) const
{
if (!index.isValid())
{
return nullptr;
}
return m_items.at(index.row());
}
//////////////////////////////////////////////////////////////////////////
void QMaterialImageListModel::OnFileChanged(AZStd::string assetPath)
{
const int rowCount = m_items.count();
// update all previews who's texture(s) changed
for (int row = 0; row < rowCount; ++row)
{
Item* pItem = m_items.at(row);
QStringList::const_iterator textureIt = std::find(pItem->vVisibleTextures.begin(), pItem->vVisibleTextures.end(), assetPath.c_str());
if (textureIt != pItem->vVisibleTextures.end())
{
pItem->image = QImage();
QModelIndex idx = index(row, 0);
emit dataChanged(idx, idx, QVector<int>() << Qt::DecorationRole);
}
}
}
#include <Material/moc_MaterialImageListCtrl.cpp>