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/IconManager.cpp

356 lines
10 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 "IconManager.h"
#include <AzFramework/API/AtomActiveInterface.h>
#include <AzCore/Interface/Interface.h>
// AzToolsFramework
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
// Editor
#include "Settings.h"
#include "Util/Image.h"
#include "Util/ImageUtil.h"
#define HELPER_MATERIAL "Objects/Helper"
namespace
{
// Object names in this array must correspond to EObject enumeration.
const char* g_ObjectNames[eStatObject_COUNT] =
{
"Objects/Arrow.cgf",
"Objects/Axis.cgf",
"Objects/Sphere.cgf",
"Objects/Anchor.cgf",
"Objects/entrypoint.cgf",
"Objects/hidepoint.cgf",
"Objects/hidepoint_sec.cgf",
"Objects/reinforcement_point.cgf",
};
const char* g_IconNames[eIcon_COUNT] =
{
"Icons/ScaleWarning.png",
"Icons/RotationWarning.png",
};
};
//////////////////////////////////////////////////////////////////////////
CIconManager::CIconManager()
{
ZeroStruct(m_icons);
ZeroStruct(m_objects);
}
//////////////////////////////////////////////////////////////////////////
CIconManager::~CIconManager()
{
}
//////////////////////////////////////////////////////////////////////////
void CIconManager::Init()
{
}
//////////////////////////////////////////////////////////////////////////
void CIconManager::Done()
{
Reset();
}
//////////////////////////////////////////////////////////////////////////
void CIconManager::Reset()
{
I3DEngine* pEngine = GetIEditor()->Get3DEngine();
// Do not unload objects. but clears them.
int i;
for (i = 0; i < sizeof(m_objects) / sizeof(m_objects[0]); i++)
{
if (m_objects[i] && pEngine)
{
m_objects[i]->Release();
}
m_objects[i] = 0;
}
for (i = 0; i < eIcon_COUNT; i++)
{
m_icons[i] = 0;
}
// Free icon bitmaps.
for (IconsMap::iterator it = m_iconBitmapsMap.begin(); it != m_iconBitmapsMap.end(); ++it)
{
delete it->second;
}
m_iconBitmapsMap.clear();
}
//////////////////////////////////////////////////////////////////////////
int CIconManager::GetIconTexture(const char* iconName)
{
int id = 0;
if (m_textures.Find(iconName, id))
{
return id;
}
if ((!iconName) || (iconName[0] == 0))
{
return 0;
}
if (AZ::Interface<AzFramework::AtomActiveInterface>::Get())
{
ITexture* texture = GetIEditor()->GetRenderer() ? GetIEditor()->GetRenderer()->EF_LoadTexture(iconName) : nullptr;
if (texture)
{
id = texture->GetTextureID();
m_textures[iconName] = id;
}
}
else
{
QString ext = Path::GetExt(iconName);
QString actualName = iconName;
char iconPath[AZ_MAX_PATH_LEN] = { 0 };
gEnv->pFileIO->ResolvePath(actualName.toUtf8().data(), iconPath, AZ_MAX_PATH_LEN);
// if we can't find it at the resolved path, try the devroot if necessary:
if (!gEnv->pFileIO->Exists(iconPath))
{
if (iconName[0] != '@') // it has no specified alias
{
if (QString::compare(ext, "dds", Qt::CaseInsensitive) != 0) // if its a DDS, it comes out of processed files in @assets@, and assets is assumed by default (legacy renderer)
{
// check for a source file
AZStd::string iconFullPath;
bool pathFound = false;
using AssetSysReqBus = AzToolsFramework::AssetSystemRequestBus;
AssetSysReqBus::BroadcastResult(pathFound, &AssetSysReqBus::Events::GetFullSourcePathFromRelativeProductPath, iconName, iconFullPath);
if (pathFound)
{
azstrncpy(iconPath, AZ_MAX_PATH_LEN, iconFullPath.c_str(), iconFullPath.length() + 1);
}
}
}
}
CImageEx image;
// Load icon.
if (CImageUtil::LoadImage(iconPath, image))
{
IRenderer* pRenderer(GetIEditor()->GetRenderer());
if (pRenderer->GetRenderType() != eRT_DX11)
{
image.SwapRedAndBlue();
}
if (QString::compare(ext, "bmp", Qt::CaseInsensitive) == 0 || QString::compare(ext, "jpg", Qt::CaseInsensitive) == 0)
{
int sz = image.GetWidth() * image.GetHeight();
uint8* buf = (uint8*)image.GetData();
for (int i = 0; i < sz; i++)
{
uint32 alpha = max(max(buf[i * 4], buf[i * 4 + 1]), buf[i * 4 + 2]);
alpha *= 2;
buf[i * 4 + 3] = (alpha > 255) ? 255 : alpha;
}
}
id = pRenderer->DownLoadToVideoMemory((unsigned char*)image.GetData(), image.GetWidth(), image.GetHeight(), eTF_R8G8B8A8, eTF_R8G8B8A8, 0, 0, 0);
m_textures[iconName] = id;
}
}
return id;
}
//////////////////////////////////////////////////////////////////////////
int CIconManager::GetIconTexture(EIcon icon)
{
assert(icon >= 0 && icon < eIcon_COUNT);
if (m_icons[icon])
{
return m_icons[icon];
}
m_icons[icon] = GetIconTexture(g_IconNames[icon]);
return m_icons[icon];
}
//////////////////////////////////////////////////////////////////////////
_smart_ptr<IMaterial> CIconManager::GetHelperMaterial()
{
if (!m_pHelperMtl)
{
m_pHelperMtl = GetIEditor()->Get3DEngine()->GetMaterialManager()->LoadMaterial(HELPER_MATERIAL);
}
return m_pHelperMtl;
};
//////////////////////////////////////////////////////////////////////////
IStatObj* CIconManager::GetObject(EStatObject object)
{
assert(object >= 0 && object < eStatObject_COUNT);
if (m_objects[object])
{
return m_objects[object];
}
// Try to load this object.
m_objects[object] = GetIEditor()->Get3DEngine()->LoadStatObjUnsafeManualRef(g_ObjectNames[object], NULL, NULL, false);
if (!m_objects[object])
{
CLogFile::FormatLine("Error: Load Failed: %s", g_ObjectNames[object]);
}
m_objects[object]->AddRef();
if (GetHelperMaterial())
{
m_objects[object]->SetMaterial(GetHelperMaterial());
}
return m_objects[object];
}
//////////////////////////////////////////////////////////////////////////
QImage* CIconManager::GetIconBitmap(const char* filename, bool& bHaveAlpha, uint32 effects /*=0*/)
{
QImage* pBitmap = 0;
QString iconFilename = filename;
if (Path::GetPath(iconFilename).isEmpty())
{
QString iconsPath;
if (!gSettings.searchPaths[EDITOR_PATH_UI_ICONS].empty())
{
iconsPath = gSettings.searchPaths[EDITOR_PATH_UI_ICONS][0];
}
iconFilename = Path::Make(iconsPath, iconFilename);
}
if (Path::GetExt(iconFilename).isEmpty())
{
// By default add .bmp extension to the filename without extension.
pBitmap = GetIconBitmap((iconFilename + ".png").toUtf8().data(), bHaveAlpha);
if (!pBitmap)
{
pBitmap = GetIconBitmap((iconFilename + ".bmp").toUtf8().data(), bHaveAlpha);
}
return pBitmap;
}
BOOL bAlphaBitmap = FALSE;
QPixmap pm(iconFilename);
bAlphaBitmap = pm.hasAlpha();
bHaveAlpha = (bAlphaBitmap == TRUE);
if (!pm.isNull())
{
pBitmap = new QImage;
*pBitmap = pm.toImage();
m_iconBitmapsMap[filename] = pBitmap;
// apply image effects
if (bAlphaBitmap)
{
const DWORD dataSize = pm.width() * pm.height() * 4;
BYTE* pImage = pBitmap->bits();
if (effects & eIconEffect_ColorEnabled)
{
for (DWORD i = 0; i < dataSize; i += 4)
{
pImage[i + 0] = (BYTE)((DWORD)pImage[i + 0] * 109 / 255);
pImage[i + 1] = (BYTE)((DWORD)pImage[i + 1] * 97 / 255);
pImage[i + 2] = (BYTE)((DWORD)pImage[i + 2] * 89 / 255);
}
}
if (effects & eIconEffect_ColorDisabled)
{
for (DWORD i = 0; i < dataSize; i += 4)
{
pImage[i + 0] = (BYTE)((DWORD)pImage[i + 0] * 168 / 255);
pImage[i + 1] = (BYTE)((DWORD)pImage[i + 1] * 164 / 255);
pImage[i + 2] = (BYTE)((DWORD)pImage[i + 2] * 162 / 255);
}
}
if (effects & eIconEffect_Dim)
{
for (DWORD i = 0; i < dataSize; i += 4)
{
pImage[i + 0] /= 2;
pImage[i + 1] /= 2;
pImage[i + 2] /= 2;
}
}
if (effects & eIconEffect_HalfAlpha)
{
for (DWORD i = 0; i < dataSize; i += 4)
{
pImage[i + 3] /= 2;
}
}
if (effects & eIconEffect_TintGreen)
{
for (DWORD i = 0; i < dataSize; i += 4)
{
pImage[i + 0] /= 2;
pImage[i + 2] /= 2;
}
}
if (effects & eIconEffect_TintRed)
{
for (DWORD i = 0; i < dataSize; i += 4)
{
pImage[i + 0] /= 2;
pImage[i + 1] /= 2;
}
}
if (effects & eIconEffect_TintYellow)
{
for (DWORD i = 0; i < dataSize; i += 4)
{
pImage[i + 0] /= 2;
}
}
// alpha premultiply
for (DWORD i = 0; i < dataSize; i += 4)
{
pImage[i + 0] = ((DWORD)pImage[i + 0] * (DWORD)pImage[i + 3]) / 255;
pImage[i + 1] = ((DWORD)pImage[i + 1] * (DWORD)pImage[i + 3]) / 255;
pImage[i + 2] = ((DWORD)pImage[i + 2] * (DWORD)pImage[i + 3]) / 255;
}
}
return pBitmap;
}
return NULL;
}