Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions Editor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ set(EDITOR_RESOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/Qml/Resource)
get_filename_component(EDITOR_RESOURCE_ROOT_ABSOLUTE ${EDITOR_RESOURCE_ROOT} ABSOLUTE)

file(GLOB QML_SOURCES ${EDITOR_QML_ROOT}/*.qml)
file(GLOB_RECURSE RESOURCES ${EDITOR_RESOURCE_ROOT}/*)

list(
APPEND SINGLETON_QML_SOURCES
Expand All @@ -70,17 +69,16 @@ foreach (QML_SOURCE ${QML_SOURCES})
endif ()
endforeach ()

foreach (RESOURCE ${RESOURCES})
string(REPLACE ${EDITOR_RESOURCE_ROOT_ABSOLUTE} "Resource" ALIAS ${RESOURCE})
set_source_files_properties(${RESOURCE} PROPERTIES QT_RESOURCE_ALIAS ${ALIAS})
endforeach ()
add_custom_command(
TARGET Editor POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${EDITOR_RESOURCE_ROOT_ABSOLUTE} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../Resource
)

qt_add_qml_module(
Editor
NO_CACHEGEN
URI editor
QML_FILES ${QML_SOURCES}
RESOURCES ${RESOURCES}
OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Generated/QmlModule
)
# ---- end qml ---------------------------------------------------------------------------------------
22 changes: 17 additions & 5 deletions Editor/Qml/EFloatInput.qml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,27 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic

ETextField {
Item {
property double value: Number(textField.text)
property double from: 0.0
property double to: 1.0

id: root
implicitWidth: 100
implicitWidth: textField.implicitWidth
implicitHeight: textField.implicitHeight

validator: DoubleValidator {
bottom: root.from
top: root.to
ETextField {
id: textField
implicitWidth: 100
text: value

onAccepted: {
root.value = Number(displayText)
}

validator: DoubleValidator {
bottom: root.from
top: root.to
}
}
}
2 changes: 1 addition & 1 deletion Editor/Qml/EIcon.qml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Item {

Image {
id: imageWidget
source: root.name === '' ? '' : 'Resource/Icon/%1.svg'.arg(root.name)
source: root.name === '' ? '' : 'file:../Resource/Icon/%1.svg'.arg(root.name)
sourceSize.width: root.size
sourceSize.height: root.size
layer.enabled: true
Expand Down
4 changes: 2 additions & 2 deletions Editor/Qml/ETheme.qml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ QtObject {
property color placeHolderFontColor: Qt.color('#c0c3c4')
property color linkFontColor: Qt.color('#91b9c4')

property FontLoader normalFont: FontLoader { source: Qt.url('Resource/Font/MiSans-Medium.ttf') }
property FontLoader boldFont: FontLoader { source: Qt.url('Resource/Font/MiSans-Semibold.ttf') }
property FontLoader normalFont: FontLoader { source: 'file:%1/Font/MiSans-Medium.ttf'.arg(appResDir) }
property FontLoader boldFont: FontLoader { source: 'file:%1/Font/MiSans-Semibold.ttf'.arg(appResDir) }
property int tiele1FontSize: 20
property int title2FontSize: 18
property int title3FontSize: 16
Expand Down
6 changes: 1 addition & 5 deletions Editor/Qml/EWidgetSamples.qml
Original file line number Diff line number Diff line change
Expand Up @@ -449,11 +449,7 @@ Rectangle {
Layout.margins: 5

RowLayout {
EFloatInput {
onAccepted: {
console.log('value accepted, value=' + text)
}
}
EFloatInput {}

EText {
Layout.leftMargin: 5
Expand Down
4 changes: 4 additions & 0 deletions Editor/Src/Widget/QmlWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Created by Kindem on 2024/12/31.
//

#include <QQmlContext>
#include <QVBoxLayout>

#include <Editor/Widget/QmlWidget.h>
Expand All @@ -15,6 +16,9 @@ namespace Editor {
, url(QmlEngine::Get().GetUrlFromShort(shortQmlFileName))
, quickView(new QQuickView)
{

const Common::Path resDir = Core::Paths::EngineResDir();
quickView->rootContext()->setContextProperty("appResDir", QString::fromStdString(resDir.String()));
quickView->setResizeMode(QQuickView::SizeRootObjectToView);
quickView->setSource(url);

Expand Down
Empty file added Engine/Shader/BasePassPS.esl
Empty file.
Empty file added Engine/Shader/BasePassVS.esl
Empty file.
1 change: 1 addition & 0 deletions Engine/Source/Common/Include/Common/File.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Common {
class FileUtils {
public:
static std::string ReadTextFile(const std::string& inFileName);
static void WriteTextFile(const std::string& inFileName, const std::string& inContent);
static rapidjson::Document ReadJsonFile(const std::string& inFileName);
static void WriteJsonFile(const std::string& inFileName, const rapidjson::Document& inJsonDocument, bool inPretty = true);
};
Expand Down
14 changes: 14 additions & 0 deletions Engine/Source/Common/Src/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ namespace Common {
return result;
}

void FileUtils::WriteTextFile(const std::string& inFileName, const std::string& inContent)
{
const Path path(inFileName);
if (const Path parentPath = path.Parent();
!parentPath.Exists()) {
parentPath.MakeDir();
}

std::ofstream file(inFileName, std::ios::out | std::ios::binary | std::ios::trunc);
Assert(file.is_open());
file.write(inContent.data(), static_cast<std::streamsize>(inContent.size()));
file.close();
}

rapidjson::Document FileUtils::ReadJsonFile(const std::string& inFileName)
{
char buffer[65536];
Expand Down
16 changes: 16 additions & 0 deletions Engine/Source/Common/Test/FileTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// Created by johnk on 2025/7/8.
//

#include <Common/File.h>
#include <Common/FileSystem.h>
#include <Test/Test.h>

TEST(FileTest, ReadWriteTextFileTest)
{
static Common::Path file = "../Test/Generated/Common/ReadTextFileTest.txt";

Common::FileUtils::WriteTextFile(file.Absolute().String(), "hello");
const std::string content = Common::FileUtils::ReadTextFile(file.Absolute().String());
ASSERT_EQ(content, "hello");
}
2 changes: 1 addition & 1 deletion Engine/Source/Render/Include/Render/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ namespace Render {
class MaterialShaderType final : public ShaderType {
public:
MaterialShaderType(
const VertexFactoryType& inVertexFactory,
const VertexFactoryType& inVertexFactoryType,
std::string inName,
RHI::ShaderStageBits inStage,
std::string inSourceFile,
Expand Down
6 changes: 3 additions & 3 deletions Engine/Source/Render/Src/Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,21 +244,21 @@ namespace Render {
}

MaterialShaderType::MaterialShaderType(
const VertexFactoryType& inVertexFactory,
const VertexFactoryType& inVertexFactoryType,
std::string inName,
RHI::ShaderStageBits inStage,
std::string inSourceFile,
std::string inEntryPoint,
const std::vector<std::string>& inIncludeDirectories,
const ShaderVariantFieldVec& inShaderVariantFields)
: ShaderType(Internal::MakeTypeKeyFromName(inName))
, vertexFactory(inVertexFactory)
, vertexFactory(inVertexFactoryType)
, name(std::move(inName))
, stage(inStage)
, sourceFile(std::move(inSourceFile))
, entryPoint(std::move(inEntryPoint))
, includeDirectories(inIncludeDirectories)
, shaderVariantFields(Common::VectorUtils::Combine(inVertexFactory.GetVariantFields(), inShaderVariantFields))
, shaderVariantFields(Common::VectorUtils::Combine(inVertexFactoryType.GetVariantFields(), inShaderVariantFields))
{
}

Expand Down
10 changes: 10 additions & 0 deletions Engine/Source/Runtime/Include/Runtime/Asset/Material.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace Runtime {
postProcess,
max
};
static_assert(static_cast<uint8_t>(MaterialType::max) == static_cast<uint8_t>(Render::MaterialType::max));

struct RUNTIME_API EClass() MaterialBoolVariantField {
EClassBody(MaterialBoolVariantField)
Expand Down Expand Up @@ -151,6 +152,9 @@ namespace Runtime {

explicit Material(Core::Uri inUri);

NonCopyable(Material)
NonMovable(Material)

EFunc() MaterialType GetType() const;
EFunc() void SetType(MaterialType inType);
EFunc() const std::string& GetSource() const;
Expand All @@ -174,11 +178,17 @@ namespace Runtime {
EFunc() const ParameterFieldMap& GetParameterFields() const;
EFunc() ParameterField& EmplaceParameterField(const std::string& inName);

EFunc() void Update();

private:
using StageShaderTypeMap = std::unordered_map<RHI::ShaderStageBits, Common::UniquePtr<Render::MaterialShaderType>>;

EProperty() MaterialType type;
EProperty() std::string source;
EProperty() VariantFieldMap variantFields;
EProperty() ParameterFieldMap parameterFields;

std::unordered_map<Render::VertexFactoryTypeKey, StageShaderTypeMap> shaderTypes;
};

class RUNTIME_API EClass() MaterialInstance final : public Asset {
Expand Down
100 changes: 100 additions & 0 deletions Engine/Source/Runtime/Src/Asset/Material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,52 @@

#include <Runtime/Asset/Material.h>

namespace Runtime::Internal {
static std::string GetVariantFieldMacro(const std::string& inVariantFieldName)
{
return Common::StringUtils::ToUpperCase(std::format("MATERIAL_VARIANT_{}", inVariantFieldName));
}

template <typename T>
struct VariantFieldConverter {};

template <>
struct VariantFieldConverter<MaterialBoolVariantField> {
static Render::ShaderBoolVariantField Execute(const std::string& inVariantFieldName, const MaterialBoolVariantField& inVariantField)
{
return {
GetVariantFieldMacro(inVariantFieldName),
inVariantField.defaultValue
};
}
};

template <>
struct VariantFieldConverter<MaterialRangedUintVariantField> {
static Render::ShaderRangedIntVariantField Execute(const std::string& inVariantFieldName, const MaterialRangedUintVariantField& inVariantField)
{
return {
GetVariantFieldMacro(inVariantFieldName),
inVariantField.defaultValue,
inVariantField.range
};
}
};

static Render::ShaderVariantFieldVec BuildShaderVariantFieldVec(const Material::VariantFieldMap& inVariantFields)
{
Render::ShaderVariantFieldVec result;
result.reserve(inVariantFields.size());

for (const auto& [variantFieldName, variantField] : inVariantFields) {
std::visit([&]<typename T>(const T& inTypedVariantField) -> void {
result.emplace_back(VariantFieldConverter<T>::Execute(variantFieldName, inTypedVariantField));
}, variantField);
}
return result;
}
}

namespace Runtime {
MaterialBoolVariantField::MaterialBoolVariantField()
: defaultValue(false)
Expand Down Expand Up @@ -178,6 +224,60 @@ namespace Runtime {
return parameterFields.at(inName);
}

void Material::Update()
{
static std::unordered_set supportedStages = {
RHI::ShaderStageBits::sVertex,
RHI::ShaderStageBits::sPixel};
static std::unordered_map<RHI::ShaderStageBits, std::string> stageEntrySourceFileMap = {
{RHI::ShaderStageBits::sVertex, "Engine/Shader/BasePassVS.esl"},
{RHI::ShaderStageBits::sPixel, "Engine/Shader/BasePassPS.esl"}};
static std::unordered_map<RHI::ShaderStageBits, std::string> stageSimpleNameMap = {
{RHI::ShaderStageBits::sVertex, "VS"},
{RHI::ShaderStageBits::sPixel, "PS"}};
static std::unordered_map<RHI::ShaderStageBits, std::string> stageEntryPointMap = {
{RHI::ShaderStageBits::sVertex, "VSMain"},
{RHI::ShaderStageBits::sPixel, "PSMain"}};

const std::string uriStr = Uri().Str();
const std::string materialName = Common::Path(Uri().Content()).FileNameWithoutExtension();
const std::uint64_t uriHash = Common::HashUtils::CityHash(uriStr.c_str(), uriStr.size());
const Common::Path materialRootCacheDir = std::format("Game/Cache/Materials/{}", uriHash);
const Common::Path materialHintFile = materialRootCacheDir / materialName;
const Common::Path materialHeader = materialRootCacheDir / "Material.ush";

if (const Common::Path absoluteMaterialRootCacheDir = Core::Paths::Translate(materialRootCacheDir);
!absoluteMaterialRootCacheDir.Exists()) {
absoluteMaterialRootCacheDir.MakeDir();
}
Common::FileUtils::WriteTextFile(Core::Paths::Translate(materialHintFile).Absolute().String(), "");
Common::FileUtils::WriteTextFile(Core::Paths::Translate(materialHeader).Absolute().String(), source);

shaderTypes.clear();
for (const Render::VertexFactoryType* vertexFactoryType : Render::VertexFactoryTypeRegistry::Get().AllTypes()) {
if (!vertexFactoryType->SupportMaterialType(static_cast<Render::MaterialType>(type))) {
continue;
}

const auto vertexFactoryTypeKey = vertexFactoryType->GetKey();
shaderTypes.emplace(vertexFactoryTypeKey, StageShaderTypeMap {});
StageShaderTypeMap& stageShaderTypeMap = shaderTypes.at(vertexFactoryTypeKey);

for (const auto stage : supportedStages) {
stageShaderTypeMap.emplace(
stage,
Common::MakeUnique<Render::MaterialShaderType>(
*vertexFactoryType,
std::format("{}-{}", materialName, stageSimpleNameMap.at(stage)),
stage,
stageEntrySourceFileMap.at(stage),
stageEntryPointMap.at(stage),
std::vector {materialRootCacheDir.String()},
Internal::BuildShaderVariantFieldVec(variantFields)));
}
}
}

MaterialInstance::MaterialInstance(Core::Uri inUri)
: Asset(std::move(inUri))
{
Expand Down
Loading