Merge branch 'main' into ly-as-sdk/LYN-2948
# Conflicts: # CMakeLists.txt # cmake/Platform/Common/Install_common.cmakemain
commit
03ae0195a3
@ -1,75 +0,0 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
#
|
||||
# This is a pytest module to test the in-Editor Python API from ViewPane.h
|
||||
#
|
||||
import pytest
|
||||
pytest.importorskip('ly_test_tools')
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.dirname(__file__))
|
||||
from hydra_utils import launch_test_case
|
||||
|
||||
|
||||
@pytest.mark.SUITE_sandbox
|
||||
@pytest.mark.parametrize('launcher_platform', ['windows_editor'])
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['auto_test'])
|
||||
class TestLegacyCryMaterialsCommandsAutomation(object):
|
||||
|
||||
def test_Legacy_CryMaterials(self, request, editor, level, launcher_platform):
|
||||
|
||||
unexpected_lines=[]
|
||||
expected_lines = [
|
||||
# "Material Settings/Shader updated correctly", # Disabled, SPEC-3590
|
||||
# "Material Settings/Surface Type updated correctly", # Disabled, SPEC-3590
|
||||
"Texture Maps/Diffuse/Tiling/IsTileU updated correctly",
|
||||
"Texture Maps/Diffuse/Tiling/TileU updated correctly",
|
||||
"Texture Maps/Diffuse/Rotator/Type updated correctly",
|
||||
"Texture Maps/Diffuse/Rotator/Amplitude updated correctly",
|
||||
"Texture Maps/Diffuse/Oscillator/AmplitudeU updated correctly",
|
||||
"Opacity Settings/Opacity updated correctly",
|
||||
"Opacity Settings/AlphaTest updated correctly",
|
||||
"Opacity Settings/Additive updated correctly",
|
||||
"Lighting Settings/Diffuse Color updated correctly",
|
||||
"Lighting Settings/Specular Color updated correctly",
|
||||
"Lighting Settings/Emissive Intensity updated correctly",
|
||||
"Lighting Settings/Emissive Color updated correctly",
|
||||
"Advanced/Allow layer activation updated correctly",
|
||||
"Advanced/2 Sided updated correctly",
|
||||
"Advanced/No Shadow updated correctly",
|
||||
"Advanced/Use Scattering updated correctly",
|
||||
"Advanced/Hide After Breaking updated correctly",
|
||||
"Advanced/Fog Volume Shading Quality High updated correctly",
|
||||
"Advanced/Blend Terrain Color updated correctly",
|
||||
"Advanced/Voxel Coverage updated correctly",
|
||||
"Advanced/Propagate Opacity Settings updated correctly",
|
||||
"Advanced/Propagate Lighting Settings updated correctly",
|
||||
"Advanced/Propagate Advanced Settings updated correctly",
|
||||
"Advanced/Propagate Texture Maps updated correctly",
|
||||
"Advanced/Propagate Shader Params updated correctly",
|
||||
"Advanced/Propagate Shader Generation updated correctly",
|
||||
"Advanced/Propagate Vertex Deformation updated correctly",
|
||||
# "Shader Params/Blend Factor updated correctly", # Disabled, SPEC-3590
|
||||
# "Shader Params/Indirect bounce color updated correctly", # Disabled, SPEC-3590
|
||||
"Vertex Deformation/Type updated correctly",
|
||||
"Vertex Deformation/Wave Length X updated correctly",
|
||||
"Vertex Deformation/Wave X/Level updated correctly",
|
||||
"Vertex Deformation/Wave X/Amplitude updated correctly",
|
||||
"Vertex Deformation/Wave X/Phase updated correctly",
|
||||
"Vertex Deformation/Wave X/Frequency updated correctly"
|
||||
]
|
||||
|
||||
test_case_file = os.path.join(os.path.dirname(__file__), 'CryMaterialsCommands_test_case.py')
|
||||
launch_test_case(editor, test_case_file, expected_lines, unexpected_lines)
|
||||
|
||||
@ -1,116 +0,0 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
# Tests the legacy Python API for CryMaterials while the Editor is running
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.material as material
|
||||
import azlmbr.math as math
|
||||
|
||||
materialName = 'materials/ter_layer_green'
|
||||
print(f'Starting CryMaterial test case using material {materialName}')
|
||||
|
||||
|
||||
def MaterialPropertyTest(property, value, doReset=True):
|
||||
try:
|
||||
# get old value and attempt to set new value
|
||||
oldValue = material.get_property(materialName, property)
|
||||
if oldValue == value:
|
||||
print(f'>>> `{property}` already set to {oldValue}')
|
||||
return
|
||||
material.set_property(materialName, property, value)
|
||||
|
||||
# test that the set new value worked
|
||||
newValue = material.get_property(materialName, property)
|
||||
if oldValue != newValue:
|
||||
print(f"{property} updated correctly")
|
||||
|
||||
# reset back to old value
|
||||
if doReset:
|
||||
material.set_property(materialName, property, oldValue)
|
||||
except:
|
||||
print(f'!!! hit an exception when setting `{property}` to {value}')
|
||||
|
||||
|
||||
color = math.Color()
|
||||
color.r = 255.0
|
||||
color.g = 128.0
|
||||
color.b = 64.0
|
||||
color.a = 0.0
|
||||
|
||||
# Material Settings
|
||||
# MaterialPropertyTest("Material Settings/Shader", "Geometrybeam") # Disabled, SPEC-3590
|
||||
# MaterialPropertyTest("Material Settings/Surface Type", "grass") # Disabled, SPEC-3590
|
||||
|
||||
# Texture Maps
|
||||
MaterialPropertyTest("Texture Maps/Diffuse/Tiling/IsTileU", False)
|
||||
MaterialPropertyTest("Texture Maps/Diffuse/Tiling/IsTileV", False)
|
||||
MaterialPropertyTest("Texture Maps/Diffuse/Tiling/TileU", 0.42)
|
||||
MaterialPropertyTest("Texture Maps/Diffuse/Rotator/Type", 'Oscillated Rotation')
|
||||
MaterialPropertyTest("Texture Maps/Diffuse/Rotator/Amplitude", 42.0)
|
||||
MaterialPropertyTest("Texture Maps/Diffuse/Oscillator/TypeU", 'Fixed Moving')
|
||||
MaterialPropertyTest("Texture Maps/Diffuse/Oscillator/AmplitudeU", 42.0)
|
||||
|
||||
# Vertex Deformation
|
||||
MaterialPropertyTest("Vertex Deformation/Type", 'Sin Wave')
|
||||
MaterialPropertyTest("Vertex Deformation/Wave Length X", 42.0)
|
||||
MaterialPropertyTest("Vertex Deformation/Type", 'Perlin 3D')
|
||||
MaterialPropertyTest("Vertex Deformation/Noise Scale", math.Vector3(1.1, 2.2, 3.3))
|
||||
|
||||
# Opacity Settings
|
||||
MaterialPropertyTest("Opacity Settings/Opacity", 42)
|
||||
MaterialPropertyTest("Opacity Settings/AlphaTest", 2)
|
||||
MaterialPropertyTest("Opacity Settings/Additive", True)
|
||||
|
||||
# Lighting Settings
|
||||
MaterialPropertyTest("Lighting Settings/Diffuse Color", color)
|
||||
MaterialPropertyTest("Lighting Settings/Specular Color", color)
|
||||
MaterialPropertyTest("Lighting Settings/Emissive Intensity", 42.0)
|
||||
MaterialPropertyTest("Lighting Settings/Emissive Color", color)
|
||||
MaterialPropertyTest("Lighting Settings/Specular Level", 2.0)
|
||||
|
||||
# Advanced
|
||||
MaterialPropertyTest("Advanced/Allow layer activation", False)
|
||||
MaterialPropertyTest("Advanced/2 Sided", True)
|
||||
MaterialPropertyTest("Advanced/No Shadow", True)
|
||||
MaterialPropertyTest("Advanced/Use Scattering", True)
|
||||
MaterialPropertyTest("Advanced/Hide After Breaking", True)
|
||||
MaterialPropertyTest("Advanced/Fog Volume Shading Quality High", True)
|
||||
MaterialPropertyTest("Advanced/Blend Terrain Color", True)
|
||||
MaterialPropertyTest("Advanced/Voxel Coverage", 0.42)
|
||||
# --- MaterialPropertyTest("Advanced/Link to Material", "materials/ter_layer_blue") # Works, but clears on UI refresh
|
||||
MaterialPropertyTest("Advanced/Propagate Opacity Settings", True)
|
||||
MaterialPropertyTest("Advanced/Propagate Lighting Settings", True)
|
||||
MaterialPropertyTest("Advanced/Propagate Advanced Settings", True)
|
||||
MaterialPropertyTest("Advanced/Propagate Texture Maps", True)
|
||||
MaterialPropertyTest("Advanced/Propagate Shader Params", True)
|
||||
MaterialPropertyTest("Advanced/Propagate Shader Generation", True)
|
||||
MaterialPropertyTest("Advanced/Propagate Vertex Deformation", True)
|
||||
|
||||
# Shader parameters vary with each Shader, just testing a couple of them...
|
||||
# MaterialPropertyTest("Shader Params/Blend Factor", 7.0, False) # Disabled, SPEC-3590
|
||||
# MaterialPropertyTest("Shader Params/Indirect bounce color", color, False) # Disabled, SPEC-3590
|
||||
|
||||
### These values are reset to False when set. Left them here commented for reference.
|
||||
# MaterialPropertyTest("Shader Generation Params/Dust & Turbulence", True)
|
||||
# MaterialPropertyTest("Shader Generation Params/Receive Shadows", True)
|
||||
# MaterialPropertyTest("Shader Generation Params/UV Vignetting", True)
|
||||
|
||||
# Vertex Deformation
|
||||
MaterialPropertyTest("Vertex Deformation/Type", "Sin Wave")
|
||||
MaterialPropertyTest("Vertex Deformation/Wave Length X", 42.0)
|
||||
MaterialPropertyTest("Vertex Deformation/Wave X/Level", 42.0)
|
||||
MaterialPropertyTest("Vertex Deformation/Wave X/Amplitude", 42.0)
|
||||
MaterialPropertyTest("Vertex Deformation/Wave X/Phase", 42.0)
|
||||
MaterialPropertyTest("Vertex Deformation/Wave X/Frequency", 42.0)
|
||||
|
||||
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'ExitNoPrompt')
|
||||
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Data
|
||||
{
|
||||
struct AssetId;
|
||||
}
|
||||
}
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace MaterialBrowser
|
||||
{
|
||||
class MaterialBrowserRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
|
||||
// Only a single handler is allowed
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
|
||||
virtual bool HasRecord(const AZ::Data::AssetId& assetId) = 0;
|
||||
virtual bool IsMultiMaterial(const AZ::Data::AssetId& assetId) = 0;
|
||||
};
|
||||
|
||||
using MaterialBrowserRequestBus = AZ::EBus<MaterialBrowserRequests>;
|
||||
} // namespace MaterialBrowser
|
||||
} // namespace AzToolsFramework
|
||||
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <AzToolsFramework/MaterialBrowser/MaterialBrowserComponent.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Thumbnails/FolderThumbnail.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.h>
|
||||
#include <AzToolsFramework/MaterialBrowser/MaterialThumbnail.h>
|
||||
#include <AzToolsFramework/Thumbnails/SourceControlThumbnail.h>
|
||||
|
||||
#include <QApplication>
|
||||
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QBrush::d': class 'QScopedPointer<QBrushData,QBrushDataPointerDeleter>' needs to have dll-interface to be used by clients of class 'QBrush'
|
||||
#include <QStyle>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace MaterialBrowser
|
||||
{
|
||||
MaterialBrowserComponent::MaterialBrowserComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialBrowserComponent::Activate()
|
||||
{
|
||||
using namespace Thumbnailer;
|
||||
using namespace AssetBrowser;
|
||||
const char* contextName = "MaterialBrowser";
|
||||
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterContext, contextName);
|
||||
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(FolderThumbnailCache), contextName);
|
||||
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(SourceThumbnailCache), contextName);
|
||||
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(MaterialThumbnailCache), contextName);
|
||||
ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(SourceControlThumbnailCache), contextName);
|
||||
}
|
||||
|
||||
void MaterialBrowserComponent::Deactivate()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialBrowserComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<MaterialBrowserComponent, AZ::Component>();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialBrowserComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
required.push_back(AZ_CRC("ThumbnailerService", 0x65422b97));
|
||||
}
|
||||
} // namespace MaterialBrowser
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace MaterialBrowser
|
||||
{
|
||||
//! MaterialBrowserComponent allows initialization of MaterialBrowser systems, such as thumbnails
|
||||
class MaterialBrowserComponent
|
||||
: public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(MaterialBrowserComponent, "{121F3F3B-2412-490D-9E3E-C205C677F476}")
|
||||
|
||||
MaterialBrowserComponent();
|
||||
virtual ~MaterialBrowserComponent() = default;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Component
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||
};
|
||||
} // namespace MaterialBrowser
|
||||
} // namespace AzToolsFramework
|
||||
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/MaterialBrowser/MaterialThumbnail.h>
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace MaterialBrowser
|
||||
{
|
||||
static constexpr const char* SimpleMaterialIconPath = ":/MaterialBrowser/images/material_04.png";
|
||||
static constexpr const char* MultiMaterialIconPath = ":/MaterialBrowser/images/material_06.png";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaterialThumbnail
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MaterialThumbnail::MaterialThumbnail(Thumbnailer::SharedThumbnailKey key)
|
||||
: Thumbnail(key)
|
||||
{
|
||||
auto productKey = azrtti_cast<const AzToolsFramework::AssetBrowser::ProductThumbnailKey*>(m_key.data());
|
||||
AZ_Assert(productKey, "Incorrect key type, excpected ProductThumbnailKey");
|
||||
|
||||
bool multiMat = false;
|
||||
MaterialBrowserRequestBus::BroadcastResult(multiMat, &MaterialBrowserRequests::IsMultiMaterial, productKey->GetAssetId());
|
||||
|
||||
QString iconPath = multiMat ? MultiMaterialIconPath : SimpleMaterialIconPath;
|
||||
m_pixmap.load(iconPath);
|
||||
m_state = m_pixmap.isNull() ? State::Failed : State::Ready;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaterialThumbnailCache
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MaterialThumbnailCache::MaterialThumbnailCache()
|
||||
: ThumbnailCache<MaterialThumbnail, MaterialKeyHash, MaterialKeyEqual>() {}
|
||||
|
||||
MaterialThumbnailCache::~MaterialThumbnailCache() = default;
|
||||
|
||||
int MaterialThumbnailCache::GetPriority() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* MaterialThumbnailCache::GetProviderName() const
|
||||
{
|
||||
return ProviderName;
|
||||
}
|
||||
|
||||
bool MaterialThumbnailCache::IsSupportedThumbnail(Thumbnailer::SharedThumbnailKey key) const
|
||||
{
|
||||
return azrtti_istypeof<const AzToolsFramework::AssetBrowser::ProductThumbnailKey*>(key.data());
|
||||
}
|
||||
|
||||
} // namespace MaterialBrowser
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
#include "MaterialBrowser/moc_MaterialThumbnail.cpp"
|
||||
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Thumbnails/ProductThumbnail.h>
|
||||
#include <AzToolsFramework/MaterialBrowser/MaterialBrowserBus.h>
|
||||
#endif
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace MaterialBrowser
|
||||
{
|
||||
//! Material Browser uses only 2 thumbnails: simple and multimaterial
|
||||
class MaterialThumbnail
|
||||
: public Thumbnailer::Thumbnail
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MaterialThumbnail(Thumbnailer::SharedThumbnailKey key);
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
class MaterialKeyHash
|
||||
{
|
||||
public:
|
||||
size_t operator()(const Thumbnailer::SharedThumbnailKey& /*val*/) const
|
||||
{
|
||||
return 0; // there is only 2 thumbnails in this cache
|
||||
}
|
||||
};
|
||||
|
||||
class MaterialKeyEqual
|
||||
{
|
||||
public:
|
||||
bool operator()(const Thumbnailer::SharedThumbnailKey& val1, const Thumbnailer::SharedThumbnailKey& val2) const
|
||||
{
|
||||
auto productThumbnailKey1 = azrtti_cast<const AzToolsFramework::AssetBrowser::ProductThumbnailKey*>(val1.data());
|
||||
auto productThumbnailKey2 = azrtti_cast<const AzToolsFramework::AssetBrowser::ProductThumbnailKey*>(val2.data());
|
||||
if (!productThumbnailKey1 || !productThumbnailKey2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// check whether keys point to single or multimaterial asset type
|
||||
bool multiMat1 = false;
|
||||
bool multiMat2 = false;
|
||||
MaterialBrowserRequestBus::BroadcastResult(multiMat1, &MaterialBrowserRequests::IsMultiMaterial, productThumbnailKey1->GetAssetId());
|
||||
MaterialBrowserRequestBus::BroadcastResult(multiMat2, &MaterialBrowserRequests::IsMultiMaterial, productThumbnailKey2->GetAssetId());
|
||||
return multiMat1 == multiMat2;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//! MaterialBrowserEntry thumbnails
|
||||
class MaterialThumbnailCache
|
||||
: public Thumbnailer::ThumbnailCache<MaterialThumbnail, MaterialKeyHash, MaterialKeyEqual>
|
||||
{
|
||||
public:
|
||||
MaterialThumbnailCache();
|
||||
~MaterialThumbnailCache() override;
|
||||
|
||||
int GetPriority() const override;
|
||||
const char* GetProviderName() const override;
|
||||
|
||||
static constexpr const char* ProviderName = "CryMaterial Thumbnails";
|
||||
|
||||
protected:
|
||||
bool IsSupportedThumbnail(Thumbnailer::SharedThumbnailKey key) const override;
|
||||
};
|
||||
} // namespace MaterialBrowser
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include "EditorDefs.h"
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <Util/EditorUtils.h>
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Debug/TraceMessageBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
|
||||
#include <AzToolsFramework/Application/ToolsApplication.h>
|
||||
#include <Material/MaterialPythonFuncs.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace MaterialPythonFuncsUnitTests
|
||||
{
|
||||
|
||||
class MaterialPythonBindingsFixture
|
||||
: public testing::Test
|
||||
{
|
||||
public:
|
||||
AzToolsFramework::ToolsApplication m_app;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
AzFramework::Application::Descriptor appDesc;
|
||||
appDesc.m_enableDrilling = false;
|
||||
|
||||
m_app.Start(appDesc);
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
m_app.RegisterComponentDescriptor(AzToolsFramework::MaterialPythonFuncsHandler::CreateDescriptor());
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_app.Stop();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MaterialPythonBindingsFixture, MaterialEditorCommands_ApiExists)
|
||||
{
|
||||
AZ::BehaviorContext* behaviorContext = m_app.GetBehaviorContext();
|
||||
ASSERT_TRUE(behaviorContext);
|
||||
|
||||
EXPECT_TRUE(behaviorContext->m_methods.find("create") != behaviorContext->m_methods.end());
|
||||
EXPECT_TRUE(behaviorContext->m_methods.find("create_multi") != behaviorContext->m_methods.end());
|
||||
EXPECT_TRUE(behaviorContext->m_methods.find("convert_to_multi") != behaviorContext->m_methods.end());
|
||||
EXPECT_TRUE(behaviorContext->m_methods.find("duplicate_current") != behaviorContext->m_methods.end());
|
||||
EXPECT_TRUE(behaviorContext->m_methods.find("merge_selection") != behaviorContext->m_methods.end());
|
||||
EXPECT_TRUE(behaviorContext->m_methods.find("delete_current") != behaviorContext->m_methods.end());
|
||||
EXPECT_TRUE(behaviorContext->m_methods.find("get_submaterial") != behaviorContext->m_methods.end());
|
||||
EXPECT_TRUE(behaviorContext->m_methods.find("get_property") != behaviorContext->m_methods.end());
|
||||
EXPECT_TRUE(behaviorContext->m_methods.find("set_property") != behaviorContext->m_methods.end());
|
||||
}
|
||||
}
|
||||
@ -1,149 +0,0 @@
|
||||
/*
|
||||
* 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 "MatEditPreviewDlg.h"
|
||||
|
||||
// Qt
|
||||
#include <QFileDialog>
|
||||
#include <QMenuBar>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
// Editor
|
||||
#include "Material/MaterialManager.h"
|
||||
#include "Material/MaterialPreviewModelView.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMatEditPreviewDlg dialog
|
||||
|
||||
|
||||
CMatEditPreviewDlg::CMatEditPreviewDlg(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
setWindowTitle(tr("Material Preview"));
|
||||
|
||||
/* create sub controls */
|
||||
m_previewCtrl.reset(new MaterialPreviewModelView(this));
|
||||
m_menubar.reset(new QMenuBar);
|
||||
|
||||
/* configure layout */
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(m_menubar.data());
|
||||
layout->addWidget(m_previewCtrl.data());
|
||||
layout->setStretchFactor(m_previewCtrl.data(), 1);
|
||||
setLayout(layout);
|
||||
|
||||
GetIEditor()->GetMaterialManager()->AddListener(this);
|
||||
|
||||
SetupMenuBar();
|
||||
|
||||
OnPreviewPlane();
|
||||
m_previewCtrl->SetMaterial(GetIEditor()->GetMaterialManager()->GetCurrentMaterial() ? GetIEditor()->GetMaterialManager()->GetCurrentMaterial()->GetMatInfo() : nullptr);
|
||||
m_previewCtrl->Update();
|
||||
}
|
||||
|
||||
CMatEditPreviewDlg::~CMatEditPreviewDlg()
|
||||
{
|
||||
GetIEditor()->GetMaterialManager()->RemoveListener(this);
|
||||
}
|
||||
|
||||
QSize CMatEditPreviewDlg::sizeHint() const
|
||||
{
|
||||
return QSize(450, 400);
|
||||
}
|
||||
|
||||
void CMatEditPreviewDlg::showEvent(QShowEvent* e)
|
||||
{
|
||||
QDialog::showEvent(e);
|
||||
resize(sizeHint()); // Because WindowDecorationWrapper resizes it to the minimum for some reason.
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatEditPreviewDlg::SetupMenuBar()
|
||||
{
|
||||
QMenu* menu;
|
||||
QAction* action;
|
||||
|
||||
menu = m_menubar->addMenu(tr("Preview"));
|
||||
action = menu->addAction(tr("&Plane"));
|
||||
connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewPlane);
|
||||
action = menu->addAction(tr("&Sphere"));
|
||||
connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewSphere);
|
||||
action = menu->addAction(tr("&Box"));
|
||||
connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewBox);
|
||||
action = menu->addAction(tr("&Teapot"));
|
||||
connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewTeapot);
|
||||
action = menu->addAction(tr("&Custom"));
|
||||
connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewCustom);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatEditPreviewDlg::OnPreviewSphere()
|
||||
{
|
||||
m_previewCtrl->LoadModelFile("Objects/MtlSphere.cgf");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatEditPreviewDlg::OnPreviewBox()
|
||||
{
|
||||
m_previewCtrl->LoadModelFile("Objects/MtlBox.cgf");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatEditPreviewDlg::OnPreviewTeapot()
|
||||
{
|
||||
m_previewCtrl->LoadModelFile("Objects/MtlTeapot.cgf");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatEditPreviewDlg::OnPreviewPlane()
|
||||
{
|
||||
m_previewCtrl->LoadModelFile("Objects/MtlPlane.cgf");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatEditPreviewDlg::OnPreviewCustom()
|
||||
{
|
||||
const QString fullFileName =
|
||||
QFileDialog::getOpenFileName(this, tr("Custom Model"), QString(), tr("Objects (*.cgf);;All files (*.*)"));
|
||||
if (!fullFileName.isNull())
|
||||
{
|
||||
m_previewCtrl->LoadModelFile(fullFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMatEditPreviewDlg message handlers
|
||||
|
||||
void CMatEditPreviewDlg::OnDataBaseItemEvent([[maybe_unused]] IDataBaseItem* pItem, EDataBaseItemEvent event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case EDB_ITEM_EVENT_SELECTED:
|
||||
case EDB_ITEM_EVENT_ADD:
|
||||
case EDB_ITEM_EVENT_CHANGED:
|
||||
m_previewCtrl->SetMaterial(GetIEditor()->GetMaterialManager()->GetCurrentMaterial() ? GetIEditor()->GetMaterialManager()->GetCurrentMaterial()->GetMatInfo() : nullptr);
|
||||
break;
|
||||
case EDB_ITEM_EVENT_DELETE:
|
||||
m_previewCtrl->SetMaterial(nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#include <moc_MatEditPreviewDlg.cpp>
|
||||
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_MATEDITPREVIEWDLG_H
|
||||
#define CRYINCLUDE_EDITOR_MATEDITPREVIEWDLG_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#include <QScopedPointer>
|
||||
|
||||
#include "IDataBaseManager.h"
|
||||
#endif
|
||||
|
||||
class MaterialPreviewModelView;
|
||||
class QMenuBar;
|
||||
|
||||
// MatEditPreviewDlg.h : header file
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMatEditPreviewDlg dialog
|
||||
class CMatEditPreviewDlg
|
||||
: public QDialog
|
||||
, public IDataBaseManagerListener
|
||||
{
|
||||
Q_OBJECT
|
||||
// Construction
|
||||
public:
|
||||
CMatEditPreviewDlg(QWidget* parent); // standard constructor
|
||||
~CMatEditPreviewDlg();
|
||||
|
||||
QSize sizeHint() const override;
|
||||
void showEvent(QShowEvent*) override;
|
||||
|
||||
//Functions
|
||||
|
||||
virtual void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event);
|
||||
|
||||
protected:
|
||||
void SetupMenuBar();
|
||||
|
||||
private slots:
|
||||
void OnPreviewSphere();
|
||||
void OnPreviewPlane();
|
||||
void OnPreviewBox();
|
||||
void OnPreviewTeapot();
|
||||
void OnPreviewCustom();
|
||||
|
||||
private:
|
||||
QScopedPointer<MaterialPreviewModelView> m_previewCtrl;
|
||||
QScopedPointer<QMenuBar> m_menubar;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_MATEDITPREVIEWDLG_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,315 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIAL_H
|
||||
#define CRYINCLUDE_EDITOR_MATERIAL_MATERIAL_H
|
||||
#pragma once
|
||||
|
||||
#include <IMaterial.h>
|
||||
#include <IRenderer.h>
|
||||
#include "BaseLibraryItem.h"
|
||||
#include "Include/IEditorMaterial.h"
|
||||
#include "Util/Variable.h"
|
||||
#include <vector>
|
||||
|
||||
// forward declarations,
|
||||
class CMaterialManager;
|
||||
class CVarBlock;
|
||||
|
||||
enum eMTL_PROPAGATION
|
||||
{
|
||||
MTL_PROPAGATE_OPACITY = 1 << 0,
|
||||
MTL_PROPAGATE_LIGHTING = 1 << 1,
|
||||
MTL_PROPAGATE_ADVANCED = 1 << 2,
|
||||
MTL_PROPAGATE_TEXTURES = 1 << 3,
|
||||
MTL_PROPAGATE_SHADER_PARAMS = 1 << 4,
|
||||
MTL_PROPAGATE_SHADER_GEN = 1 << 5,
|
||||
MTL_PROPAGATE_VERTEX_DEF = 1 << 6,
|
||||
MTL_PROPAGATE_LAYER_PRESETS = 1 << 7,
|
||||
MTL_PROPAGATE_MATERIAL_SETTINGS = 1 << 8,
|
||||
MTL_PROPAGATE_ALL = (
|
||||
MTL_PROPAGATE_OPACITY |
|
||||
MTL_PROPAGATE_LIGHTING |
|
||||
MTL_PROPAGATE_ADVANCED |
|
||||
MTL_PROPAGATE_TEXTURES |
|
||||
MTL_PROPAGATE_SHADER_PARAMS |
|
||||
MTL_PROPAGATE_SHADER_GEN |
|
||||
MTL_PROPAGATE_VERTEX_DEF |
|
||||
MTL_PROPAGATE_LAYER_PRESETS |
|
||||
MTL_PROPAGATE_MATERIAL_SETTINGS),
|
||||
MTL_PROPAGATE_RESERVED = 1 << 9
|
||||
};
|
||||
|
||||
/** CMaterial class
|
||||
Every Material is a member of material library.
|
||||
Materials can have child sub materials,
|
||||
Sub materials are applied to the same geometry of the parent material in the other material slots.
|
||||
*/
|
||||
|
||||
struct SMaterialLayerResources
|
||||
{
|
||||
SMaterialLayerResources()
|
||||
: m_nFlags(MTL_LAYER_USAGE_REPLACEBASE)
|
||||
, m_bRegetPublicParams(true)
|
||||
, m_pMatLayer(0)
|
||||
{
|
||||
}
|
||||
|
||||
uint8 m_nFlags;
|
||||
bool m_bRegetPublicParams;
|
||||
QString m_shaderName;
|
||||
|
||||
_smart_ptr< IMaterialLayer > m_pMatLayer;
|
||||
SInputShaderResources m_shaderResources;
|
||||
XmlNodeRef m_publicVarsCache;
|
||||
};
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
class CRYEDIT_API CMaterial
|
||||
: public IEditorMaterial
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CMaterial(const QString& name, int nFlags = 0);
|
||||
CMaterial(const CMaterial& rhs);
|
||||
~CMaterial();
|
||||
|
||||
virtual EDataBaseItemType GetType() const { return EDB_TYPE_MATERIAL; };
|
||||
|
||||
void SetName(const QString& name);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString GetFullName() const { return m_name; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// File properties of the material.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString GetFilename() const;
|
||||
|
||||
//! Collect filenames of texture sources used in material
|
||||
//! Return number of filenames
|
||||
int GetTextureFilenames(QStringList& outFilenames) const;
|
||||
int GetAnyTextureFilenames(QStringList& outFilenames) const;
|
||||
|
||||
void UpdateFileAttributes(bool useSourceControl = true);
|
||||
uint32 GetFileAttributes();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Sets one or more material flags from EMaterialFlags enum.
|
||||
void SetFlags(int flags) { m_mtlFlags = flags; };
|
||||
//! Query this material flags.
|
||||
virtual int GetFlags() const { return m_mtlFlags; }
|
||||
bool IsMultiSubMaterial() const { return (m_mtlFlags & MTL_FLAG_MULTI_SUBMTL) != 0; };
|
||||
bool IsPureChild() const { return (m_mtlFlags & MTL_FLAG_PURE_CHILD) != 0; }
|
||||
|
||||
// Check if material is used.
|
||||
bool IsUsed() const { /*return m_nUseCount > 0 || (m_mtlFlags & MTL_FLAG_ALWAYS_USED);*/ return true; };
|
||||
|
||||
virtual void GatherUsedResources(CUsedResources& resources);
|
||||
|
||||
//! Set name of shader used by this material.
|
||||
void SetShaderName(const QString& shaderName);
|
||||
//! Get name of shader used by this material.
|
||||
QString GetShaderName() const { return m_shaderName; };
|
||||
|
||||
virtual SInputShaderResources& GetShaderResources() { return m_shaderResources; };
|
||||
|
||||
//! Get public parameters of material in variable block.
|
||||
CVarBlock* GetPublicVars(SInputShaderResources& pShaderResources);
|
||||
|
||||
//! Set the shader public param m_script variable into our own m_script, script contains min/max for a given shader param value
|
||||
void SetShaderParamPublicScript();
|
||||
|
||||
//! Sets variable block of public shader parameters.
|
||||
//! VarBlock must be in same format as returned by GetPublicVars().
|
||||
void SetPublicVars(CVarBlock* pPublicVars, CMaterial* pMtl);
|
||||
|
||||
//! Update names/descriptions in this variable array, return a variable block for replacing
|
||||
CVarBlock* UpdateTextureNames(CSmartVariableArray textureVars[EFTT_MAX]);
|
||||
// [Shader System] - Do To: add back with map usage: CVarBlock* UpdateTextureNames(AZStd::unordered_map<ResourceSlotIndex, CSmartVariableArray>& textureVarsMap);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVarBlock* GetShaderGenParamsVars();
|
||||
void SetShaderGenParamsVars(CVarBlock* pBlock);
|
||||
uint64 GetShaderGenMask() { return m_nShaderGenMask; }
|
||||
void SetShaderGenMask(uint64 mask) { m_nShaderGenMask = mask; }
|
||||
|
||||
//! Return variable block of shader params.
|
||||
SShaderItem& GetShaderItem() { return m_shaderItem; };
|
||||
|
||||
//! Return material layers resources
|
||||
SMaterialLayerResources* GetMtlLayerResources() { return m_pMtlLayerResources; };
|
||||
|
||||
//! Get texture map usage mask for shader in this material.
|
||||
unsigned int GetTexmapUsageMask() const;
|
||||
|
||||
//! Load new shader.
|
||||
bool LoadShader();
|
||||
|
||||
//! Reload shader, update all shader parameters.
|
||||
virtual void Update();
|
||||
|
||||
// Reload material settings from file.
|
||||
// NOTICE: The function will remove all the sub-materials and recreate them!
|
||||
void Reload();
|
||||
|
||||
//! Serialize material settings to xml.
|
||||
virtual void Serialize(SerializeContext& ctx);
|
||||
|
||||
//! Assign this material to static geometry.
|
||||
void AssignToEntity(IRenderNode* pEntity);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Surface types.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void SetSurfaceTypeName(const QString& surfaceType);
|
||||
virtual const QString& GetSurfaceTypeName() const { return m_surfaceType; };
|
||||
bool IsBreakable2D() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Child Sub materials.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Get number of sub materials childs.
|
||||
int GetSubMaterialCount() const;
|
||||
//! Set number of sub materials childs.
|
||||
void SetSubMaterialCount(int nSubMtlsCount);
|
||||
//! Get sub material child by index.
|
||||
CMaterial* GetSubMaterial(int index) const;
|
||||
//! Find sub material index by name
|
||||
int FindMaterialIndex(const QString& name);
|
||||
// Set a material to the sub materials slot.
|
||||
// Use NULL material pointer to clear slot.
|
||||
void SetSubMaterial(int nSlot, CMaterial* mtl);
|
||||
//! Remove all sub materials, does not change number of sub material slots.
|
||||
void ClearAllSubMaterials();
|
||||
|
||||
//! Return pointer to engine material.
|
||||
virtual _smart_ptr<IMaterial> GetMatInfo(bool bUseExistingEngineMaterial = true);
|
||||
// Clear stored pointer to engine material.
|
||||
void ClearMatInfo();
|
||||
|
||||
//! Validate materials for errors.
|
||||
void Validate();
|
||||
|
||||
// Check if material file can be modified.
|
||||
// Will check file attributes if it is not read only.
|
||||
bool CanModify(bool bSkipReadOnly = true);
|
||||
|
||||
// Save material to file.
|
||||
virtual bool Save(bool bSkipReadOnly = true, const QString& fullPath = "");
|
||||
|
||||
// Dummy material is just a placeholder item for materials that have not been found on disk.
|
||||
void SetDummy(bool bDummy) { m_bDummyMaterial = bDummy; }
|
||||
bool IsDummy() const { return m_bDummyMaterial != 0; }
|
||||
|
||||
// Called by material manager when material selected as a current material.
|
||||
void OnMakeCurrent();
|
||||
|
||||
void SetFromMatInfo(_smart_ptr<IMaterial> pMatInfo);
|
||||
|
||||
// Link a submaterial by name (used for value propagation in CMaterialUI)
|
||||
void LinkToMaterial(const QString& name);
|
||||
const QString& GetLinkedMaterialName() { return m_linkedMaterial; }
|
||||
|
||||
// Return parent material for submaterial
|
||||
CMaterial* GetParent() const {return m_pParent; }
|
||||
|
||||
//! Loads material layers
|
||||
bool LoadMaterialLayers();
|
||||
//! Updates material layers
|
||||
void UpdateMaterialLayers();
|
||||
|
||||
void SetHighlightFlags(int highlightFlags);
|
||||
void UpdateHighlighting();
|
||||
virtual void DisableHighlightForFrame();
|
||||
void RecordUndo(const char* sText, bool bForceUpdate = false);
|
||||
|
||||
int GetPropagationFlags() const { return m_propagationFlags; }
|
||||
void SetPropagationFlags(const int flags) { m_propagationFlags = flags; }
|
||||
|
||||
bool LayerActivationAllowed() const { return m_allowLayerActivation; }
|
||||
void SetLayerActivation(bool allowed) { m_allowLayerActivation = allowed; }
|
||||
|
||||
uint32 GetDccMaterialHash() const { return m_dccMaterialHash; }
|
||||
void SetDccMaterialHash(AZ::u32 hash) { m_dccMaterialHash = hash; }
|
||||
void SetShaderItem(const SShaderItem& shaderItem);
|
||||
|
||||
private:
|
||||
void UpdateMatInfo();
|
||||
void CheckSpecialConditions();
|
||||
|
||||
void NotifyChanged();
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Variables.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString m_shaderName;
|
||||
QString m_surfaceType;
|
||||
QString m_linkedMaterial;
|
||||
|
||||
//! Material flags.
|
||||
int m_mtlFlags;
|
||||
|
||||
// Hash for DCC material attributes, used to check if .dccmtl has changed
|
||||
// If so, the source .mtl file will need to be rebuilt
|
||||
uint32 m_dccMaterialHash;
|
||||
|
||||
// Parent material, Only valid for Pure Childs.
|
||||
CMaterial* m_pParent;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Shader resources.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
SShaderItem m_shaderItem;
|
||||
SInputShaderResources m_shaderResources;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
//CVarBlockPtr m_shaderParamsVar;
|
||||
//! Common shader flags.
|
||||
uint64 m_nShaderGenMask;
|
||||
QString m_pszShaderGenMask;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
SMaterialLayerResources m_pMtlLayerResources[MTL_LAYER_MAX_SLOTS];
|
||||
|
||||
_smart_ptr<IMaterial> m_pMatInfo;
|
||||
|
||||
XmlNodeRef m_publicVarsCache;
|
||||
|
||||
//! Array of sub materials.
|
||||
std::vector<_smart_ptr<CMaterial> > m_subMaterials;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
int m_nUseCount;
|
||||
uint32 m_scFileAttributes;
|
||||
|
||||
unsigned char m_highlightFlags;
|
||||
|
||||
// The propagation flags are a bit combination of the MTL_PROPAGATION enum above
|
||||
// and determine which properties get propagated to an optional linked material
|
||||
// during ui editing
|
||||
int m_propagationFlags;
|
||||
|
||||
//! Material Used in level.
|
||||
unsigned int m_bDummyMaterial : 1; // Dummy material, name specified but material file not found.
|
||||
unsigned int m_bIgnoreNotifyChange : 1; // Do not send notifications about changes.
|
||||
unsigned int m_bRegetPublicParams : 1;
|
||||
unsigned int m_bKeepPublicParamsValues : 1;
|
||||
|
||||
bool m_allowLayerActivation;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIAL_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,248 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALBROWSER_H
|
||||
#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALBROWSER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "Include/IDataBaseManager.h"
|
||||
#include "Material/Material.h"
|
||||
#include "Material/MaterialBrowserFilterModel.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QDateTime>
|
||||
#include <QModelIndex>
|
||||
#include <ISourceControl.h>
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
|
||||
#endif
|
||||
|
||||
class CMaterial;
|
||||
|
||||
class MaterialBrowserWidget;
|
||||
class CMaterialImageListCtrl;
|
||||
class QMaterialImageListModel;
|
||||
|
||||
class QTreeView;
|
||||
class QAction;
|
||||
|
||||
struct IDataBaseItem;
|
||||
class CMaterialBrowserRecord;
|
||||
typedef std::vector<CMaterialBrowserRecord> TMaterialBrowserRecords;
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace AssetBrowser
|
||||
{
|
||||
class AssetBrowserModel;
|
||||
class AssetBrowserFilterModel;
|
||||
class AssetTypeFilter;
|
||||
}
|
||||
}
|
||||
|
||||
enum ESccFileAttributes;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MaterialBrowser;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct IMaterialBrowserListener
|
||||
{
|
||||
virtual void OnBrowserSelectItem(IDataBaseItem* pItem, bool bForce) = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaterialBrowserWidget
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class MaterialBrowserFilterModel;
|
||||
|
||||
class MaterialBrowserWidget
|
||||
: public QWidget
|
||||
, public IDataBaseManagerListener
|
||||
, public IEditorNotifyListener
|
||||
, public MaterialBrowserWidgetBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum EViewType
|
||||
{
|
||||
VIEW_LEVEL = 0,
|
||||
VIEW_ALL = 1,
|
||||
};
|
||||
|
||||
enum EFilter
|
||||
{
|
||||
eFilter_Materials = 0x01,
|
||||
eFilter_Textures = 0x02,
|
||||
eFilter_Materials_And_Textures = 0x03,
|
||||
eFilter_Submaterials = 0x04
|
||||
};
|
||||
|
||||
MaterialBrowserWidget(QWidget* parent);
|
||||
~MaterialBrowserWidget();
|
||||
|
||||
void SetListener(IMaterialBrowserListener* pListener) { m_pListener = pListener; }
|
||||
|
||||
EViewType GetViewType() const { return m_viewType; };
|
||||
|
||||
void ClearItems();
|
||||
|
||||
void SelectItem(IDataBaseItem* pItem, IDataBaseItem* pParentItem);
|
||||
void DeleteItem();
|
||||
|
||||
void PopulateItems();
|
||||
void StartRecordUpdateJobs();
|
||||
|
||||
bool ShowCheckedOutRecursive(TMaterialBrowserRecords* pRecords);
|
||||
|
||||
void ShowOnlyLevelMaterials(bool levelOnly);
|
||||
|
||||
void OnCopy();
|
||||
void OnCopyName();
|
||||
void OnPaste();
|
||||
void OnCut();
|
||||
void OnDuplicate();
|
||||
void OnAddNewMaterial();
|
||||
void OnAddNewMultiMaterial();
|
||||
void OnConvertToMulti();
|
||||
void OnMergeMaterials();
|
||||
|
||||
public slots:
|
||||
void OnSelectionChanged();
|
||||
void OnSubMaterialSelectedInPreviewPane(const QModelIndex& current);
|
||||
void SaveCurrentMaterial();
|
||||
void OnRefreshSelection();
|
||||
void OnMaterialAdded();
|
||||
|
||||
signals:
|
||||
void refreshSelection();
|
||||
void materialAdded();
|
||||
|
||||
public:
|
||||
void OnUpdateShowCheckedOut();
|
||||
bool CanPaste() const;
|
||||
|
||||
void SetImageListCtrl(CMaterialImageListCtrl* pCtrl);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IDataBaseManagerListener implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void OnEditorNotifyEvent(EEditorNotifyEvent event);
|
||||
void AddContextMenuActionsSingleSelection(QMenu &menu, _smart_ptr<CMaterial> material) const;
|
||||
void OnContextMenuAction(int command, _smart_ptr<CMaterial> material);
|
||||
|
||||
// MaterialBrowserWidgetBus event handlers
|
||||
void MaterialAddFinished() override;
|
||||
void MaterialFinishedProcessing(_smart_ptr<CMaterial> material, const QPersistentModelIndex &filterModelIndex) override;
|
||||
void MaterialRecordUpdateFinished() override;
|
||||
|
||||
protected:
|
||||
// Item definition.
|
||||
enum ESourceControlOp
|
||||
{
|
||||
ESCM_IMPORT,
|
||||
ESCM_CHECKOUT,
|
||||
ESCM_UNDO_CHECKOUT,
|
||||
ESCM_GETLATEST,
|
||||
ESCM_GETLATESTTEXTURES,
|
||||
};
|
||||
|
||||
void DeleteItem(const CMaterialBrowserRecord &record);
|
||||
void SetSelectedItem(_smart_ptr<CMaterial> material, const TMaterialBrowserRecords* pMarkedRecords, bool selectInTreeView);
|
||||
void OnAddSubMtl();
|
||||
void OnSelectAssignedObjects();
|
||||
void OnAssignMaterialToSelection();
|
||||
void OnRenameItem();
|
||||
void OnResetItem();
|
||||
void OnSetSubMtlCount(const CMaterialBrowserRecord &record);
|
||||
|
||||
void DoSourceControlOp(CMaterialBrowserRecord &record, ESourceControlOp);
|
||||
|
||||
void OnMakeSubMtlSlot(const CMaterialBrowserRecord &record);
|
||||
void OnClearSubMtlSlot(_smart_ptr<CMaterial> subMaterial);
|
||||
void SetSubMaterial(_smart_ptr<CMaterial> parentMaterial, int slot, _smart_ptr<CMaterial> subMaterial);
|
||||
|
||||
void OnSaveToFile(bool bMulti);
|
||||
|
||||
void RefreshSelected();
|
||||
|
||||
void TickRefreshMaterials();
|
||||
void TryLoadRecordMaterial(CMaterialBrowserRecord &record);
|
||||
|
||||
void ShowContextMenu(const CMaterialBrowserRecord &record, const QPoint& point);
|
||||
_smart_ptr<CMaterial> GetCurrentMaterial();
|
||||
|
||||
uint32 MaterialNameToCrc32(const QString& str);
|
||||
|
||||
bool TryGetSelectedRecord(CMaterialBrowserRecord &record);
|
||||
AZStd::string GetSelectedMaterialID();
|
||||
|
||||
private:
|
||||
void expandAllNotMatchingIndexes(const QModelIndex& parent = QModelIndex());
|
||||
void ClearImageListControlSelection();
|
||||
void ClearSelection(QMaterialImageListModel* materialModel);
|
||||
QMenu *InitializeSearchMenu();
|
||||
|
||||
void AddContextMenuActionsMultiSelect(QMenu &menu) const;
|
||||
void AddContextMenuActionsNoSelection(QMenu &menu) const;
|
||||
void AddContextMenuActionsSubMaterial(QMenu &menu, _smart_ptr<CMaterial> parentMaterial, _smart_ptr<CMaterial> subMaterial) const;
|
||||
void AddContextMenuActionsMultiMaterial(QMenu &menu) const;
|
||||
void AddContextMenuActionsSingleMaterial(QMenu &menu) const;
|
||||
void AddContextMenuActionsCommon(QMenu &menu, _smart_ptr<CMaterial> material) const;
|
||||
void AddContextMenuActionsSourceControl(QMenu &menu, _smart_ptr<CMaterial> material, uint32 fileAttributes) const;
|
||||
|
||||
QScopedPointer<Ui::MaterialBrowser> m_ui;
|
||||
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserModel* m_assetBrowserModel;
|
||||
QSharedPointer<MaterialBrowserFilterModel> m_filterModel;
|
||||
int m_selectedSubMaterialIndex = -1;
|
||||
|
||||
bool m_bIgnoreSelectionChange;
|
||||
bool m_bItemsValid;
|
||||
|
||||
CMaterialManager* m_pMatMan;
|
||||
IMaterialBrowserListener* m_pListener;
|
||||
CMaterialImageListCtrl* m_pMaterialImageListCtrl;
|
||||
|
||||
EViewType m_viewType;
|
||||
bool m_bNeedReload;
|
||||
|
||||
bool m_bHighlightMaterial;
|
||||
uint32 m_timeOfHighlight;
|
||||
|
||||
TMaterialBrowserRecords m_markedRecords;
|
||||
|
||||
_smart_ptr<CMaterial> m_pLastActiveMultiMaterial;
|
||||
_smart_ptr<CMaterial> m_delayedSelection;
|
||||
|
||||
bool m_bShowOnlyCheckedOut;
|
||||
|
||||
QAction* m_cutAction;
|
||||
QAction* m_copyAction;
|
||||
QAction* m_pasteAction;
|
||||
QAction* m_duplicateAction;
|
||||
QAction* m_deleteAction;
|
||||
QAction* m_renameItemAction;
|
||||
QAction* m_addNewMaterialAction;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALBROWSER_H
|
||||
@ -1,87 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MaterialBrowser</class>
|
||||
<widget class="QWidget" name="MaterialBrowser">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>250</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="AzToolsFramework::AssetBrowser::SearchWidget" name="m_searchWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>147</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AzToolsFramework::AssetBrowser::AssetBrowserTreeView" name="treeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzToolsFramework::AssetBrowser::SearchWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>AzToolsFramework/AssetBrowser/Search/SearchWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AzToolsFramework::AssetBrowser::AssetBrowserTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="MaterialDialog.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,652 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "MaterialBrowserFilterModel.h"
|
||||
|
||||
// AzFramework
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
|
||||
// AzToolsFramework
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/AssetBrowser/EBusFindAssetTypeByName.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
|
||||
|
||||
// Editor
|
||||
#include "MaterialBrowserSearchFilters.h"
|
||||
#include "MaterialManager.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// how often to re-query source control status of an item after querying it, in seconds.
|
||||
// note that using a source control operation on an item invalidates the cache and will immediately
|
||||
// refresh its status regardless of this value, so it can be pretty high.
|
||||
qint64 g_timeRefreshSCCStatus = 60;
|
||||
}
|
||||
|
||||
#define IDC_MATERIAL_TREECTRL 3
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#define ITEM_IMAGE_SHARED_MATERIAL 0
|
||||
#define ITEM_IMAGE_SHARED_MATERIAL_SELECTED 1
|
||||
#define ITEM_IMAGE_FOLDER 2
|
||||
#define ITEM_IMAGE_FOLDER_OPEN 3
|
||||
#define ITEM_IMAGE_MATERIAL 4
|
||||
#define ITEM_IMAGE_MATERIAL_SELECTED 5
|
||||
#define ITEM_IMAGE_MULTI_MATERIAL 6
|
||||
#define ITEM_IMAGE_MULTI_MATERIAL_SELECTED 7
|
||||
|
||||
|
||||
#define ITEM_IMAGE_OVERLAY_CGF 8
|
||||
#define ITEM_IMAGE_OVERLAY_INPAK 9
|
||||
#define ITEM_IMAGE_OVERLAY_READONLY 10
|
||||
#define ITEM_IMAGE_OVERLAY_ONDISK 11
|
||||
#define ITEM_IMAGE_OVERLAY_LOCKED 12
|
||||
#define ITEM_IMAGE_OVERLAY_CHECKEDOUT 13
|
||||
#define ITEM_IMAGE_OVERLAY_NO_CHECKOUT 14
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AZ::Data::AssetId GetMaterialProductAssetIdFromAssetBrowserEntry(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* assetEntry)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
|
||||
if (assetEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source ||
|
||||
assetEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product)
|
||||
{
|
||||
AZStd::vector<const ProductAssetBrowserEntry*> products;
|
||||
assetEntry->GetChildrenRecursively<ProductAssetBrowserEntry>(products);
|
||||
|
||||
// Cache the material asset type because this function is called for every submaterial when searching.
|
||||
// AssetType is a POD struct so it should be fine to leave it as a static that gets destroyed during library unload/program termination.
|
||||
static AZ::Data::AssetType materialAssetType = AZ::Data::AssetType::CreateNull();
|
||||
if (materialAssetType.IsNull())
|
||||
{
|
||||
EBusFindAssetTypeByName materialAssetTypeResult("Material");
|
||||
AZ::AssetTypeInfoBus::BroadcastResult(materialAssetTypeResult, &AZ::AssetTypeInfo::GetAssetType);
|
||||
AZ_Assert(materialAssetTypeResult.Found(), "Could not find asset type for material asset");
|
||||
materialAssetType = materialAssetTypeResult.GetAssetType();
|
||||
}
|
||||
|
||||
for (const auto* product : products)
|
||||
{
|
||||
if (product->GetAssetType() == materialAssetType)
|
||||
{
|
||||
return product->GetAssetId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return AZ::Data::AssetId();
|
||||
}
|
||||
|
||||
MaterialBrowserFilterModel::MaterialBrowserFilterModel(QObject* parent)
|
||||
: AzToolsFramework::AssetBrowser::AssetBrowserFilterModel(parent)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
using namespace AzToolsFramework::MaterialBrowser;
|
||||
|
||||
MaterialBrowserSourceControlBus::Handler::BusConnect();
|
||||
AssetBrowserModelNotificationBus::Handler::BusConnect();
|
||||
MaterialBrowserRequestBus::Handler::BusConnect();
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
|
||||
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_00.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_01.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_02.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_03.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_04.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_05.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_06.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_07.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_00.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_01.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_02.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_03.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_04.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_05.png"));
|
||||
m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_06.png"));
|
||||
|
||||
|
||||
// Create an asset type filter for materials
|
||||
AssetTypeFilter* assetTypeFilter = new AssetTypeFilter();
|
||||
assetTypeFilter->SetAssetType("Material");
|
||||
assetTypeFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down); //this will make sure folders that contain materials are displayed
|
||||
m_assetTypeFilter = FilterConstType(assetTypeFilter);
|
||||
|
||||
// Create search filters. SetSearchFilter stores these filters so that they are deleted when this object is deleted.
|
||||
m_subMaterialSearchFilter = new SubMaterialSearchFilter(this);
|
||||
m_levelMaterialSearchFilter = new LevelMaterialSearchFilter(this);
|
||||
|
||||
InitializeRecordUpdateJob();
|
||||
}
|
||||
|
||||
MaterialBrowserFilterModel::~MaterialBrowserFilterModel()
|
||||
{
|
||||
SAFE_DELETE(m_jobCancelGroup);
|
||||
SAFE_DELETE(m_jobContext);
|
||||
SAFE_DELETE(m_jobManager);
|
||||
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler::BusDisconnect();
|
||||
MaterialBrowserSourceControlBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::MaterialBrowser::MaterialBrowserRequestBus::Handler::BusDisconnect();
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::UpdateRecord(const QModelIndex& filterModelIndex)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
|
||||
if (filterModelIndex.isValid())
|
||||
{
|
||||
QModelIndex modelIndex = mapToSource(filterModelIndex);
|
||||
|
||||
AssetBrowserEntry* assetEntry = static_cast<AssetBrowserEntry*>(modelIndex.internalPointer());
|
||||
|
||||
if (assetEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source ||
|
||||
assetEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product)
|
||||
{
|
||||
AZStd::vector<const ProductAssetBrowserEntry*> products;
|
||||
assetEntry->GetChildrenRecursively<ProductAssetBrowserEntry>(products);
|
||||
|
||||
for (const auto* product : products)
|
||||
{
|
||||
if (!m_assetTypeFilter->Match(product))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
MaterialBrowserRecordAssetBrowserData assetBrowserData;
|
||||
assetBrowserData.assetId = product->GetAssetId();
|
||||
assetBrowserData.relativeFilePath = product->GetRelativePath();
|
||||
assetBrowserData.fullSourcePath = product->GetFullPath();
|
||||
assetBrowserData.modelIndex = modelIndex;
|
||||
assetBrowserData.filterModelIndex = filterModelIndex;
|
||||
UpdateRecord(assetBrowserData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::UpdateRecord(const MaterialBrowserRecordAssetBrowserData& assetBrowserData)
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
record.SetAssetBrowserData(assetBrowserData);
|
||||
record.m_material = GetIEditor()->GetMaterialManager()->LoadMaterial(record.GetRelativeFilePath().c_str());
|
||||
SetRecord(record);
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::UpdateSourceControlFileInfoCallback(const AZ::Data::AssetId& assetId, const AzToolsFramework::SourceControlFileInfo& info)
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
bool found = m_materialRecordMap.find(assetId, &record);
|
||||
if (found)
|
||||
{
|
||||
// Update the cached source control attributes for the record
|
||||
record.m_lastCachedSCCAttributes = info;
|
||||
record.m_lastCachedFileAttributes = static_cast<ESccFileAttributes>(CFileUtil::GetAttributes(record.GetFullSourcePath().c_str(), false));
|
||||
record.m_lastCheckedSCCAttributes = QDateTime::currentDateTime();
|
||||
|
||||
// Update the record
|
||||
m_materialRecordMap.erase(assetId);
|
||||
m_materialRecordMap.insert(AZStd::pair<AZ::Data::AssetId, CMaterialBrowserRecord>(record.GetAssetId(), record));
|
||||
|
||||
QueueDataChangedEvent(record.GetFilterModelIndex());
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::UpdateSourceControlLastCheckedTime(const AZ::Data::AssetId& assetId, const QDateTime& dateTime)
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
bool found = m_materialRecordMap.find(assetId, &record);
|
||||
if (found)
|
||||
{
|
||||
// Update the record
|
||||
record.m_lastCheckedSCCAttributes = dateTime;
|
||||
m_materialRecordMap.erase(assetId);
|
||||
m_materialRecordMap.insert(AZStd::pair<AZ::Data::AssetId, CMaterialBrowserRecord>(record.GetAssetId(), record));
|
||||
}
|
||||
}
|
||||
|
||||
QVariant MaterialBrowserFilterModel::data(const QModelIndex& index, int role /* = Qt::DisplayRole*/) const
|
||||
{
|
||||
// Should return data from an AssetBrowserEntry, or get material specific info from that data
|
||||
if (index.isValid())
|
||||
{
|
||||
// Use the base AssetBrowserFilterModel::data function for display role
|
||||
if (role != AzToolsFramework::AssetBrowser::AssetBrowserModel::Roles::EntryRole)
|
||||
{
|
||||
QModelIndex modelIndex = mapToSource(index);
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserEntry* assetEntry = static_cast<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>(modelIndex.internalPointer());
|
||||
|
||||
AZ::Data::AssetId assetId = GetMaterialProductAssetIdFromAssetBrowserEntry(assetEntry);
|
||||
if (assetId.IsValid())
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
bool found = m_materialRecordMap.find(assetId, &record);
|
||||
|
||||
if (role == Qt::UserRole)
|
||||
{
|
||||
if (found)
|
||||
{
|
||||
return QVariant::fromValue(record);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the role is Qt::DisplayRole, the item a folder, or the material has not been parsed yet, fall back on the default data result from the underlying AssetBrowserModel
|
||||
return AzToolsFramework::AssetBrowser::AssetBrowserFilterModel::data(index, role);
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::GetRelativeFilePaths(AZStd::vector<MaterialBrowserRecordAssetBrowserData>& files) const
|
||||
{
|
||||
GetRelativeFilePathsRecursive(files, this);
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::GetRelativeFilePathsRecursive(AZStd::vector<MaterialBrowserRecordAssetBrowserData>& files,
|
||||
const MaterialBrowserFilterModel* model, const QModelIndex& parent) const
|
||||
{
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
|
||||
for (int r = 0; r < model->rowCount(parent); ++r)
|
||||
{
|
||||
QModelIndex index = model->index(r, 0, parent);
|
||||
QModelIndex modelIndex = model->mapToSource(index);
|
||||
|
||||
if (model->hasChildren(index))
|
||||
{
|
||||
GetRelativeFilePathsRecursive(files, model, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetBrowserEntry* assetEntry = static_cast<AssetBrowserEntry*>(modelIndex.internalPointer());
|
||||
|
||||
AZStd::vector<const ProductAssetBrowserEntry*> products;
|
||||
assetEntry->GetChildrenRecursively<ProductAssetBrowserEntry>(products);
|
||||
|
||||
for (const auto* product : products)
|
||||
{
|
||||
if (!m_assetTypeFilter->Match(product))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
MaterialBrowserRecordAssetBrowserData item;
|
||||
item.assetId = product->GetAssetId();
|
||||
item.fullSourcePath = product->GetFullPath();
|
||||
item.relativeFilePath = product->GetRelativePath();
|
||||
item.modelIndex = modelIndex;
|
||||
item.filterModelIndex = index;
|
||||
files.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex MaterialBrowserFilterModel::GetIndexFromMaterial(_smart_ptr<CMaterial> material) const
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
bool found = TryGetRecordFromMaterial(material, record);
|
||||
if (found)
|
||||
{
|
||||
return record.GetFilterModelIndex();
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex MaterialBrowserFilterModel::GetFilterModelIndex(const AZ::Data::AssetId& assetId) const
|
||||
{
|
||||
QModelIndex filterModelIndex;
|
||||
if (TryGetFilterModelIndexRecursive(filterModelIndex, assetId, this))
|
||||
{
|
||||
return filterModelIndex;
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
bool MaterialBrowserFilterModel::TryGetFilterModelIndexRecursive(QModelIndex& filterModelIndex,
|
||||
const AZ::Data::AssetId& assetId, const MaterialBrowserFilterModel* model, const QModelIndex& parent) const
|
||||
{
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
|
||||
// Walk through the filter model to find the product entry with the corresponding assetId
|
||||
for (int r = 0; r < model->rowCount(parent); ++r)
|
||||
{
|
||||
QModelIndex index = model->index(r, 0, parent);
|
||||
QModelIndex modelIndex = model->mapToSource(index);
|
||||
|
||||
if (model->hasChildren(index))
|
||||
{
|
||||
if (TryGetFilterModelIndexRecursive(filterModelIndex, assetId, model, index))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check to see if the current entry is the one we're looking for
|
||||
AssetBrowserEntry* assetEntry = static_cast<AssetBrowserEntry*>(modelIndex.internalPointer());
|
||||
|
||||
AZStd::vector<const ProductAssetBrowserEntry*> products;
|
||||
assetEntry->GetChildrenRecursively<ProductAssetBrowserEntry>(products);
|
||||
|
||||
for (const auto* product : products)
|
||||
{
|
||||
if (assetId == product->GetAssetId())
|
||||
{
|
||||
filterModelIndex = index;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
|
||||
{
|
||||
// If the entry is a product material
|
||||
if (entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product && m_assetTypeFilter->Match(entry))
|
||||
{
|
||||
// capture the data here, so that entry cannot disappear before we actually get to the job.
|
||||
MaterialBrowserRecordAssetBrowserData assetBrowserData;
|
||||
assetBrowserData.assetId = GetMaterialProductAssetIdFromAssetBrowserEntry(entry);
|
||||
assetBrowserData.relativeFilePath = entry->GetRelativePath();
|
||||
assetBrowserData.fullSourcePath = entry->GetFullPath();
|
||||
assetBrowserData.filterModelIndex = GetFilterModelIndex(assetBrowserData.assetId);
|
||||
|
||||
// Create a job to add/update the entry in the underlying map
|
||||
AZ::Job* updateEntryJob = AZ::CreateJobFunction([this, assetBrowserData]()
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
record.SetAssetBrowserData(assetBrowserData);
|
||||
record.m_material = GetIEditor()->GetMaterialManager()->LoadMaterialWithFullSourcePath(record.GetRelativeFilePath().c_str(), record.GetFullSourcePath().c_str());
|
||||
SetRecord(record);
|
||||
MaterialBrowserWidgetBus::Broadcast(&MaterialBrowserWidgetEvents::MaterialAddFinished);
|
||||
}, true, m_jobContext);
|
||||
|
||||
// Start the job immediately
|
||||
AZ::Job* currentJob = m_jobContext->GetJobManager().GetCurrentJob();
|
||||
if (currentJob)
|
||||
{
|
||||
// Suspend the current job until the new job completes so that
|
||||
// if a new material is created by the user it's ready to use sooner
|
||||
currentJob->StartAsChild(updateEntryJob);
|
||||
currentJob->WaitForChildren();
|
||||
}
|
||||
else
|
||||
{
|
||||
updateEntryJob->Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MaterialBrowserFilterModel::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId)
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
bool found = m_materialRecordMap.find(assetId, &record);
|
||||
if (found)
|
||||
{
|
||||
record.m_material->Reload();
|
||||
//Send out event to notify UI update if it's currently selected
|
||||
MaterialBrowserWidgetBus::Broadcast(&MaterialBrowserWidgetEvents::MaterialFinishedProcessing, record.m_material, record.GetFilterModelIndex());
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialBrowserFilterModel::HasRecord(const AZ::Data::AssetId& assetId)
|
||||
{
|
||||
return m_materialRecordMap.find(assetId);
|
||||
}
|
||||
|
||||
bool MaterialBrowserFilterModel::IsMultiMaterial(const AZ::Data::AssetId& assetId)
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
bool found = m_materialRecordMap.find(assetId, &record);
|
||||
if (found)
|
||||
{
|
||||
if (record.m_material && record.m_material->IsMultiSubMaterial())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaterialBrowserFilterModel::TryGetRecordFromMaterial(_smart_ptr<CMaterial> material, CMaterialBrowserRecord& record) const
|
||||
{
|
||||
if (material)
|
||||
{
|
||||
// Get the relative path for the material
|
||||
bool pathFound = false;
|
||||
AZStd::string relativePath;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(pathFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath, material->GetFilename().toUtf8().data(), relativePath);
|
||||
AZ_Assert(pathFound, "Failed to get engine relative path from %s", material->GetFilename().toUtf8().data());
|
||||
|
||||
// Get the assetId from the relative path
|
||||
AZ::Data::AssetId assetId;
|
||||
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, relativePath.c_str(), GetIEditor()->GetMaterialManager()->GetMaterialAssetType(), false);
|
||||
|
||||
return TryGetRecordFromAssetId(assetId, record);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaterialBrowserFilterModel::TryGetRecordFromAssetId(const AZ::Data::AssetId& assetId, CMaterialBrowserRecord& record) const
|
||||
{
|
||||
bool recordFound = m_materialRecordMap.find(assetId, &record);
|
||||
return recordFound;
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::SetRecord(const CMaterialBrowserRecord& record)
|
||||
{
|
||||
m_materialRecordMap.erase(record.GetAssetId());
|
||||
m_materialRecordMap.insert({ record.GetAssetId(), record });
|
||||
|
||||
QueueDataChangedEvent(record.GetFilterModelIndex());
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::SetSearchFilter(const AzToolsFramework::AssetBrowser::SearchWidget* searchWidget)
|
||||
{
|
||||
/*
|
||||
* The filter matches the following rule:
|
||||
* A. If the entry is a material
|
||||
* 1. The material's name matches the search text
|
||||
* 2. The sub material's name matches the search text
|
||||
* B. If the entry is a folder:
|
||||
* 1. The folder's name matches the search text
|
||||
* 2. The folder contains a material matching A
|
||||
* 3. The folder contains a folder matching B.1 & B.2
|
||||
*/
|
||||
|
||||
using namespace AzToolsFramework::AssetBrowser;
|
||||
|
||||
m_searchWidget = searchWidget;
|
||||
|
||||
// Create a search filter where a search text either matches entry/entry parent's name or sub material name
|
||||
CompositeFilter* nameFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::OR);
|
||||
QSharedPointer<CompositeFilter> searchWidgetFilter = m_searchWidget->GetFilter();
|
||||
// The default setting for search widget filter is Down
|
||||
// Since now we only need to match for the entry itself in this filter, set back to None
|
||||
searchWidgetFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::None);
|
||||
nameFilter->AddFilter(FilterConstType(m_subMaterialSearchFilter));
|
||||
nameFilter->AddFilter(FilterConstType(searchWidgetFilter));
|
||||
|
||||
EntryTypeFilter* productsFilter = new EntryTypeFilter();
|
||||
productsFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Product);
|
||||
InverseFilter* noProductsFilter = new InverseFilter();
|
||||
noProductsFilter->SetFilter(FilterConstType(productsFilter));
|
||||
|
||||
// Create a filter where the entry needs to match the previous name filter and it needs to be material itself or it contains material.
|
||||
CompositeFilter* isMaterialAndMatchesSearchFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
|
||||
isMaterialAndMatchesSearchFilter->AddFilter(FilterConstType(nameFilter));
|
||||
isMaterialAndMatchesSearchFilter->AddFilter(FilterConstType(m_assetTypeFilter));
|
||||
isMaterialAndMatchesSearchFilter->AddFilter(FilterConstType(noProductsFilter));
|
||||
isMaterialAndMatchesSearchFilter->AddFilter(FilterConstType(m_levelMaterialSearchFilter));
|
||||
// Make sure any folder contains the matching result is included
|
||||
isMaterialAndMatchesSearchFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
|
||||
|
||||
// Set the filter for the MaterialBrowserFilterModel
|
||||
SetFilter(FilterConstType(isMaterialAndMatchesSearchFilter));
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::ShowOnlyLevelMaterials(bool levelOnly, bool invalidateFilterNow)
|
||||
{
|
||||
m_levelMaterialSearchFilter->ShowOnlyLevelMaterials(levelOnly);
|
||||
if (levelOnly)
|
||||
{
|
||||
m_levelMaterialSearchFilter->CacheLoadedMaterials();
|
||||
}
|
||||
|
||||
if (invalidateFilterNow)
|
||||
{
|
||||
// we need to invalid the filter immediately, for example this is used when we are changing level, otherwise
|
||||
// the current filter is used when getting file paths for all of the materials as part of StartRecordUpdateJobs.
|
||||
invalidateFilter();
|
||||
}
|
||||
else
|
||||
{
|
||||
filterUpdatedSlot();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::SearchFilterUpdated()
|
||||
{
|
||||
m_subMaterialSearchFilter->SetFilterString(m_searchWidget->textFilter());
|
||||
filterUpdatedSlot();
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::QueueDataChangedEvent(const QPersistentModelIndex& filterModelIndex)
|
||||
{
|
||||
// Queue a data changed event to be executed on the main thread
|
||||
AZStd::function<void()> emitDataChanged =
|
||||
[this, filterModelIndex]()
|
||||
{
|
||||
if (filterModelIndex.isValid())
|
||||
{
|
||||
Q_EMIT dataChanged(filterModelIndex, filterModelIndex);
|
||||
}
|
||||
};
|
||||
|
||||
AZ::TickBus::QueueFunction(emitDataChanged);
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::InitializeRecordUpdateJob()
|
||||
{
|
||||
AZ::JobManagerDesc desc;
|
||||
AZ::JobManagerThreadDesc threadDesc;
|
||||
for (size_t i = 0; i < AZStd::thread::hardware_concurrency(); ++i)
|
||||
{
|
||||
desc.m_workerThreads.push_back(threadDesc);
|
||||
}
|
||||
|
||||
// Check to ensure these have not already been initialized.
|
||||
AZ_Error("Material Browser", !m_jobManager && !m_jobCancelGroup && !m_jobContext, "MaterialBrowserFilterModel::InitializeRecordUpdateJob is being called again after it has already been initialized");
|
||||
m_jobManager = aznew AZ::JobManager(desc);
|
||||
m_jobCancelGroup = aznew AZ::JobCancelGroup();
|
||||
m_jobContext = aznew AZ::JobContext(*m_jobManager, *m_jobCancelGroup);
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::StartRecordUpdateJobs()
|
||||
{
|
||||
// Generate a list of file paths, assetId's, and asset browser model indices
|
||||
// This must be done on the main thread, otherwise it can lead to a crash when the tree view UI is being initialized
|
||||
AZStd::vector<MaterialBrowserRecordAssetBrowserData> files;
|
||||
GetRelativeFilePaths(files);
|
||||
|
||||
// Kick off the background process that will iterate over the list of file paths and update the material record map
|
||||
m_mainUpdateRecordJob = aznew MaterialBrowserUpdateJobCreator(this, files, m_jobContext);
|
||||
m_mainUpdateRecordJob->Start();
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::CancelRecordUpdateJobs()
|
||||
{
|
||||
m_jobContext->GetCancelGroup()->Cancel();
|
||||
m_jobContext->GetCancelGroup()->Reset();
|
||||
}
|
||||
|
||||
void MaterialBrowserFilterModel::ClearRecordMap()
|
||||
{
|
||||
CancelRecordUpdateJobs();
|
||||
m_materialRecordMap.clear();
|
||||
}
|
||||
|
||||
MaterialBrowserUpdateJobCreator::MaterialBrowserUpdateJobCreator(MaterialBrowserFilterModel* model, AZStd::vector<MaterialBrowserRecordAssetBrowserData>& files, AZ::JobContext* context /*= NULL*/)
|
||||
: Job(true, context)
|
||||
, m_files(files)
|
||||
, m_filterModel(model)
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialBrowserUpdateJobCreator::Process()
|
||||
{
|
||||
// Split the files to be processed evenly among threads
|
||||
int numJobs = GetContext()->GetJobManager().GetNumWorkerThreads();
|
||||
int materialsPerJob = (m_files.size() / numJobs) + 1;
|
||||
|
||||
for (auto it = m_files.begin(); it <= m_files.end(); it += materialsPerJob)
|
||||
{
|
||||
// Create a subset of the list of material files to be processed by another job
|
||||
auto start = it;
|
||||
auto end = it + materialsPerJob;
|
||||
if (end > m_files.end())
|
||||
{
|
||||
end = m_files.end();
|
||||
}
|
||||
AZStd::vector<MaterialBrowserRecordAssetBrowserData> subset(start, end);
|
||||
|
||||
if (subset.size() > 0)
|
||||
{
|
||||
AZ::Job* materialBrowserUpdateJob = aznew MaterialBrowserUpdateJob(m_filterModel, subset, GetContext());
|
||||
StartAsChild(materialBrowserUpdateJob);
|
||||
}
|
||||
}
|
||||
|
||||
WaitForChildren();
|
||||
|
||||
MaterialBrowserWidgetBus::Broadcast(&MaterialBrowserWidgetEvents::MaterialRecordUpdateFinished);
|
||||
}
|
||||
|
||||
MaterialBrowserUpdateJob::MaterialBrowserUpdateJob(MaterialBrowserFilterModel* model, AZStd::vector<MaterialBrowserRecordAssetBrowserData>& files, AZ::JobContext* context /*= NULL*/)
|
||||
: Job(true, context)
|
||||
, m_filterModel(model)
|
||||
, m_files(files)
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialBrowserUpdateJob::Process()
|
||||
{
|
||||
for (size_t i = 0; i < m_files.size(); ++i)
|
||||
{
|
||||
// Early out when the job is cancelled
|
||||
if (IsCancelled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
CMaterialBrowserRecord record;
|
||||
record.SetAssetBrowserData(m_files[i]);
|
||||
|
||||
// Get the writable status of the file, but don't update source control status until it is actually needed
|
||||
record.m_lastCachedFileAttributes = static_cast<ESccFileAttributes>(CFileUtil::GetAttributes(record.GetFullSourcePath().c_str(), false));
|
||||
|
||||
record.m_material = GetIEditor()->GetMaterialManager()->LoadMaterialWithFullSourcePath(record.GetRelativeFilePath().c_str(), record.GetFullSourcePath().c_str());
|
||||
m_filterModel->SetRecord(record);
|
||||
}
|
||||
}
|
||||
@ -1,240 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/parallel/containers/concurrent_unordered_map.h>
|
||||
#include <AzCore/std/parallel/atomic.h>
|
||||
#include <AzCore/Jobs/Job.h>
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Search/SearchWidget.h>
|
||||
#include <AzToolsFramework/MaterialBrowser/MaterialBrowserBus.h>
|
||||
#include <AzFramework/Asset/AssetCatalogBus.h>
|
||||
|
||||
|
||||
#include <ISourceControl.h>
|
||||
#include <QDateTime>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Job;
|
||||
class JobManager;
|
||||
class JobCancelGroup;
|
||||
class JobContext;
|
||||
}
|
||||
|
||||
class SubMaterialSearchFilter;
|
||||
class LevelMaterialSearchFilter;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Item class for browser.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct MaterialBrowserRecordAssetBrowserData
|
||||
{
|
||||
AZ::Data::AssetId assetId;
|
||||
AZStd::string relativeFilePath;
|
||||
AZStd::string fullSourcePath;
|
||||
QPersistentModelIndex modelIndex;
|
||||
QPersistentModelIndex filterModelIndex;
|
||||
};
|
||||
|
||||
class CMaterialBrowserRecord
|
||||
{
|
||||
public:
|
||||
CMaterialBrowserRecord()
|
||||
{
|
||||
InitializeSourceControlAttributes();
|
||||
}
|
||||
|
||||
CMaterialBrowserRecord(const CMaterialBrowserRecord &rhs)
|
||||
: m_material(rhs.m_material)
|
||||
, m_lastCachedSCCAttributes(rhs.m_lastCachedSCCAttributes)
|
||||
, m_lastCachedFileAttributes(rhs.m_lastCachedFileAttributes)
|
||||
, m_lastCheckedSCCAttributes(rhs.m_lastCheckedSCCAttributes)
|
||||
, m_assetBrowserData(rhs.m_assetBrowserData)
|
||||
{
|
||||
}
|
||||
|
||||
AZ::Data::AssetId GetAssetId() const { return m_assetBrowserData.assetId; }
|
||||
AZStd::string GetRelativeFilePath() const { return m_assetBrowserData.relativeFilePath; }
|
||||
AZStd::string GetFullSourcePath() const { return m_assetBrowserData.fullSourcePath; }
|
||||
QPersistentModelIndex GetModelIndex() const { return m_assetBrowserData.modelIndex; }
|
||||
QPersistentModelIndex GetFilterModelIndex() const { return m_assetBrowserData.filterModelIndex; }
|
||||
void SetAssetBrowserData(const MaterialBrowserRecordAssetBrowserData &assetBrowserData) { m_assetBrowserData = assetBrowserData; }
|
||||
void InitializeSourceControlAttributes()
|
||||
{
|
||||
// Force an update by setting the last update time to 1 / 1 / 1
|
||||
m_lastCachedSCCAttributes = AzToolsFramework::SourceControlFileInfo();
|
||||
m_lastCachedFileAttributes = SCC_FILE_ATTRIBUTE_INVALID;
|
||||
m_lastCheckedSCCAttributes = QDate(1, 1, 1).startOfDay();
|
||||
}
|
||||
public:
|
||||
_smart_ptr<CMaterial> m_material = nullptr;
|
||||
AzToolsFramework::SourceControlFileInfo m_lastCachedSCCAttributes;
|
||||
ESccFileAttributes m_lastCachedFileAttributes;
|
||||
QDateTime m_lastCheckedSCCAttributes;
|
||||
|
||||
private:
|
||||
MaterialBrowserRecordAssetBrowserData m_assetBrowserData;
|
||||
};
|
||||
Q_DECLARE_METATYPE(CMaterialBrowserRecord)
|
||||
|
||||
|
||||
//! MaterialBrowserSourceControlEvents
|
||||
//! This bus informs the material browser filter model
|
||||
//! when an ASYNC source control command has completed
|
||||
class MaterialBrowserSourceControlEvents
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
typedef AZStd::recursive_mutex MutexType;
|
||||
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; // there's only one listener
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; // theres only one listener
|
||||
virtual ~MaterialBrowserSourceControlEvents() {}
|
||||
|
||||
//! Signals the callback for the GetFileInfo source control op
|
||||
virtual void UpdateSourceControlFileInfoCallback(const AZ::Data::AssetId &assetId, const AzToolsFramework::SourceControlFileInfo& fileInfo) = 0;
|
||||
//! Updates the timestamp for when the source control status was last checked
|
||||
virtual void UpdateSourceControlLastCheckedTime(const AZ::Data::AssetId &assetId, const QDateTime &dateTime) = 0;
|
||||
};
|
||||
|
||||
using MaterialBrowserSourceControlBus = AZ::EBus<MaterialBrowserSourceControlEvents>;
|
||||
|
||||
//! MaterialBrowserWidgetEvents
|
||||
//! This bus is used to send events to the material browser widget
|
||||
class MaterialBrowserWidgetEvents
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
typedef AZStd::recursive_mutex MutexType;
|
||||
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; // there's only one listener
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; // theres only one listener
|
||||
virtual ~MaterialBrowserWidgetEvents() {}
|
||||
|
||||
//! Indicates that a material has finished being processed by the asset processor
|
||||
virtual void MaterialFinishedProcessing(_smart_ptr<CMaterial> material, const QPersistentModelIndex &filterModelIndex) = 0;
|
||||
|
||||
//! Indicates that a material has finished being added to the material browser
|
||||
virtual void MaterialAddFinished() = 0;
|
||||
|
||||
//! Indicates that the material record update for initially populating the material browser has finished
|
||||
virtual void MaterialRecordUpdateFinished() = 0;
|
||||
};
|
||||
|
||||
using MaterialBrowserWidgetBus = AZ::EBus<MaterialBrowserWidgetEvents>;
|
||||
|
||||
/**
|
||||
* Get the product material assetId for a given AssetBrowserEntry
|
||||
* If there is no valid product material, the material has not been processed, or there are multiple product materials
|
||||
* and thus there is not an individual material that can be assumed based on the source, an invalid assetId is returned
|
||||
* @param assetEntry An asset entry that may be a source or a product
|
||||
* @return The assetId of the product material.
|
||||
*/
|
||||
AZ::Data::AssetId GetMaterialProductAssetIdFromAssetBrowserEntry(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* assetEntry);
|
||||
|
||||
class MaterialBrowserFilterModel
|
||||
: public AzToolsFramework::AssetBrowser::AssetBrowserFilterModel
|
||||
, public MaterialBrowserSourceControlBus::Handler
|
||||
, public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler
|
||||
, public AzToolsFramework::MaterialBrowser::MaterialBrowserRequestBus::Handler
|
||||
, private AzFramework::AssetCatalogEventBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialBrowserFilterModel, AZ::SystemAllocator, 0);
|
||||
MaterialBrowserFilterModel(QObject* parent);
|
||||
~MaterialBrowserFilterModel();
|
||||
void UpdateRecord(const QModelIndex& filterModelIndex);
|
||||
void UpdateRecord(const MaterialBrowserRecordAssetBrowserData &assetBrowserData);
|
||||
void UpdateSourceControlFileInfoCallback(const AZ::Data::AssetId &assetId, const AzToolsFramework::SourceControlFileInfo& info) override;
|
||||
void UpdateSourceControlLastCheckedTime(const AZ::Data::AssetId &assetId, const QDateTime &dateTime) override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
bool TryGetRecordFromMaterial(_smart_ptr<CMaterial> material, CMaterialBrowserRecord& record) const;
|
||||
bool TryGetRecordFromAssetId(const AZ::Data::AssetId &assetId, CMaterialBrowserRecord& record) const;
|
||||
void SetRecord(const CMaterialBrowserRecord& record);
|
||||
void SetSearchFilter(const AzToolsFramework::AssetBrowser::SearchWidget* searchWidget);
|
||||
void StartRecordUpdateJobs();
|
||||
void CancelRecordUpdateJobs();
|
||||
void ClearRecordMap();
|
||||
void GetRelativeFilePaths(AZStd::vector<MaterialBrowserRecordAssetBrowserData> &files) const;
|
||||
QModelIndex GetIndexFromMaterial(_smart_ptr<CMaterial> material) const;
|
||||
QModelIndex GetFilterModelIndex(const AZ::Data::AssetId &assetId) const;
|
||||
|
||||
// AssetBrowserModelNotificationBus event handlers
|
||||
void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override;
|
||||
|
||||
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
|
||||
// MaterialBrowserRequestBus
|
||||
bool HasRecord(const AZ::Data::AssetId& assetId) override;
|
||||
bool IsMultiMaterial(const AZ::Data::AssetId& assetId) override;
|
||||
|
||||
void ShowOnlyLevelMaterials(bool levelOnly, bool invalidateFilterNow = false);
|
||||
|
||||
public Q_SLOTS:
|
||||
void SearchFilterUpdated();
|
||||
|
||||
private:
|
||||
void GetRelativeFilePathsRecursive(AZStd::vector<MaterialBrowserRecordAssetBrowserData> &files, const MaterialBrowserFilterModel* model, const QModelIndex &parent = QModelIndex()) const;
|
||||
bool TryGetFilterModelIndexRecursive(QModelIndex &filterModelIndex, const AZ::Data::AssetId &assetId, const MaterialBrowserFilterModel* model, const QModelIndex &parent = QModelIndex()) const;
|
||||
void QueueDataChangedEvent(const QPersistentModelIndex &filterModelIndex);
|
||||
AZStd::concurrent_unordered_map<AZ::Data::AssetId, CMaterialBrowserRecord> m_materialRecordMap;
|
||||
QVector<QPixmap> m_imageList;
|
||||
AzToolsFramework::AssetBrowser::FilterConstType m_assetTypeFilter;
|
||||
SubMaterialSearchFilter* m_subMaterialSearchFilter;
|
||||
LevelMaterialSearchFilter* m_levelMaterialSearchFilter;
|
||||
const AzToolsFramework::AssetBrowser::SearchWidget* m_searchWidget;
|
||||
|
||||
void InitializeRecordUpdateJob();
|
||||
AZ::JobManager* m_jobManager = nullptr;
|
||||
AZ::JobCancelGroup* m_jobCancelGroup = nullptr;
|
||||
AZ::JobContext* m_jobContext = nullptr;
|
||||
AZ::Job* m_mainUpdateRecordJob = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Job that walks through a MaterialBrowserFilterModel to generate a list of files,
|
||||
* then divides the list amongst child jobs for processing
|
||||
*/
|
||||
class MaterialBrowserUpdateJobCreator
|
||||
: public AZ::Job
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialBrowserUpdateJobCreator, AZ::ThreadPoolAllocator, 0);
|
||||
|
||||
MaterialBrowserUpdateJobCreator(MaterialBrowserFilterModel* model, AZStd::vector<MaterialBrowserRecordAssetBrowserData>& files, AZ::JobContext* context = nullptr);
|
||||
void Process() override;
|
||||
private:
|
||||
MaterialBrowserFilterModel* m_filterModel;
|
||||
AZStd::vector<MaterialBrowserRecordAssetBrowserData> m_files;
|
||||
};
|
||||
|
||||
/**
|
||||
* Job that walks through a list of material files, loads them, and then populates
|
||||
* the MaterialBrowserFilterModel's map of material data
|
||||
*/
|
||||
class MaterialBrowserUpdateJob
|
||||
: public AZ::Job
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialBrowserUpdateJob, AZ::ThreadPoolAllocator, 0);
|
||||
|
||||
MaterialBrowserUpdateJob(MaterialBrowserFilterModel* model, AZStd::vector<MaterialBrowserRecordAssetBrowserData> &files, AZ::JobContext* context = nullptr);
|
||||
void Process() override;
|
||||
private:
|
||||
MaterialBrowserFilterModel* m_filterModel;
|
||||
AZStd::vector<MaterialBrowserRecordAssetBrowserData> m_files;
|
||||
};
|
||||
|
||||
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "MaterialBrowserSearchFilters.h"
|
||||
|
||||
// Editor
|
||||
#include "MaterialBrowserFilterModel.h"
|
||||
#include "Material.h"
|
||||
|
||||
|
||||
SubMaterialSearchFilter::SubMaterialSearchFilter(const MaterialBrowserFilterModel* filterModel)
|
||||
: m_filterModel(filterModel)
|
||||
{
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::SetFilterPropagation(AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::PropagateDirection::Down);
|
||||
}
|
||||
|
||||
void SubMaterialSearchFilter::SetFilterString(const QString& filterString)
|
||||
{
|
||||
m_filterString = filterString;
|
||||
}
|
||||
|
||||
QString SubMaterialSearchFilter::GetNameInternal() const
|
||||
{
|
||||
return "SubMaterialSearchFilter";
|
||||
}
|
||||
|
||||
bool SubMaterialSearchFilter::MatchInternal(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
|
||||
{
|
||||
// All entries match if there is no search string
|
||||
if (m_filterString.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_filterModel)
|
||||
{
|
||||
// Get the product material for the given asset browser entry
|
||||
AZ::Data::AssetId assetId = GetMaterialProductAssetIdFromAssetBrowserEntry(entry);
|
||||
if (assetId.IsValid())
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
bool found = m_filterModel->TryGetRecordFromAssetId(assetId, record);
|
||||
if (found)
|
||||
{
|
||||
// If there is a valid product material, check to see if any of its sub-materials match the search string
|
||||
if (record.m_material)
|
||||
{
|
||||
for (int i = 0; i < record.m_material->GetSubMaterialCount(); ++i)
|
||||
{
|
||||
CMaterial* subMaterial = record.m_material->GetSubMaterial(i);
|
||||
if (subMaterial)
|
||||
{
|
||||
// If any of the product sub-materials matches the string, return true for this entry
|
||||
if (subMaterial->GetName().contains(m_filterString, Qt::CaseInsensitive))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
LevelMaterialSearchFilter::LevelMaterialSearchFilter(const MaterialBrowserFilterModel* filterModel)
|
||||
: m_filterModel(filterModel)
|
||||
{
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::SetFilterPropagation(AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::PropagateDirection::Down);
|
||||
}
|
||||
|
||||
QString LevelMaterialSearchFilter::GetNameInternal() const
|
||||
{
|
||||
return "LoadedMaterialSearchFilter";
|
||||
}
|
||||
|
||||
void LevelMaterialSearchFilter::CacheLoadedMaterials()
|
||||
{
|
||||
m_localMap.clear();
|
||||
|
||||
AZStd::vector<IRenderNode*> foundRenderNodes;
|
||||
unsigned int numFoundObjects = 0;
|
||||
|
||||
numFoundObjects = GetIEditor()->Get3DEngine()->GetObjectsByFlags(0);
|
||||
foundRenderNodes.resize(numFoundObjects, nullptr);
|
||||
GetIEditor()->Get3DEngine()->GetObjectsByFlags(0, foundRenderNodes.data());
|
||||
|
||||
AZStd::vector<_smart_ptr<IMaterial>> materials;
|
||||
materials.reserve(foundRenderNodes.size());
|
||||
for (IRenderNode* renderNode : foundRenderNodes)
|
||||
{
|
||||
renderNode->GetMaterials(materials);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < materials.size(); ++i)
|
||||
{
|
||||
if (materials[i])
|
||||
{
|
||||
m_localMap[materials[i]->GetName()] = materials[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LevelMaterialSearchFilter::MatchInternal(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
|
||||
{
|
||||
// All entries match if show level materials isn't selected
|
||||
if (!m_onlyShowLevelMaterials)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the product material for the given asset browser entry
|
||||
AZ::Data::AssetId assetId = GetMaterialProductAssetIdFromAssetBrowserEntry(entry);
|
||||
if (assetId.IsValid() && m_filterModel)
|
||||
{
|
||||
CMaterialBrowserRecord record;
|
||||
bool found = m_filterModel->TryGetRecordFromAssetId(assetId, record);
|
||||
if (found && record.m_material)
|
||||
{
|
||||
// If there is a valid product material, check to see if it is used by the level
|
||||
return m_localMap.find(record.m_material->GetName()) != m_localMap.end();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <Material/moc_MaterialBrowserSearchFilters.cpp>
|
||||
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
|
||||
#include <QHash>
|
||||
#endif
|
||||
|
||||
class MaterialBrowserFilterModel;
|
||||
|
||||
//! Filter that checks the name of each sub-material in a material to see if it contains the filter string
|
||||
class SubMaterialSearchFilter
|
||||
: public AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SubMaterialSearchFilter(const MaterialBrowserFilterModel* filterModel);
|
||||
~SubMaterialSearchFilter() override = default;
|
||||
|
||||
void SetFilterString(const QString& filterString);
|
||||
|
||||
protected:
|
||||
QString GetNameInternal() const override;
|
||||
bool MatchInternal(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const override;
|
||||
|
||||
private:
|
||||
bool TextMatchesFilter(const QString &text) const;
|
||||
QString m_filterString = "";
|
||||
const MaterialBrowserFilterModel* m_filterModel = nullptr;
|
||||
};
|
||||
|
||||
class LevelMaterialSearchFilter
|
||||
: public AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LevelMaterialSearchFilter(const MaterialBrowserFilterModel* filterModel);
|
||||
~LevelMaterialSearchFilter() override = default;
|
||||
|
||||
void ShowOnlyLevelMaterials(bool onlyLevel) { m_onlyShowLevelMaterials = onlyLevel; }
|
||||
|
||||
void CacheLoadedMaterials();
|
||||
|
||||
protected:
|
||||
QString GetNameInternal() const override;
|
||||
bool MatchInternal(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const override;
|
||||
|
||||
private:
|
||||
bool m_onlyShowLevelMaterials = false;
|
||||
const MaterialBrowserFilterModel* m_filterModel = nullptr;
|
||||
using MaterialMap = QHash<QString, _smart_ptr<IMaterial> >;
|
||||
MaterialMap m_localMap;
|
||||
};
|
||||
@ -1,23 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="/MaterialBrowser">
|
||||
<file>images/material_browser_00.png</file>
|
||||
<file>images/material_browser_01.png</file>
|
||||
<file>images/material_browser_02.png</file>
|
||||
<file>images/material_browser_03.png</file>
|
||||
<file>images/material_00.png</file>
|
||||
<file>images/material_01.png</file>
|
||||
<file>images/material_02.png</file>
|
||||
<file>images/material_03.png</file>
|
||||
<file>images/material_04.png</file>
|
||||
<file>images/material_05.png</file>
|
||||
<file>images/material_06.png</file>
|
||||
<file>images/material_07.png</file>
|
||||
<file>images/filestatus_00.png</file>
|
||||
<file>images/filestatus_01.png</file>
|
||||
<file>images/filestatus_02.png</file>
|
||||
<file>images/filestatus_03.png</file>
|
||||
<file>images/filestatus_04.png</file>
|
||||
<file>images/filestatus_05.png</file>
|
||||
<file>images/filestatus_06.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@ -1,372 +0,0 @@
|
||||
/*
|
||||
* 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 "MaterialHelpers.h"
|
||||
|
||||
namespace MaterialHelpers
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static void ParsePublicParamsScript(const char* sUIScript, IVariable* pVar)
|
||||
{
|
||||
string uiscript = sUIScript;
|
||||
string element[3];
|
||||
int p1 = 0;
|
||||
string itemToken = uiscript.Tokenize(";", p1);
|
||||
while (!itemToken.empty())
|
||||
{
|
||||
int nElements = 0;
|
||||
int p2 = 0;
|
||||
string token = itemToken.Tokenize(" \t\r\n=", p2);
|
||||
while (!token.empty())
|
||||
{
|
||||
element[nElements++] = token;
|
||||
if (nElements == 2)
|
||||
{
|
||||
element[nElements] = itemToken.substr(p2);
|
||||
element[nElements].Trim(" =\t\"");
|
||||
break;
|
||||
}
|
||||
token = itemToken.Tokenize(" \t\r\n=", p2);
|
||||
}
|
||||
|
||||
float minLimit, maxLimit;
|
||||
pVar->GetLimits(minLimit, maxLimit);
|
||||
|
||||
if (azstricmp(element[1], "UIWidget") == 0)
|
||||
{
|
||||
if (azstricmp(element[2], "Color") == 0)
|
||||
{
|
||||
pVar->SetDataType(IVariable::DT_COLOR);
|
||||
}
|
||||
}
|
||||
else if (azstricmp(element[1], "UIHelp") == 0)
|
||||
{
|
||||
string help = element[2];
|
||||
help.replace("\\n", "\n");
|
||||
pVar->SetDescription(help);
|
||||
}
|
||||
else if (azstricmp(element[1], "UIName") == 0)
|
||||
{
|
||||
pVar->SetHumanName(element[2].c_str());
|
||||
}
|
||||
else if (azstricmp(element[1], "UIMin") == 0)
|
||||
{
|
||||
pVar->SetLimits(atof(element[2]), maxLimit);
|
||||
}
|
||||
else if (azstricmp(element[1], "UIMax") == 0)
|
||||
{
|
||||
pVar->SetLimits(minLimit, atof(element[2]));
|
||||
}
|
||||
else if (azstricmp(element[1], "UIStep") == 0)
|
||||
{
|
||||
}
|
||||
|
||||
itemToken = uiscript.Tokenize(";", p1);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static void AddRealNameToDescription(IVariable* pIVar, const SShaderParam* pParam)
|
||||
{
|
||||
// In order to help the user discover the true names of parameters, info they need using certain script functions,
|
||||
// we embed the real parameter name in the description.
|
||||
QString description = pIVar->GetDescription();
|
||||
if (!description.isEmpty())
|
||||
{
|
||||
description += "\n";
|
||||
}
|
||||
description += "(Script Param Name = ";
|
||||
description += pParam->m_Name.c_str();
|
||||
description += ")";
|
||||
pIVar->SetDescription(description);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVarBlock* GetPublicVars(SInputShaderResources& pShaderResources)
|
||||
{
|
||||
if (pShaderResources.m_ShaderParams.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CVarBlock* pPublicVars = new CVarBlock;
|
||||
for (int i = 0; i < pShaderResources.m_ShaderParams.size(); i++)
|
||||
{
|
||||
IVariable* pIVar = NULL;
|
||||
SShaderParam* pParam = &pShaderResources.m_ShaderParams[i];
|
||||
|
||||
switch (pParam->m_Type)
|
||||
{
|
||||
case eType_BYTE:
|
||||
pIVar = new CVariable<int>(pParam->m_Value.m_Byte);
|
||||
break;
|
||||
case eType_SHORT:
|
||||
pIVar = new CVariable<int>(pParam->m_Value.m_Short);
|
||||
break;
|
||||
case eType_INT:
|
||||
pIVar = new CVariable<int>(pParam->m_Value.m_Int);
|
||||
break;
|
||||
case eType_FLOAT:
|
||||
pIVar = new CVariable<float>(pParam->m_Value.m_Float);
|
||||
break;
|
||||
/* case eType_STRING:
|
||||
pIVar = new CVariable<string>(pParam->m_Value.m_String);
|
||||
break; */
|
||||
case eType_FCOLOR:
|
||||
pIVar = new CVariable<Vec3>(Vec3(pParam->m_Value.m_Color[0], pParam->m_Value.m_Color[1], pParam->m_Value.m_Color[2]));
|
||||
pIVar->SetDataType(IVariable::DT_COLOR);
|
||||
break;
|
||||
case eType_FCOLORA:
|
||||
pIVar = new CVariable<Vec4>(Vec4(pParam->m_Value.m_Color[0], pParam->m_Value.m_Color[1], pParam->m_Value.m_Color[2], pParam->m_Value.m_Color[3]));
|
||||
pIVar->SetDataType(IVariable::DT_COLORA);
|
||||
break;
|
||||
case eType_VECTOR:
|
||||
pIVar = new CVariable<Vec3>(Vec3(pParam->m_Value.m_Vector[0], pParam->m_Value.m_Vector[1], pParam->m_Value.m_Vector[2]));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pIVar)
|
||||
{
|
||||
pIVar->SetName(pParam->m_Name.c_str());
|
||||
pPublicVars->AddVariable(pIVar);
|
||||
|
||||
if (pParam->m_Script.size())
|
||||
{
|
||||
ParsePublicParamsScript(pParam->m_Script.c_str(), pIVar);
|
||||
}
|
||||
|
||||
AddRealNameToDescription(pIVar, pParam);
|
||||
}
|
||||
}
|
||||
|
||||
return pPublicVars;
|
||||
}
|
||||
|
||||
void SetPublicVars(CVarBlock* pPublicVars, SInputShaderResources& pInputShaderResources)
|
||||
{
|
||||
assert(pPublicVars);
|
||||
|
||||
if (pInputShaderResources.m_ShaderParams.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int numVars = pPublicVars->GetNumVariables();
|
||||
|
||||
for (int i = 0; i < numVars; i++)
|
||||
{
|
||||
if (i >= numVars)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
IVariable* pVar = pPublicVars->GetVariable(i);
|
||||
SShaderParam* pParam = NULL;
|
||||
for (int j = 0; j < pInputShaderResources.m_ShaderParams.size(); j++)
|
||||
{
|
||||
if (QString::compare(pVar->GetName(), pInputShaderResources.m_ShaderParams[j].m_Name.c_str()) == 0)
|
||||
{
|
||||
pParam = &pInputShaderResources.m_ShaderParams[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pParam)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (pParam->m_Type)
|
||||
{
|
||||
case eType_BYTE:
|
||||
if (pVar->GetType() == IVariable::INT)
|
||||
{
|
||||
int val = 0;
|
||||
pVar->Get(val);
|
||||
pParam->m_Value.m_Byte = val;
|
||||
}
|
||||
break;
|
||||
case eType_SHORT:
|
||||
if (pVar->GetType() == IVariable::INT)
|
||||
{
|
||||
int val = 0;
|
||||
pVar->Get(val);
|
||||
pParam->m_Value.m_Short = val;
|
||||
}
|
||||
break;
|
||||
case eType_INT:
|
||||
if (pVar->GetType() == IVariable::INT)
|
||||
{
|
||||
int val = 0;
|
||||
pVar->Get(val);
|
||||
pParam->m_Value.m_Int = val;
|
||||
}
|
||||
break;
|
||||
case eType_FLOAT:
|
||||
if (pVar->GetType() == IVariable::FLOAT)
|
||||
{
|
||||
float val = 0;
|
||||
pVar->Get(val);
|
||||
pParam->m_Value.m_Float = val;
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case eType_STRING:
|
||||
if (pVar->GetType() == IVariable::STRING)
|
||||
{
|
||||
CString str;
|
||||
int val = 0;
|
||||
pVar->Get(val);
|
||||
pParam->m_Value.m_Byte = val;
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case eType_FCOLOR:
|
||||
case eType_FCOLORA:
|
||||
if (pVar->GetType() == IVariable::VECTOR4 && (pVar->GetDataType() == IVariable::DT_COLOR || pVar->GetDataType() == IVariable::DT_COLORA))
|
||||
{
|
||||
Vec4 val(0, 0, 0, 0);
|
||||
pVar->Get(val);
|
||||
pParam->m_Value.m_Color[0] = val.x;
|
||||
pParam->m_Value.m_Color[1] = val.y;
|
||||
pParam->m_Value.m_Color[2] = val.z;
|
||||
pParam->m_Value.m_Color[3] = val.w;
|
||||
}
|
||||
else if (pVar->GetType() == IVariable::VECTOR && (pVar->GetDataType() == IVariable::DT_COLOR || pVar->GetDataType() == IVariable::DT_COLORA))
|
||||
{
|
||||
Vec3 val(0, 0, 0);
|
||||
pVar->Get(val);
|
||||
pParam->m_Value.m_Color[0] = val.x;
|
||||
pParam->m_Value.m_Color[1] = val.y;
|
||||
pParam->m_Value.m_Color[2] = val.z;
|
||||
}
|
||||
break;
|
||||
case eType_VECTOR:
|
||||
if (pVar->GetType() == IVariable::VECTOR)
|
||||
{
|
||||
Vec3 val(0, 0, 0);
|
||||
pVar->Get(val);
|
||||
pParam->m_Value.m_Vector[0] = val.x;
|
||||
pParam->m_Value.m_Vector[1] = val.y;
|
||||
pParam->m_Value.m_Vector[2] = val.z;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetPublicVars(CVarBlock* pPublicVars, SInputShaderResources& pInputShaderResources, IRenderShaderResources* pRenderShaderResources, IShader* pShader)
|
||||
{
|
||||
SetPublicVars(pPublicVars, pInputShaderResources);
|
||||
|
||||
// Set shader params.
|
||||
if (pRenderShaderResources)
|
||||
{
|
||||
pRenderShaderResources->SetShaderParams(&pInputShaderResources, pShader);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVarBlock* GetShaderGenParamsVars(IShader* pShader, uint64 nShaderGenMask)
|
||||
{
|
||||
IShader* pTemplShader = pShader;
|
||||
if (!pTemplShader)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SShaderGen* pShaderGen = pTemplShader->GetGenerationParams();
|
||||
if (!pShaderGen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CVarBlock* pBlock = new CVarBlock;
|
||||
for (int i = 0; i < pShaderGen->m_BitMask.size(); i++)
|
||||
{
|
||||
SShaderGenBit* pGenBit = pShaderGen->m_BitMask[i];
|
||||
if (pGenBit->m_Flags & SHGF_HIDDEN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!pGenBit->m_ParamProp.empty())
|
||||
{
|
||||
CVariable<bool>* pVar = new CVariable<bool>;
|
||||
pBlock->AddVariable(pVar);
|
||||
pVar->SetName(pGenBit->m_ParamProp.c_str());
|
||||
*pVar = (pGenBit->m_Mask & nShaderGenMask) != 0;
|
||||
pVar->SetDescription(pGenBit->m_ParamDesc.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// make sure if no valid generation parameters to not create new tab
|
||||
if (!pBlock->GetVarsCount())
|
||||
{
|
||||
SAFE_DELETE(pBlock);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
return pBlock;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint64 SetShaderGenParamsVars(IShader* pShader, CVarBlock* pBlock)
|
||||
{
|
||||
IShader* pTemplShader = pShader;
|
||||
if (!pTemplShader)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SShaderGen* pShaderGen = pTemplShader->GetGenerationParams();
|
||||
if (!pShaderGen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64 nGenMask = 0;
|
||||
|
||||
for (int i = 0; i < pShaderGen->m_BitMask.size(); i++)
|
||||
{
|
||||
SShaderGenBit* pGenBit = pShaderGen->m_BitMask[i];
|
||||
if (pGenBit->m_Flags & SHGF_HIDDEN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pGenBit->m_ParamProp.empty())
|
||||
{
|
||||
IVariable* pVar = pBlock->FindVariable(pGenBit->m_ParamProp.c_str());
|
||||
if (!pVar)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool bFlagOn = false;
|
||||
pVar->Get(bFlagOn);
|
||||
if (bFlagOn)
|
||||
{
|
||||
nGenMask |= pGenBit->m_Mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nGenMask;
|
||||
}
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Material.h"
|
||||
|
||||
namespace MaterialHelpers
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Get public parameters of material in variable block.
|
||||
CVarBlock* GetPublicVars(SInputShaderResources& pShaderResources);
|
||||
|
||||
//! Sets variable block of public shader parameters.
|
||||
//! VarBlock must be in same format as returned by GetPublicVars().
|
||||
void SetPublicVars(CVarBlock* pPublicVars, SInputShaderResources& pInputShaderResources);
|
||||
void SetPublicVars(CVarBlock* pPublicVars, SInputShaderResources& pInputShaderResources, IRenderShaderResources* pRenderShaderResources, IShader* pShader);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVarBlock* GetShaderGenParamsVars(IShader* pShader, uint64 nShaderGenMask);
|
||||
uint64 SetShaderGenParamsVars(IShader* pShader, CVarBlock* pBlock);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// [Shader System TO DO] change the usage of these functions to retrieve by slot name
|
||||
inline EEfResTextures FindTexSlot(const char* texName) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().FindTexSlot(texName); }
|
||||
inline const char* FindTexName(EEfResTextures texSlot) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().FindTexName(texSlot); }
|
||||
inline const char* LookupTexName(EEfResTextures texSlot) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().LookupTexName(texSlot); }
|
||||
inline const char* LookupTexDesc(EEfResTextures texSlot) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().LookupTexDesc(texSlot); }
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Adjustable means that the slot is not virtual, i.e. using a sub-channel from another
|
||||
// slot (for example - smoothness that uses the normal's alpha)
|
||||
inline bool IsAdjustableTexSlot(EEfResTextures texSlot) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().IsAdjustableTexSlot(texSlot); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline void SetTexModFromXml(SEfTexModificator& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetTexModFromXml(pShaderResources, node); }
|
||||
inline void SetXmlFromTexMod(const SEfTexModificator& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromTexMod(pShaderResources, node); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline void SetTexturesFromXml(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetTexturesFromXml(pShaderResources, node); }
|
||||
inline void SetXmlFromTextures( SInputShaderResources& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromTextures(pShaderResources, node); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline void SetVertexDeformFromXml(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetVertexDeformFromXml(pShaderResources, node); }
|
||||
inline void SetXmlFromVertexDeform(const SInputShaderResources& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromVertexDeform(pShaderResources, node); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline void SetLightingFromXml(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetLightingFromXml(pShaderResources, node); }
|
||||
inline void SetXmlFromLighting(const SInputShaderResources& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromLighting(pShaderResources, node); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline void SetShaderParamsFromXml(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetShaderParamsFromXml(pShaderResources, node); }
|
||||
inline void SetXmlFromShaderParams(const SInputShaderResources& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromShaderParams(pShaderResources, node); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline void MigrateXmlLegacyData(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().MigrateXmlLegacyData(pShaderResources, node); }
|
||||
}
|
||||
@ -1,834 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
@ -1,164 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALIMAGELISTCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALIMAGELISTCTRL_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "Controls/ImageListCtrl.h"
|
||||
#include <QAbstractListModel>
|
||||
#include "Material.h"
|
||||
#include "IRenderer.h" // IAsyncTextureCompileListener
|
||||
#include "IResourceCompilerHelper.h"
|
||||
#include <AzFramework/Asset/AssetCatalogBus.h>
|
||||
|
||||
#include <QScopedPointer>
|
||||
#include <QPointer>
|
||||
#endif
|
||||
|
||||
class MaterialPreviewModelView;
|
||||
class MaterialBrowserWidget;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CMaterialImageListCtrl
|
||||
: public CImageListCtrl
|
||||
, public ISystemEventListener
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum class ModelType
|
||||
{
|
||||
Default,
|
||||
Box,
|
||||
Sphere,
|
||||
Teapot,
|
||||
Plane
|
||||
};
|
||||
|
||||
enum MenuAction
|
||||
{
|
||||
ModelDefault = 0,
|
||||
ModelPlane,
|
||||
ModelBox,
|
||||
ModelSphere,
|
||||
ModelTeapot,
|
||||
// Context menu actions that are common to both the material browser and the preview swatches
|
||||
// are handled by the same switch statement, so they need to be unique. This sets the starting point for the common actions
|
||||
MaterialBrowserWidgetActionsStart
|
||||
};
|
||||
|
||||
CMaterialImageListCtrl(QWidget* parent = nullptr);
|
||||
~CMaterialImageListCtrl();
|
||||
|
||||
void setModel(QAbstractItemModel* model) override;
|
||||
|
||||
void EnableAutoRefresh(bool autoRefreshState, unsigned int refreshInterval);
|
||||
void SelectMaterial(CMaterial* pMaterial);
|
||||
void LoadModel();
|
||||
void SetMaterialBrowserWidget(MaterialBrowserWidget* materialBrowserWidget){ m_materialBrowserWidget = materialBrowserWidget; }
|
||||
// ISystemEventListener
|
||||
// Due to the material editor working on a ProcessEvents -> Timer based system, rather than the OnIdle update event loops
|
||||
// that the other editor windows use, make sure that when the editor loses focus that the Material Editor itself loses focus.
|
||||
// This will pause updates/renderings in the material editor when it does not have focus.
|
||||
// This prevents certain materials from re-creating themselves and eventually overflowing a few resource buffers.
|
||||
// The main window cleans up those resources during its main update, which is bypassed when the window does not have focus.
|
||||
virtual void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam);
|
||||
// ~ISystemEventListener
|
||||
|
||||
// Override resizeEvent and use this const to rate limit it such that it only fires RESIZE_TIMEOUT ms after resizing stops
|
||||
static const int RESIZE_TIMEOUT = 100;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
public slots:
|
||||
void ModelDataChanged(const QModelIndex& index);
|
||||
void ResizeTimeout();
|
||||
protected:
|
||||
void OnCreate();
|
||||
void OnDestroy();
|
||||
|
||||
void contextMenuEvent(QContextMenuEvent* event) override;
|
||||
void showEvent(QShowEvent* event) override;
|
||||
void updateGeometries() override;
|
||||
|
||||
private:
|
||||
void GenerateImage(const QModelIndex& index);
|
||||
void GenerateAllImages();
|
||||
void UpdateLargePreview();
|
||||
|
||||
QScopedPointer<MaterialPreviewModelView> m_largePreviewCtrl; // Used to draw the main 3D preview viewport for the selected sub-material
|
||||
_smart_ptr<CMaterial> m_largePreviewMaterial;
|
||||
_smart_ptr<CMaterial> m_tempTerrainMaterial;
|
||||
QScopedPointer<MaterialPreviewModelView> m_renderCtrl; // Used to draw the swatches for all the sub-materials
|
||||
int m_nColor;
|
||||
bool m_updatingGeometries = false;
|
||||
ModelType m_modelType = ModelType::Default;
|
||||
MaterialBrowserWidget* m_materialBrowserWidget;
|
||||
QTimer* m_resizeTimer; // Used to stall a resizeEvent from firing until RESIZE_TIMEOUT ms have passed since resizing stopped
|
||||
};
|
||||
|
||||
class QMaterialImageListModel
|
||||
: public QAbstractListModel
|
||||
, public AzFramework::LegacyAssetEventBus::Handler
|
||||
{
|
||||
struct Item;
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum CustomRoles
|
||||
{
|
||||
PositionRole = Qt::UserRole
|
||||
};
|
||||
|
||||
QMaterialImageListModel(QObject* parent = nullptr);
|
||||
~QMaterialImageListModel();
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
QModelIndex AddMaterial(CMaterial* pMaterial, void* pUserData = nullptr);
|
||||
void SetMaterial(int nItemIndex, CMaterial* pMaterial, void* pUserData = nullptr);
|
||||
QModelIndex FindMaterial(CMaterial* pMaterial);
|
||||
void InvalidateMaterial(CMaterial* pMaterial);
|
||||
void DeleteAllItems();
|
||||
|
||||
MaterialPreviewModelView* PreviewModelCtrl() const;
|
||||
void SetPreviewModelCtrl(MaterialPreviewModelView* ctrl);
|
||||
|
||||
CMaterial* MaterialFromIndex(QModelIndex index) const;
|
||||
void* UserDataFromIndex(QModelIndex index) const;
|
||||
|
||||
public slots:
|
||||
void GenerateImages();
|
||||
void GenerateImage(const QModelIndex& index);
|
||||
|
||||
protected:
|
||||
void GenerateImage(Item* pItem);
|
||||
Item* ItemFromIndex(QModelIndex index) const;
|
||||
|
||||
private slots:
|
||||
void ClearPreviewModelCtrl();
|
||||
|
||||
private:
|
||||
void OnFileChanged(AZStd::string assetPath) override;
|
||||
|
||||
private:
|
||||
_smart_ptr<CMaterial> m_pMatPreview;
|
||||
QPointer<MaterialPreviewModelView> m_renderCtrl;
|
||||
QVector<Item*> m_items;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALIMAGELISTCTRL_H
|
||||
@ -1,151 +0,0 @@
|
||||
/*
|
||||
* 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 "MaterialLibrary.h"
|
||||
|
||||
// Editor
|
||||
#include "BaseLibraryItem.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CMaterialLibrary implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CMaterialLibrary::Save()
|
||||
{
|
||||
return SaveLibrary("MaterialLibrary");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CMaterialLibrary::Load(const QString& filename)
|
||||
{
|
||||
if (filename.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SetFilename(filename);
|
||||
XmlNodeRef root = XmlHelpers::LoadXmlFromFile(filename.toUtf8().data());
|
||||
if (!root)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Serialize(root, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMaterialLibrary::Serialize([[maybe_unused]] XmlNodeRef& root, [[maybe_unused]] bool bLoading)
|
||||
{
|
||||
/*
|
||||
if (bLoading)
|
||||
{
|
||||
// Loading.
|
||||
CString name = GetName();
|
||||
root->getAttr( "Name",name );
|
||||
SetName( name );
|
||||
for (int i = 0; i < root->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef itemNode = root->getChild(i);
|
||||
CMaterial *material = new CMaterial(itemNode->getAttr("Name"));
|
||||
AddItem( material );
|
||||
CBaseLibraryItem::SerializeContext ctx( itemNode,bLoading );
|
||||
material->Serialize( ctx );
|
||||
}
|
||||
SetModified(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Saving.
|
||||
root->setAttr( "Name",GetName() );
|
||||
root->setAttr( "SandboxVersion",(const char*)GetIEditor()->GetFileVersion().ToFullString() );
|
||||
// Serialize prototypes.
|
||||
for (int i = 0; i < GetItemCount(); i++)
|
||||
{
|
||||
CMaterial *pMtl = (CMaterial*)GetItem(i);
|
||||
// Save materials with parents under thier parent xml node.
|
||||
if (pMtl->GetParent())
|
||||
continue;
|
||||
|
||||
XmlNodeRef itemNode = root->newChild( "Material" );
|
||||
CBaseLibraryItem::SerializeContext ctx( itemNode,bLoading );
|
||||
GetItem(i)->Serialize( ctx );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMaterialLibrary::AddItem(IDataBaseItem* item, bool bRegister)
|
||||
{
|
||||
CBaseLibraryItem* pLibItem = (CBaseLibraryItem*)item;
|
||||
// Check if item is already assigned to this library.
|
||||
if (pLibItem->GetLibrary() != this)
|
||||
{
|
||||
pLibItem->SetLibrary(this);
|
||||
if (bRegister)
|
||||
{
|
||||
m_pManager->RegisterItem(pLibItem);
|
||||
}
|
||||
m_items.push_back(pLibItem);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CMaterialLibrary::GetItem(int index)
|
||||
{
|
||||
assert(index >= 0 && index < m_items.size());
|
||||
return m_items[index];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMaterialLibrary::RemoveItem(IDataBaseItem* item)
|
||||
{
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
if (m_items[i] == item)
|
||||
{
|
||||
m_items.erase(m_items.begin() + i);
|
||||
SetModified();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CMaterialLibrary::FindItem(const QString& name)
|
||||
{
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
if (QString::compare(m_items[i]->GetName(), name, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
return m_items[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMaterialLibrary::RemoveAllItems()
|
||||
{
|
||||
AddRef();
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
// Clear library item.
|
||||
m_items[i]->SetLibrary(NULL);
|
||||
}
|
||||
m_items.clear();
|
||||
Release();
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALLIBRARY_H
|
||||
#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALLIBRARY_H
|
||||
#pragma once
|
||||
|
||||
#include "BaseLibrary.h"
|
||||
|
||||
/** Library of prototypes.
|
||||
*/
|
||||
class CRYEDIT_API CMaterialLibrary
|
||||
: public CBaseLibrary
|
||||
{
|
||||
public:
|
||||
CMaterialLibrary(IBaseLibraryManager* pManager)
|
||||
: CBaseLibrary(pManager) {};
|
||||
virtual bool Save();
|
||||
virtual bool Load(const QString& filename);
|
||||
virtual void Serialize(XmlNodeRef& node, bool bLoading);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CBaseLibrary override.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void AddItem(IDataBaseItem* item, bool bRegister = true);
|
||||
int GetItemCount() const { return m_items.size(); }
|
||||
IDataBaseItem* GetItem(int index);
|
||||
void RemoveItem(IDataBaseItem* item);
|
||||
void RemoveAllItems();
|
||||
IDataBaseItem* FindItem(const QString& name);
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
std::vector<CBaseLibraryItem*> m_items;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALLIBRARY_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,300 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include "BaseLibraryManager.h"
|
||||
#include "Material.h"
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <Include/IEditorMaterialManager.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/std/string/wildcard.h>
|
||||
#include <AzFramework/Asset/AssetCatalogBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzCore/std/parallel/mutex.h>
|
||||
#include <AzCore/std/parallel/binary_semaphore.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
|
||||
|
||||
class CMaterial;
|
||||
class CMaterialLibrary;
|
||||
class CMaterialHighlighter;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
struct Uuid;
|
||||
}
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace AssetBrowser
|
||||
{
|
||||
struct SourceFileOpenerDetails;
|
||||
typedef AZStd::vector<SourceFileOpenerDetails> SourceFileOpenerList;
|
||||
}
|
||||
}
|
||||
|
||||
enum EHighlightMode
|
||||
{
|
||||
eHighlight_Pick = BIT(0),
|
||||
eHighlight_Breakable = BIT(1),
|
||||
eHighlight_NoSurfaceType = BIT(2),
|
||||
eHighlight_All = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
/** Manages all entity prototypes and material libraries.
|
||||
*/
|
||||
class CRYEDIT_API CMaterialManager
|
||||
: public IEditorMaterialManager
|
||||
, public CBaseLibraryManager
|
||||
, public IMaterialManagerListener
|
||||
, protected AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
|
||||
, public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler
|
||||
, public AzFramework::AssetCatalogEventBus::Handler
|
||||
, public AzToolsFramework::EditorEvents::Bus::Handler
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
public:
|
||||
|
||||
//! Notification callback.
|
||||
typedef AZStd::function<void()> NotifyCallback;
|
||||
|
||||
CMaterialManager(CRegistrationContext& regCtx);
|
||||
~CMaterialManager();
|
||||
|
||||
void Set3DEngine();
|
||||
|
||||
// Clear all prototypes and material libraries.
|
||||
void ClearAll();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Materials.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Loads material.
|
||||
CMaterial* LoadMaterial(const QString& sMaterialName, bool bMakeIfNotFound = true);
|
||||
XmlNodeRef LoadXmlNode(const QString &fullSourcePath, const QString &relativeFilePath);
|
||||
//! Loads a material, avoiding a call to CMaterialManager::MaterialToFilename if the full path is already known
|
||||
CMaterial* LoadMaterialWithFullSourcePath(const QString& relativeFilePath, const QString& fullSourcePath, bool makeIfNotFound = true);
|
||||
virtual CMaterial* LoadMaterial(const char* sMaterialName, bool bMakeIfNotFound = true);
|
||||
virtual void OnRequestMaterial(_smart_ptr<IMaterial> pMaterial);
|
||||
// Creates a new material from a xml node.
|
||||
CMaterial* CreateMaterial(const QString& sMaterialName, const XmlNodeRef& node = XmlNodeRef(), int nMtlFlags = 0, unsigned long nLoadingFlags = 0);
|
||||
virtual CMaterial* CreateMaterial(const char* sMaterialName, const XmlNodeRef& node = XmlNodeRef(), int nMtlFlags = 0, unsigned long nLoadingFlags = 0);
|
||||
|
||||
// Duplicate material and do nothing more.
|
||||
CMaterial* DuplicateMaterial(const char* newName, CMaterial* pOriginal);
|
||||
|
||||
// Delete specified material, erases material file, and unassigns from all objects.
|
||||
virtual void DeleteMaterial(CMaterial* pMtl);
|
||||
virtual void RemoveMaterialFromDisk(const char* fileName);
|
||||
|
||||
|
||||
//! Export property manager to game.
|
||||
void Export(XmlNodeRef& node);
|
||||
int ExportLib(CMaterialLibrary* pLib, XmlNodeRef& libNode);
|
||||
|
||||
virtual void SetSelectedItem(IDataBaseItem* pItem);
|
||||
void SetCurrentMaterial(CMaterial* pMtl);
|
||||
//! Get currently active material.
|
||||
CMaterial* GetCurrentMaterial() const;
|
||||
|
||||
void SetCurrentFolder(const QString& folder);
|
||||
|
||||
// This material will be highlighted
|
||||
void SetHighlightedMaterial(CMaterial* pMtl);
|
||||
void GetHighlightColor(ColorF* color, float* intensity, int flags);
|
||||
void HighlightedMaterialChanged(CMaterial* pMtl);
|
||||
// highlightMask is a combination of EHighlightMode flags
|
||||
void SetHighlightMask(int highlightMask);
|
||||
int GetHighlightMask() const{ return m_highlightMask; }
|
||||
void SetMarkedMaterials(const std::vector<_smart_ptr<CMaterial> >& markedMaterials);
|
||||
void OnLoadShader(CMaterial* pMaterial);
|
||||
|
||||
//! Serialize property manager.
|
||||
virtual void Serialize(XmlNodeRef& node, bool bLoading);
|
||||
|
||||
virtual void SaveAllLibs();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IMaterialManagerListener implementation
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Called when material manager tries to load a material.
|
||||
virtual void OnCreateMaterial(_smart_ptr<IMaterial> pMaterial);
|
||||
virtual void OnDeleteMaterial(_smart_ptr<IMaterial> pMaterial);
|
||||
virtual bool IsCurrentMaterial(_smart_ptr<IMaterial> pMaterial) const;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Convert filename of material file into the name of the material.
|
||||
QString FilenameToMaterial(const QString& filename);
|
||||
|
||||
// Convert name of the material to the filename.
|
||||
QString MaterialToFilename(const QString& sMaterialName);
|
||||
|
||||
//! Get the full file path of the source material
|
||||
const AZ::Data::AssetType& GetMaterialAssetType();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Convert 3DEngine IMaterial to Editor's CMaterial pointer.
|
||||
CMaterial* FromIMaterial(_smart_ptr<IMaterial> pMaterial);
|
||||
|
||||
// Open File selection dialog to create a new material.
|
||||
CMaterial* SelectNewMaterial(int nMtlFlags, const char* sStartPath = NULL);
|
||||
|
||||
// Synchronize material between 3dsMax and editor.
|
||||
void SyncMaterialEditor();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void GotoMaterial(CMaterial* pMaterial);
|
||||
void GotoMaterial(_smart_ptr<IMaterial> pMaterial);
|
||||
|
||||
// Gather resources from the game material.
|
||||
static void GatherResources(_smart_ptr<IMaterial> pMaterial, CUsedResources& resources);
|
||||
|
||||
void Command_Create();
|
||||
void Command_CreateMulti();
|
||||
void Command_ConvertToMulti();
|
||||
void Command_Duplicate();
|
||||
void Command_Merge();
|
||||
void Command_Delete();
|
||||
void Command_AssignToSelection();
|
||||
void Command_ResetSelection();
|
||||
void Command_SelectAssignedObjects();
|
||||
void Command_SelectFromObject();
|
||||
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// protected AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
|
||||
void AddSourceFileOpeners(const char* fullSourceFileName, const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers) override;
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationsBus::Handler
|
||||
void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// AssetCatalogEventBus Functions
|
||||
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// EditorEventsBus Functions
|
||||
bool SkipEditorStartupUI() override;
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SaveDccMaterial(const AZStd::string& relativeDccMaterialPath);
|
||||
bool DccMaterialRequiresSave(const AZStd::string& relativeDccMaterialPath, const AZStd::string& fullSourcePath);
|
||||
void DccMaterialSourceControlCheck(const AZStd::string& relativeDccMaterialPath);
|
||||
void AddDccMaterialPath(const AZStd::string relativeDccMaterialPath);
|
||||
void TickSourceControl();
|
||||
void QueueSourceControlTick();
|
||||
|
||||
// Duplicate the source material and set it as a submaterial of the target material at subMaterialIndex. Returns true if successful.
|
||||
bool DuplicateAsSubMaterialAtIndex(CMaterial* pSourceMaterial, CMaterial* pTargetMaterial, int subMaterialIndex);
|
||||
// Generates a unique variant of the name of the source material to resolve name collisions with the names of the submaterials in the target material.
|
||||
void GenerateUniqueSubmaterialName(const CMaterial* pSourceMaterial, const CMaterial* pTargetMaterial, QString& uniqueSubmaterialName) const;
|
||||
|
||||
// Open save as dialog for saving materials.
|
||||
bool SelectSaveMaterial(QString& itemName, QString& fullPath, const char* defaultStartPath);
|
||||
|
||||
void OnEditorNotifyEvent(EEditorNotifyEvent event);
|
||||
|
||||
virtual CBaseLibraryItem* MakeNewItem();
|
||||
virtual CBaseLibrary* MakeNewLibrary();
|
||||
//! Root node where this library will be saved.
|
||||
virtual QString GetRootNodeName();
|
||||
//! Path to libraries in this manager.
|
||||
virtual QString GetLibsPath();
|
||||
virtual void ReportDuplicateItem(CBaseLibraryItem* pItem, CBaseLibraryItem* pOldItem);
|
||||
|
||||
void RegisterCommands(CRegistrationContext& regCtx);
|
||||
|
||||
void UpdateHighlightedMaterials();
|
||||
void AddForHighlighting(CMaterial* pMaterial);
|
||||
void RemoveFromHighlighting(CMaterial* pMaterial, int mask);
|
||||
int GetHighlightFlags(CMaterial* pMaterial) const;
|
||||
|
||||
// For material syncing with 3dsMax.
|
||||
void PickPreviewMaterial();
|
||||
void InitMatSender();
|
||||
|
||||
//! Reloads any registered materials that have been modified by the runtime.
|
||||
void ReloadDirtyMaterials();
|
||||
|
||||
protected:
|
||||
QString m_libsPath;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
// Currently selected (focused) material, in material browser.
|
||||
_smart_ptr<CMaterial> m_pCurrentMaterial;
|
||||
// current selected folder
|
||||
QString m_currentFolder;
|
||||
// List of materials selected in material browser tree.
|
||||
std::vector<_smart_ptr<CMaterial> > m_markedMaterials;
|
||||
// IMaterial is needed to not let 3Dengine release selected IMaterial
|
||||
_smart_ptr<IMaterial> m_pCurrentEngineMaterial;
|
||||
|
||||
// Paths of .dccmtl that might require saving. They will be fed to
|
||||
// DccMaterialSourceControlCheck() and if saving is required, they
|
||||
// will be added to m_dccMaterialSaveBuffer
|
||||
AZStd::vector<AZStd::string> m_sourceControlBuffer;
|
||||
AZStd::mutex m_sourceControlBufferMutex;
|
||||
AZStd::atomic_bool m_sourceControlFunctionQueued;
|
||||
|
||||
// Paths of .dccmtl that require saving. These paths have
|
||||
// gone through DccMaterialSourceControlCheck() and will
|
||||
// be saved by the dcc material save thread
|
||||
AZStd::vector<AZStd::string> m_dccMaterialSaveBuffer;
|
||||
AZStd::mutex m_dccMaterialSaveMutex;
|
||||
|
||||
// Material highlighting
|
||||
_smart_ptr<CMaterial> m_pHighlightMaterial;
|
||||
CMaterialHighlighter* m_pHighlighter;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
int m_highlightMask;
|
||||
|
||||
bool m_bHighlightingMaterial;
|
||||
|
||||
// Only begin processing .dccmtl filepaths once editor is ready
|
||||
// and we can display appropriate error messages
|
||||
bool m_bEditorUiReady;
|
||||
|
||||
// Only report source control error to the user once,
|
||||
// no need to spam them for every material
|
||||
bool m_bSourceControlErrorReported;
|
||||
|
||||
class CMaterialSender* m_MatSender;
|
||||
|
||||
private:
|
||||
CMaterial* LoadMaterialInternal(const QString &materialNameClear, const QString &fullSourcePath, const QString &relativeFilePath, bool bMakeIfNotFound);
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
AZ::Data::AssetType m_materialAssetType;
|
||||
AZ::Data::AssetType m_dccMaterialAssetType;
|
||||
|
||||
void StartDccMaterialSaveThread();
|
||||
void DccMaterialSaveThreadFunc();
|
||||
AZStd::thread m_dccMaterialSaveThread;
|
||||
AZStd::atomic_bool m_joinThreads;
|
||||
AZStd::binary_semaphore m_dccMaterialSaveSemaphore;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALMANAGER_H
|
||||
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "MaterialPreviewModelView.h"
|
||||
|
||||
|
||||
|
||||
MaterialPreviewModelView::MaterialPreviewModelView(QWidget* parent, bool enableIdleUpdate)
|
||||
: CPreviewModelView(parent)
|
||||
, m_enableIdleUpdate(enableIdleUpdate)
|
||||
{}
|
||||
|
||||
MaterialPreviewModelView::~MaterialPreviewModelView()
|
||||
{}
|
||||
|
||||
void MaterialPreviewModelView::SetCameraLookAt(float fRadiusScale, const Vec3& fromDir)
|
||||
{
|
||||
IStatObj* target = GetStaticModel();
|
||||
if (target)
|
||||
{
|
||||
Vec3 dir = fromDir.GetNormalized();
|
||||
|
||||
// Calculate the camera matrix
|
||||
Matrix34 tm = Matrix33::CreateRotationVDir(dir, 0);
|
||||
Vec3 translation = target->GetAABB().GetCenter() - dir * target->GetAABB().GetRadius() * fRadiusScale;
|
||||
tm.SetTranslation(translation);
|
||||
|
||||
// Convert it to a quaternion and move the viewport's camera
|
||||
QuatT quat(tm);
|
||||
CameraMoved(quat, true);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialPreviewModelView::SetMaterial(_smart_ptr<IMaterial> material)
|
||||
{
|
||||
IStatObj* staticModel = GetStaticModel();
|
||||
if (staticModel)
|
||||
{
|
||||
staticModel->SetMaterial(material);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialPreviewModelView::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
if (m_enableIdleUpdate)
|
||||
{
|
||||
CPreviewModelView::resizeEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialPreviewModelView::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case eNotify_OnIdleUpdate:
|
||||
{
|
||||
if (m_enableIdleUpdate)
|
||||
{
|
||||
Update();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "PreviewModelView.h"
|
||||
|
||||
class MaterialPreviewModelView
|
||||
: public CPreviewModelView
|
||||
{
|
||||
public:
|
||||
// set enableIdleUpdate to false if you don't want the view to update itself during
|
||||
// application idle notification (and resize events). That makes sense when this view
|
||||
// is only used to render into memory bitmaps. Note that the view has to been visible
|
||||
// for that, but can be somewhere of-screen.
|
||||
MaterialPreviewModelView(QWidget* parent, bool enableIdleUpdate = true);
|
||||
virtual ~MaterialPreviewModelView();
|
||||
void SetCameraLookAt(float fRadiusScale, const Vec3& fromDir);
|
||||
void SetMaterial(_smart_ptr<IMaterial> material);
|
||||
void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private:
|
||||
bool m_enableIdleUpdate;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Include/SandboxAPI.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
//! A component to reflect scriptable commands for materials in the Editor
|
||||
class MaterialPythonFuncsHandler
|
||||
: public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(MaterialPythonFuncsHandler, "{E437BCF2-DE71-43E1-A7EC-DD243EB41F0B}")
|
||||
|
||||
SANDBOX_API static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
// AZ::Component ...
|
||||
void Activate() override {}
|
||||
void Deactivate() override {}
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
@ -1,416 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
//AZCore
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
//CRY
|
||||
#include <ILogFile.h>
|
||||
#include <IMaterial.h>
|
||||
|
||||
//Editor
|
||||
#include <Settings.h>
|
||||
#include <IEditor.h>
|
||||
#include <IResourceSelectorHost.h>
|
||||
#include <Util/Variable.h>
|
||||
#include <Util/VariablePropertyType.h>
|
||||
#include <QViewport.h>
|
||||
#include <QViewportSettings.h>
|
||||
#include <DisplaySettings.h>
|
||||
|
||||
//EditorCommon
|
||||
#include <RenderHelpers/AxisHelper.h>
|
||||
|
||||
//Local
|
||||
#include "PreviewModelView.h"
|
||||
|
||||
//QT
|
||||
#include <qapplication.h>
|
||||
|
||||
|
||||
|
||||
CPreviewModelView::CPreviewModelView(QWidget* parent)
|
||||
: QViewport(parent, QViewport::StartupMode_Manual) // Manual since we need to set WA_DontCreateNativeAncestors before QViewport::Startup() creates the internal native window and propagates
|
||||
, m_Flags(0)
|
||||
, m_GridColor(150, 150, 150, 40)
|
||||
, m_BackgroundColor(0.5f, 0.5f, 0.5f)
|
||||
, m_TimeScale(1.0f)
|
||||
, m_PlayState(PlayState::NONE)
|
||||
, m_pStaticModel(nullptr)
|
||||
, m_PostUpdateCallback(nullptr)
|
||||
, m_ContextMenuCallback(nullptr)
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
// Don't propagate the nativeness up, as dockwidgets on macOS don't like it
|
||||
setAttribute(Qt::WA_DontCreateNativeAncestors);
|
||||
#endif
|
||||
Startup();
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//QViewport
|
||||
AddConsumer(this);
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//IEditorNotifyListener
|
||||
GetIEditor()->RegisterNotifyListener(this);
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
FocusOnScreen();//update the camera ...
|
||||
SetDefaultFlags();
|
||||
UpdateSettings();
|
||||
}
|
||||
|
||||
CPreviewModelView::~CPreviewModelView()
|
||||
{
|
||||
CRY_ASSERT(GetIEditor());
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//IEditorNotifyListener
|
||||
GetIEditor()->UnregisterNotifyListener(this);
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
ReleaseModel();
|
||||
}
|
||||
|
||||
|
||||
bool CPreviewModelView::IsFlagSet(PreviewModelViewFlag flag) const
|
||||
{
|
||||
CRY_ASSERT(flag < PreviewModelViewFlag::END_POSSIBLE_ITEMS);
|
||||
return (m_Flags & (1 << static_cast<unsigned int>(flag)));
|
||||
}
|
||||
|
||||
void CPreviewModelView::ToggleFlag(PreviewModelViewFlag flag)
|
||||
{
|
||||
CRY_ASSERT(flag < PreviewModelViewFlag::END_POSSIBLE_ITEMS);
|
||||
if (IsFlagSet(flag))
|
||||
{
|
||||
UnSetFlag(flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFlag(flag);
|
||||
}
|
||||
}
|
||||
|
||||
void CPreviewModelView::SetFlag(PreviewModelViewFlag flag)
|
||||
{
|
||||
CRY_ASSERT(flag < PreviewModelViewFlag::END_POSSIBLE_ITEMS);
|
||||
m_Flags |= (1 << static_cast<unsigned int>(flag));
|
||||
}
|
||||
|
||||
void CPreviewModelView::UnSetFlag(PreviewModelViewFlag flag)
|
||||
{
|
||||
CRY_ASSERT(flag < PreviewModelViewFlag::END_POSSIBLE_ITEMS);
|
||||
m_Flags &= ~(1 << static_cast<unsigned int>(flag));
|
||||
}
|
||||
|
||||
void CPreviewModelView::ResetPlaybackControls()
|
||||
{
|
||||
UnSetFlag(CPreviewModelView::PreviewModelViewFlag::LOOPING_PLAY);
|
||||
m_TimeScale = 1.0f;
|
||||
}
|
||||
|
||||
void CPreviewModelView::ResetBackgroundColor()
|
||||
{
|
||||
SetBackgroundColor(ColorF(0.5f, 0.5f, 0.5f));
|
||||
}
|
||||
|
||||
void CPreviewModelView::ResetGridColor()
|
||||
{
|
||||
SetGridColor(ColorF(150, 150, 150, 40));
|
||||
}
|
||||
|
||||
void CPreviewModelView::ResetCamera()
|
||||
{
|
||||
FocusOnScreen();
|
||||
}
|
||||
|
||||
void CPreviewModelView::ResetAll()
|
||||
{
|
||||
ResetPlaybackControls();
|
||||
ResetGridColor();
|
||||
ResetBackgroundColor();
|
||||
ReleaseModel();
|
||||
SetDefaultFlags();
|
||||
}
|
||||
|
||||
void CPreviewModelView::SetGridColor(ColorF color)
|
||||
{
|
||||
m_GridColor = color;
|
||||
}
|
||||
|
||||
void CPreviewModelView::SetBackgroundColor(ColorF color)
|
||||
{
|
||||
m_BackgroundColor = color;
|
||||
}
|
||||
|
||||
void CPreviewModelView::SetPlayState(PlayState state)
|
||||
{
|
||||
m_PlayState = state;
|
||||
}
|
||||
|
||||
void CPreviewModelView::SetTimeScale(float scale)
|
||||
{
|
||||
m_TimeScale = scale;
|
||||
}
|
||||
|
||||
CPreviewModelView::PlayState CPreviewModelView::GetPlayState() const
|
||||
{
|
||||
return m_PlayState;
|
||||
}
|
||||
|
||||
float CPreviewModelView::GetTimeScale() const
|
||||
{
|
||||
return m_TimeScale;
|
||||
}
|
||||
|
||||
|
||||
ColorF CPreviewModelView::GetGridColor() const
|
||||
{
|
||||
return m_GridColor;
|
||||
}
|
||||
|
||||
ColorF CPreviewModelView::GetBackgroundColor() const
|
||||
{
|
||||
return m_BackgroundColor;
|
||||
}
|
||||
|
||||
void CPreviewModelView::ImportModel()
|
||||
{
|
||||
SResourceSelectorContext x;
|
||||
x.typeName = Prop::GetPropertyTypeToResourceType(ePropertyModel);
|
||||
|
||||
QString currPath = m_ModelFilename.toLower();
|
||||
QString selected = GetIEditor()->GetResourceSelectorHost()->SelectResource(x, currPath);
|
||||
LoadModelFile(selected);
|
||||
}
|
||||
|
||||
void CPreviewModelView::SetPostUpdateCallback(PostUpdateCallback callback)
|
||||
{
|
||||
m_PostUpdateCallback = callback;
|
||||
}
|
||||
|
||||
void CPreviewModelView::SetContextMenuCallback(ContextMenuCallback callback)
|
||||
{
|
||||
m_ContextMenuCallback = callback;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//QViewportConsumer
|
||||
void CPreviewModelView::OnViewportRender(const SRenderContext& rc)
|
||||
{
|
||||
///UPDATE
|
||||
UpdateSettings();//Some changes may take effect next frame ...
|
||||
|
||||
//External updating ...
|
||||
if (m_PostUpdateCallback)
|
||||
{
|
||||
m_PostUpdateCallback();
|
||||
}
|
||||
|
||||
//RENDER
|
||||
CRY_ASSERT(rc.renderParams);
|
||||
CRY_ASSERT(rc.passInfo);
|
||||
RenderModels(*rc.renderParams, *rc.passInfo);
|
||||
}
|
||||
|
||||
void CPreviewModelView::OnViewportKey([[maybe_unused]] const SKeyEvent& ev)
|
||||
{
|
||||
}
|
||||
|
||||
void CPreviewModelView::OnViewportMouse([[maybe_unused]] const SMouseEvent& ev)
|
||||
{
|
||||
}
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//IEditorNotifyListener
|
||||
void CPreviewModelView::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case eNotify_OnCloseScene:
|
||||
{
|
||||
ResetAll();
|
||||
break;
|
||||
}
|
||||
case eNotify_OnIdleUpdate:
|
||||
{
|
||||
Update();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void CPreviewModelView::UpdateSettings()
|
||||
{
|
||||
//Update the settings
|
||||
SViewportSettings allsettings;
|
||||
|
||||
allsettings.background.topColor = m_BackgroundColor;
|
||||
allsettings.background.useGradient = false;
|
||||
|
||||
allsettings.grid.showGrid = IsFlagSet(PreviewModelViewFlag::SHOW_GRID);
|
||||
allsettings.grid.middleColor = m_BackgroundColor;
|
||||
allsettings.grid.mainColor = m_GridColor;
|
||||
|
||||
allsettings.rendering.wireframe = IsFlagSet(PreviewModelViewFlag::DRAW_WIREFRAME);
|
||||
allsettings.rendering.sunlight = IsFlagSet(PreviewModelViewFlag::ENABLE_TIME_OF_DAY);
|
||||
allsettings.rendering.fps = false;
|
||||
|
||||
|
||||
// Set zoom speed to 1.0f for better UI workflow, instead of the default 0.1f
|
||||
allsettings.camera.zoomSpeed = 1.0f;
|
||||
allsettings.camera.moveSpeed = GetIEditor()->GetEditorSettings()->cameraMoveSpeed;
|
||||
allsettings.camera.fastMoveMultiplier = GetIEditor()->GetEditorSettings()->cameraFastMoveSpeed;
|
||||
allsettings.camera.rotationSpeed = GetIEditor()->GetEditorSettings()->cameraRotateSpeed;
|
||||
allsettings.camera.showViewportOrientation = IsFlagSet(PreviewModelViewFlag::SHOW_GRID_AXIS);
|
||||
|
||||
//Set them ...
|
||||
SetSettings(allsettings);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CPreviewModelView::RenderModels(SRendParams& rendParams, SRenderingPassInfo& passInfo)
|
||||
{
|
||||
if (m_pStaticModel)
|
||||
{
|
||||
if (IsFlagSet(PreviewModelViewFlag::PRECACHE_MATERIAL))
|
||||
{
|
||||
_smart_ptr<IMaterial> pCurMat = m_pStaticModel->GetMaterial();
|
||||
if (pCurMat)
|
||||
{
|
||||
pCurMat->PrecacheMaterial(0.0f, nullptr, true, true);
|
||||
}
|
||||
}
|
||||
m_pStaticModel->Render(rendParams, passInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void CPreviewModelView::ReleaseModel()
|
||||
{
|
||||
m_ModelFilename = "";
|
||||
SAFE_RELEASE(m_pStaticModel);
|
||||
}
|
||||
|
||||
void CPreviewModelView::SetDefaultFlags()
|
||||
{
|
||||
UnSetFlag(PreviewModelViewFlag::SHOW_OVERDRAW);
|
||||
|
||||
m_Flags = 0;
|
||||
|
||||
SetFlag(PreviewModelViewFlag::SHOW_GRID);
|
||||
SetFlag(PreviewModelViewFlag::SHOW_GRID_AXIS);
|
||||
}
|
||||
|
||||
void CPreviewModelView::LoadModelFile(const QString& modelFile)
|
||||
{
|
||||
//Something to load
|
||||
if (!modelFile.isEmpty())
|
||||
{
|
||||
//Make sure we are not loading the same thing ...
|
||||
if (m_ModelFilename != modelFile)
|
||||
{
|
||||
ReleaseModel();//release any old mesh
|
||||
|
||||
QString strFileExt = Path::GetExt(modelFile);
|
||||
bool isCGF = (QString::compare(strFileExt, CRY_GEOMETRY_FILE_EXT, Qt::CaseInsensitive) == 0);
|
||||
|
||||
// NOTE: have to create a local buffer and evaluate the full message here due to calling into another address space to evaluate va_args
|
||||
// this prevents passing of random data to the log system ... any plugin that does not do it this way is rolling the dice each time.
|
||||
char buffer[2046];
|
||||
CRY_ASSERT(GetIEditor());
|
||||
if (isCGF)
|
||||
{
|
||||
CRY_ASSERT(GetIEditor()->Get3DEngine());
|
||||
// Load object.
|
||||
m_pStaticModel = GetIEditor()->Get3DEngine()->LoadStatObjUnsafeManualRef(modelFile.toUtf8().data(), nullptr, nullptr, false);
|
||||
if (m_pStaticModel)
|
||||
{
|
||||
m_pStaticModel->AddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
CRY_ASSERT(GetIEditor()->GetLogFile());
|
||||
azsprintf(buffer, "Loading of geometry object %s failed.", modelFile.toUtf8().data());
|
||||
GetIEditor()->GetLogFile()->Warning(buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CRY_ASSERT(GetIEditor()->GetLogFile());
|
||||
azsprintf(buffer, "Unknown model file (%s) attempting to be loaded.", modelFile.toUtf8().data());
|
||||
GetIEditor()->GetLogFile()->Warning(buffer);
|
||||
}
|
||||
|
||||
//if something was loaded then we store off the model path for the future
|
||||
if (m_pStaticModel)
|
||||
{
|
||||
m_ModelFilename = modelFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IStatObj* CPreviewModelView::GetStaticModel()
|
||||
{
|
||||
return m_pStaticModel;
|
||||
}
|
||||
|
||||
void CPreviewModelView::FocusOnScreen()
|
||||
{
|
||||
CCamera* camera = Camera();
|
||||
if (camera)
|
||||
{
|
||||
AABB accumulated(2);
|
||||
|
||||
if (m_pStaticModel)
|
||||
{
|
||||
AABB temp;
|
||||
temp.min = m_pStaticModel->GetBoxMin();
|
||||
temp.max = m_pStaticModel->GetBoxMax();
|
||||
accumulated.Add(temp);
|
||||
}
|
||||
|
||||
Vec3 fromDir(1.0f, 1.0f, -0.5f);
|
||||
Vec3 target = accumulated.GetCenter();
|
||||
float bbRadius = accumulated.GetRadius();
|
||||
|
||||
Vec3 dir = fromDir.GetNormalized();
|
||||
Matrix34 tm = Matrix33::CreateRotationVDir(dir, 0);
|
||||
tm.SetTranslation(target - dir * bbRadius);
|
||||
CameraMoved(QuatT(tm), true);
|
||||
}
|
||||
}
|
||||
|
||||
float CPreviewModelView::GetSpeedScale() const
|
||||
{
|
||||
CRY_ASSERT(GetIEditor());
|
||||
CRY_ASSERT(GetIEditor()->GetSystem());
|
||||
CRY_ASSERT(GetIEditor()->GetSystem()->GetITimer());
|
||||
//Taken from CRenderViewport to mirror controls from there ...
|
||||
float speedScale = 60.0f * GetIEditor()->GetSystem()->GetITimer()->GetFrameTime();
|
||||
if (speedScale > 20.0f)
|
||||
{
|
||||
speedScale = 20.0f;
|
||||
}
|
||||
return speedScale;
|
||||
}
|
||||
|
||||
@ -1,173 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//Editor
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "IEditor.h"
|
||||
#include "../EditorCommon/QViewport.h"
|
||||
#include "../EditorCommon/QViewportConsumer.h"
|
||||
|
||||
#endif
|
||||
|
||||
struct IStatObj;
|
||||
struct SRenderingPassInfo;
|
||||
struct SRendParams;
|
||||
class CParticleItem;
|
||||
class CAxisHelper;
|
||||
struct HitContext;
|
||||
struct IGizmoMouseDragHandler;
|
||||
struct SLodInfo;
|
||||
|
||||
namespace RotationDrawHelper
|
||||
{
|
||||
class Axis;
|
||||
}
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
class CPreviewModelView
|
||||
: public QViewport
|
||||
, public QViewportConsumer
|
||||
, public IEditorNotifyListener
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
public:
|
||||
enum class PlayState
|
||||
{
|
||||
NONE,
|
||||
PLAY,
|
||||
PAUSE,
|
||||
STEP,
|
||||
RESET
|
||||
};
|
||||
enum class SplineMode
|
||||
{
|
||||
NONE,
|
||||
LINE,
|
||||
SINEWAVE,
|
||||
COIL
|
||||
};
|
||||
|
||||
//NOTE: these need to be limited to 32 as these are being used for bit wise operations.
|
||||
enum class PreviewModelViewFlag
|
||||
{
|
||||
DRAW_WIREFRAME = 0,
|
||||
|
||||
SHOW_BOUNDINGBOX,
|
||||
SHOW_GIZMO,
|
||||
SHOW_GRID,
|
||||
SHOW_GRID_AXIS,
|
||||
SHOW_EMITTER_SHAPE,
|
||||
SHOW_OVERDRAW,
|
||||
SHOW_FIRST_CONTAINER,
|
||||
|
||||
LOOPING_PLAY,
|
||||
|
||||
//Spline
|
||||
SPLINE_LOOPING,
|
||||
SPLINE_PINGPONG,
|
||||
|
||||
PRECACHE_MATERIAL,
|
||||
|
||||
ENABLE_TIME_OF_DAY,
|
||||
|
||||
END_POSSIBLE_ITEMS = 32,
|
||||
};
|
||||
|
||||
explicit CPreviewModelView(QWidget* parent);
|
||||
virtual ~CPreviewModelView();
|
||||
|
||||
//Flags
|
||||
bool IsFlagSet(PreviewModelViewFlag flag) const;
|
||||
void ToggleFlag(PreviewModelViewFlag flag);
|
||||
virtual void SetFlag(PreviewModelViewFlag flag);
|
||||
virtual void UnSetFlag(PreviewModelViewFlag flag);
|
||||
|
||||
//Resets
|
||||
void ResetPlaybackControls();
|
||||
void ResetBackgroundColor();
|
||||
void ResetGridColor();
|
||||
virtual void ResetCamera();
|
||||
virtual void ResetAll();
|
||||
|
||||
void SetGridColor(ColorF color);
|
||||
void SetBackgroundColor(ColorF color);
|
||||
void SetPlayState(PlayState state);
|
||||
void SetTimeScale(float scale);
|
||||
|
||||
PlayState GetPlayState() const;
|
||||
float GetTimeScale() const;
|
||||
ColorF GetGridColor() const;
|
||||
ColorF GetBackgroundColor() const;
|
||||
|
||||
void ImportModel();
|
||||
|
||||
void LoadModelFile(const QString& modelFile);
|
||||
IStatObj* GetStaticModel();
|
||||
|
||||
typedef std::function<void()> PostUpdateCallback;
|
||||
void SetPostUpdateCallback(PostUpdateCallback callback);
|
||||
|
||||
typedef std::function<void(Vec2i mousePos)> ContextMenuCallback;
|
||||
void SetContextMenuCallback(ContextMenuCallback callback);
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//QViewportConsumer
|
||||
virtual void OnViewportRender(const SRenderContext& rc) override;
|
||||
virtual void OnViewportKey(const SKeyEvent& ev) override;
|
||||
virtual void OnViewportMouse(const SMouseEvent& ev) override;
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//IEditorNotifyListener
|
||||
virtual void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
//Update
|
||||
void UpdateSettings();
|
||||
protected:
|
||||
private:
|
||||
//Render
|
||||
void RenderModels(SRendParams& rendParams, SRenderingPassInfo& passInfo);
|
||||
|
||||
//Misc
|
||||
void ReleaseModel();
|
||||
void SetDefaultFlags();
|
||||
protected:
|
||||
void FocusOnScreen();
|
||||
private:
|
||||
float GetSpeedScale() const;
|
||||
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
ColorF m_GridColor;
|
||||
ColorF m_BackgroundColor;
|
||||
|
||||
QString m_ModelFilename;
|
||||
|
||||
|
||||
IStatObj* m_pStaticModel;
|
||||
|
||||
protected:
|
||||
PostUpdateCallback m_PostUpdateCallback;
|
||||
ContextMenuCallback m_ContextMenuCallback;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
protected:
|
||||
PlayState m_PlayState;
|
||||
float m_TimeScale;
|
||||
private:
|
||||
unsigned int m_Flags;
|
||||
};
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3e5d226d043630028a1fe88af240b627a08966066b605294cc79ff8273588166
|
||||
size 194
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f80544a0537398979dd423ffdc8e99c08e47dbe814cd4225646761cbe281eecc
|
||||
size 206
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bee8a3d1d5571e5afe0bd02edf0fc58d8297f96494a7c074fd2a37ecda7ae4dc
|
||||
size 208
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d3d0fc234e3154c06abd4e3b8d3d7e52a75f80d527b1d05541f55221cba199d7
|
||||
size 183
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ffb3586ef4309d8bfa93a581c38fe970e8b0411f170955921054522b0bf52bd3
|
||||
size 182
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f258e9617a1d4c7be16fcab12533a4f0bfe4072151f2140ca41364ef1a3cea62
|
||||
size 196
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:68c609d7bde1796f281690148c19694afddcc2cf4ea306116b546327cb50aad2
|
||||
size 249
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bd5106eebb6cf264fdac5f3568977fc8f944df4a4d4de6b0e9f35b3a001a3001
|
||||
size 206
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2b08a8d94c64aed944901b76afcb921c3df2c122c9eac6d52140552c2eb4e5cc
|
||||
size 227
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:623a937f09f1de3ebb889d7ac9e042f91bf67bef34695801b3603f4517166c8e
|
||||
size 223
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:623a937f09f1de3ebb889d7ac9e042f91bf67bef34695801b3603f4517166c8e
|
||||
size 223
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0ad56ab7be0a5a40b644045ac01c90fed6e70433a693e80c5b4b88d63801d75f
|
||||
size 14604
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9cc845c4eb0ed6fb772064d73f1c679e3b28288411a02f0cafaf248b83b44ca2
|
||||
size 221
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:966fd5ef5c1e0fe6e920511952d7aea98ad0f165f9ce0197f000f9f48ccd338b
|
||||
size 14628
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:966fd5ef5c1e0fe6e920511952d7aea98ad0f165f9ce0197f000f9f48ccd338b
|
||||
size 14628
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c4a8dc85c9928faacd184148aaf0f17ef7b68c185b04b0b5f16e942fb11c528e
|
||||
size 209
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d9047378404e0893b79bafaad9e6b312d467033daab2191a8c8839e4ff494bd8
|
||||
size 321
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2e79122edef52c3f9a31fd662f9f5cfd08b06e44e861c7379d8869635fd1d245
|
||||
size 168
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8cc16bbb4c4c0c1bea14c94d0609f4b11a7cd0ead4af3d236d329a404e8223a8
|
||||
size 200
|
||||
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "MaterialSender.h"
|
||||
|
||||
bool CMaterialSender::SendMessage(int msg, const XmlNodeRef& node)
|
||||
{
|
||||
bool bRet = false;
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
if (!CheckWindows())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_h.msg = msg;
|
||||
|
||||
int nDataSize = sizeof(SMaterialMapFileHeader) + strlen(node->getXML().c_str()) + 1;
|
||||
|
||||
//hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nDataSize, "EditMatMappingObject");
|
||||
|
||||
HANDLE mapFileHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "EditMatMappingObject");
|
||||
if (mapFileHandle)
|
||||
{
|
||||
void* pMes = MapViewOfFile(mapFileHandle, FILE_MAP_ALL_ACCESS, 0, 0, nDataSize);
|
||||
if (pMes)
|
||||
{
|
||||
memcpy(pMes, &m_h, sizeof(SMaterialMapFileHeader));
|
||||
azstrcpy(((char*)pMes) + sizeof(SMaterialMapFileHeader), nDataSize - sizeof(SMaterialMapFileHeader), node->getXML().c_str());
|
||||
UnmapViewOfFile(pMes);
|
||||
if (m_bIsMatEditor)
|
||||
{
|
||||
::SendMessage(m_h.GetMaxHWND(), WM_MATEDITSEND, msg, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
::SendMessage(m_h.GetEditorHWND(), WM_MATEDITSEND, msg, 0);
|
||||
}
|
||||
bRet = true;
|
||||
}
|
||||
CloseHandle(mapFileHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
CryLog("No File Map");
|
||||
}
|
||||
#endif
|
||||
|
||||
return bRet;
|
||||
}
|
||||
@ -1,175 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_MATERIALSENDER_H
|
||||
#define CRYINCLUDE_EDITOR_MATERIALSENDER_H
|
||||
#pragma once
|
||||
|
||||
#ifndef WM_MATEDITSEND
|
||||
// Value copied from Code/Tools/MaxCryExport/CryShader/MaterialSender.h
|
||||
# define WM_MATEDITSEND (WM_USER + 315)
|
||||
#endif
|
||||
|
||||
enum EMaterialSenderMessage
|
||||
{
|
||||
eMSM_Create = 1,
|
||||
eMSM_GetSelectedMaterial = 2,
|
||||
eMSM_Init = 3,
|
||||
};
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
struct SMaterialMapFileHeader
|
||||
{
|
||||
// max
|
||||
void SetMaxHWND(HWND hWnd)
|
||||
{
|
||||
hwndMax = (int64)hWnd;
|
||||
}
|
||||
HWND GetMaxHWND() const
|
||||
{
|
||||
return (HWND)hwndMax;
|
||||
}
|
||||
// editor
|
||||
void SetEditorHWND(HWND hWnd)
|
||||
{
|
||||
hwndMatEdit = (int64)hWnd;
|
||||
}
|
||||
HWND GetEditorHWND() const
|
||||
{
|
||||
return (HWND)hwndMatEdit;
|
||||
}
|
||||
int64 msg;// 64bits for both 32 and 64
|
||||
int64 Reserved;// 64bits for both 32 and 64
|
||||
protected:
|
||||
uint64 hwndMax;// HWND for 32 and 64 is different
|
||||
uint64 hwndMatEdit;// HWND for 32 and 64 is different
|
||||
};
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
|
||||
|
||||
class CMaterialSender
|
||||
{
|
||||
public:
|
||||
|
||||
CMaterialSender(bool bIsMatEditor)
|
||||
: m_bIsMatEditor(bIsMatEditor)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
m_h.SetEditorHWND(0);
|
||||
m_h.SetMaxHWND(0);
|
||||
m_h.msg = 0;
|
||||
hMapFile = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
~CMaterialSender()
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
if (hMapFile)
|
||||
{
|
||||
CloseHandle(hMapFile);
|
||||
}
|
||||
hMapFile = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GetMessage()
|
||||
{
|
||||
LoadMapFile();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckWindows()
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
if (!m_h.GetMaxHWND() || !m_h.GetEditorHWND() || !::IsWindow(m_h.GetMaxHWND()) || !::IsWindow(m_h.GetEditorHWND()))
|
||||
{
|
||||
LoadMapFile();
|
||||
}
|
||||
if (!m_h.GetMaxHWND() || !m_h.GetEditorHWND() || !::IsWindow(m_h.GetMaxHWND()) || !::IsWindow(m_h.GetEditorHWND()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Create()
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024 * 1024, "EditMatMappingObject");
|
||||
if (hMapFile)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
CryLog("Can't create File Map");
|
||||
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SendMessage(int msg, const XmlNodeRef& node);
|
||||
|
||||
void SetupWindows(QWidget* hwndMax, QWidget* hwndMatEdit)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
m_h.SetMaxHWND(reinterpret_cast<HWND>(hwndMax->winId()));
|
||||
m_h.SetEditorHWND(reinterpret_cast<HWND>(hwndMatEdit->winId()));
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool LoadMapFile()
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
bool bRet = false;
|
||||
const HANDLE mapFileHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "EditMatMappingObject");
|
||||
if (mapFileHandle)
|
||||
{
|
||||
void* const pMes = MapViewOfFile(mapFileHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
|
||||
if (pMes)
|
||||
{
|
||||
memcpy(&m_h, pMes, sizeof(SMaterialMapFileHeader));
|
||||
const char* const pXml = ((const char*)pMes) + sizeof(SMaterialMapFileHeader);
|
||||
m_node = XmlHelpers::LoadXmlFromBuffer(pXml, strlen(pXml));
|
||||
UnmapViewOfFile(pMes);
|
||||
bRet = true;
|
||||
}
|
||||
|
||||
CloseHandle(mapFileHandle);
|
||||
}
|
||||
|
||||
return bRet;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
SMaterialMapFileHeader m_h;
|
||||
#endif
|
||||
XmlNodeRef m_node;
|
||||
private:
|
||||
bool m_bIsMatEditor;
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
HANDLE hMapFile;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_MATERIALSENDER_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue