void ezWorld::SetObjectGlobalKey(ezGameObject* pObject, const ezHashedString& sGlobalKey) { if (m_Data.m_GlobalKeyToIdTable.Contains(sGlobalKey.GetHash())) { ezLog::Error("Can't set global key to '{0}' because an object with this global key already exists. Global keys have to be unique.", sGlobalKey); return; } const ezUInt32 uiId = pObject->m_InternalId.m_Data; // Remove existing entry first. ezHashedString* pOldGlobalKey; if (m_Data.m_IdToGlobalKeyTable.TryGetValue(uiId, pOldGlobalKey)) { if (sGlobalKey == *pOldGlobalKey) { return; } EZ_VERIFY(m_Data.m_GlobalKeyToIdTable.Remove(pOldGlobalKey->GetHash()), "Implementation error."); EZ_VERIFY(m_Data.m_IdToGlobalKeyTable.Remove(uiId), "Implementation error."); } // Insert new one if key is valid. if (!sGlobalKey.IsEmpty()) { m_Data.m_GlobalKeyToIdTable.Insert(sGlobalKey.GetHash(), pObject->m_InternalId); m_Data.m_IdToGlobalKeyTable.Insert(uiId, sGlobalKey); } }
void ezGameApplicationBase::Deinit_UnloadPlugins() { ezSet<ezString> ToUnload; // if a plugin is linked statically (which happens mostly in an editor context) // then it cannot be unloaded and the ezPlugin instance won't ever go away // however, ezPlugin::UnloadPlugin will always return that it is already unloaded, so we can just skip it there // all other plugins must be unloaded as often as their refcount, though ezStringBuilder s; ezPlugin* pPlugin = ezPlugin::GetFirstInstance(); while (pPlugin != nullptr) { s = ezPlugin::GetFirstInstance()->GetPluginName(); ToUnload.Insert(s); pPlugin = pPlugin->GetNextInstance(); } ezString temp; while (!ToUnload.IsEmpty()) { auto it = ToUnload.GetIterator(); ezInt32 iRefCount = 0; EZ_VERIFY(ezPlugin::UnloadPlugin(it.Key(), &iRefCount).Succeeded(), "Failed to unload plugin '{0}'", s); if (iRefCount == 0) ToUnload.Remove(it); } }
ezUInt32 ezQtPropertyContainerWidget::GetRequiredElementCount() const { if (m_pProp->GetCategory() == ezPropertyCategory::Map) { m_Keys.Clear(); EZ_VERIFY(m_pObjectAccessor->GetKeys(m_Items[0].m_pObject, m_pProp, m_Keys).m_Result.Succeeded(), "GetKeys should always succeed."); ezHybridArray<ezVariant, 16> keys; for (ezUInt32 i = 1; i < m_Items.GetCount(); i++) { keys.Clear(); EZ_VERIFY(m_pObjectAccessor->GetKeys(m_Items[i].m_pObject, m_pProp, keys).m_Result.Succeeded(), "GetKeys should always succeed."); for (ezInt32 k = (ezInt32)m_Keys.GetCount() - 1; k >= 0; --k) { if (!keys.Contains(m_Keys[k])) { m_Keys.RemoveAtAndSwap(k); } } } m_Keys.Sort([](const ezVariant& a, const ezVariant& b) { return a.Get<ezString>().Compare(b.Get<ezString>()) < 0; }); return m_Keys.GetCount(); } else { ezInt32 iElements = 0x7FFFFFFF; for (const auto& item : m_Items) { ezInt32 iCount = 0; EZ_VERIFY(m_pObjectAccessor->GetCount(item.m_pObject, m_pProp, iCount).m_Result.Succeeded(), "GetCount should always succeed."); iElements = ezMath::Min(iElements, iCount); } EZ_ASSERT_DEV(iElements >= 0, "Mismatch between storage and RTTI ({0})", iElements); m_Keys.Clear(); for (ezUInt32 i = 0; i < (ezUInt32)iElements; i++) { m_Keys.PushBack(i); } return ezUInt32(iElements); } }
void ezQtVariantPropertyWidget::ChangeVariantType(ezVariantType::Enum type) { m_pObjectAccessor->StartTransaction("Change variant type"); // check if we have multiple values for (const auto& item : m_Items) { ezVariant value; EZ_VERIFY(m_pObjectAccessor->GetValue(item.m_pObject, m_pProp, value, item.m_Index).Succeeded(), ""); if (value.CanConvertTo(type)) { EZ_VERIFY(m_pObjectAccessor->SetValue(item.m_pObject, m_pProp, value.ConvertTo(type), item.m_Index).Succeeded(), ""); } else { EZ_VERIFY(m_pObjectAccessor->SetValue(item.m_pObject, m_pProp, ezReflectionUtils::GetDefaultVariantFromType(type), item.m_Index) .Succeeded(), ""); } } m_pObjectAccessor->FinishTransaction(); }
void ezWorld::DeleteObjectNow(const ezGameObjectHandle& object) { CheckForWriteAccess(); ezGameObject* pObject = nullptr; if (!m_Data.m_Objects.TryGetValue(object, pObject)) return; // set object to inactive so components and children know that they shouldn't access the object anymore. pObject->m_Flags.Remove(ezObjectFlags::Active); // delete children for (auto it = pObject->GetChildren(); it.IsValid(); ++it) { DeleteObjectNow(it->GetHandle()); } // delete attached components const ezArrayPtr<ezComponent*> components = pObject->m_Components; for (ezUInt32 c = 0; c < components.GetCount(); ++c) { ezComponent* pComponent = components[c]; pComponent->GetOwningManager()->DeleteComponent(pComponent->GetHandle()); } EZ_ASSERT_DEV(pObject->m_Components.GetCount() == 0, "Components should already be removed"); // fix parent and siblings UnlinkFromParent(pObject); // remove from global key tables SetObjectGlobalKey(pObject, ezHashedString()); // invalidate and remove from id table pObject->m_InternalId.Invalidate(); m_Data.m_DeadObjects.PushBack(pObject); EZ_VERIFY(m_Data.m_Objects.Remove(object), "Implementation error."); }
ezQtShortcutEditorDlg::ezQtShortcutEditorDlg(QWidget* parent) : QDialog(parent) { setupUi(this); EZ_VERIFY(connect(Shortcuts, SIGNAL(itemSelectionChanged()), this, SLOT(SlotSelectionChanged())) != nullptr, "signal/slot connection failed"); m_iSelectedAction = -1; KeyEditor->setEnabled(false); ezMap<ezString, ezMap<ezString, ezInt32>> SortedItems; { auto itActions = ezActionManager::GetActionIterator(); while (itActions.IsValid()) { if (itActions.Value()->m_Type == ezActionType::Action) { SortedItems[itActions.Value()->m_sCategoryPath][itActions.Value()->m_sActionName] = m_ActionDescs.GetCount(); m_ActionDescs.PushBack(itActions.Value()); } itActions.Next(); } } { ezQtScopedBlockSignals bs(Shortcuts); ezQtScopedUpdatesDisabled ud(Shortcuts); Shortcuts->setAlternatingRowColors(true); Shortcuts->setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers); Shortcuts->setExpandsOnDoubleClick(true); ezStringBuilder sTemp; for (auto it = SortedItems.GetIterator(); it.IsValid(); ++it) { auto pParent = new QTreeWidgetItem(); pParent->setData(0, Qt::DisplayRole, it.Key().GetData()); Shortcuts->addTopLevelItem(pParent); pParent->setExpanded(true); pParent->setFirstColumnSpanned(true); pParent->setFlags(Qt::ItemFlag::ItemIsEnabled); QFont font = pParent->font(0); font.setBold(true); pParent->setFont(0, font); for (auto it2 : it.Value()) { const auto& item = m_ActionDescs[it2.Value()]; auto pItem = new QTreeWidgetItem(pParent); /// \todo Instead of removing &, replace it by underlined text (requires formatted text output) sTemp = ezTranslate(item->m_sActionName); sTemp.ReplaceAll("&", ""); pItem->setData(0, Qt::UserRole, it2.Value()); pItem->setData(0, Qt::DisplayRole, item->m_sActionName.GetData()); pItem->setData(1, Qt::DisplayRole, sTemp.GetData()); pItem->setData(2, Qt::DisplayRole, item->m_sShortcut.GetData()); pItem->setData(3, Qt::DisplayRole, ezTranslateTooltip(item->m_sActionName)); if (item->m_sShortcut == item->m_sDefaultShortcut) pItem->setBackground(2, QBrush()); else pItem->setBackgroundColor(2, Qt::darkYellow); sTemp.Set("Default: ", item->m_sDefaultShortcut.IsEmpty() ? "<none>" : item->m_sDefaultShortcut); pItem->setToolTip(2, QString::fromUtf8(sTemp.GetData())); } } Shortcuts->resizeColumnToContents(0); Shortcuts->resizeColumnToContents(2); } ButtonAssign->setEnabled(false); ButtonRemove->setEnabled(false); ButtonReset->setEnabled(false); }
void AfterCoreSystemsStartup() override { ezStringBuilder sProjectDir = ">sdk/Data/Samples/TextureSample"; ezStringBuilder sProjectDirResolved; ezFileSystem::ResolveSpecialDirectory(sProjectDir, sProjectDirResolved); ezFileSystem::SetSpecialDirectory("project", sProjectDirResolved); // setup the 'asset management system' { // which redirection table to search ezDataDirectory::FolderType::s_sRedirectionFile = "AssetCache/LookupTable.ezAsset"; // which platform assets to use ezDataDirectory::FolderType::s_sRedirectionPrefix = "AssetCache/PC/"; } ezFileSystem::RegisterDataDirectoryFactory(ezDataDirectory::FolderType::Factory); ezFileSystem::AddDataDirectory("", "", ":", ezFileSystem::AllowWrites); ezFileSystem::AddDataDirectory(">appdir/", "AppBin", "bin", ezFileSystem::AllowWrites); // writing to the binary directory ezFileSystem::AddDataDirectory(">appdir/", "ShaderCache", "shadercache", ezFileSystem::AllowWrites); // for shader files ezFileSystem::AddDataDirectory(">user/ezEngine Project/TextureSample", "AppData", "appdata", ezFileSystem::AllowWrites); // app user data ezFileSystem::AddDataDirectory(">sdk/Data/Base", "Base", "base"); ezFileSystem::AddDataDirectory(">sdk/Data/FreeContent", "Shared", "shared"); ezFileSystem::AddDataDirectory(">project/", "Project", "project", ezFileSystem::AllowWrites); ezGlobalLog::AddLogWriter(ezLogWriter::Console::LogMessageHandler); ezGlobalLog::AddLogWriter(ezLogWriter::VisualStudio::LogMessageHandler); ezTelemetry::CreateServer(); ezPlugin::LoadPlugin("ezInspectorPlugin"); EZ_VERIFY(ezPlugin::LoadPlugin("ezShaderCompilerHLSL").Succeeded(), "Compiler Plugin not found"); // Register Input { ezInputActionConfig cfg; cfg = ezInputManager::GetInputActionConfig("Main", "CloseApp"); cfg.m_sInputSlotTrigger[0] = ezInputSlot_KeyEscape; ezInputManager::SetInputActionConfig("Main", "CloseApp", cfg, true); cfg = ezInputManager::GetInputActionConfig("Main", "MovePosX"); cfg.m_sInputSlotTrigger[0] = ezInputSlot_MouseMovePosX; cfg.m_bApplyTimeScaling = false; ezInputManager::SetInputActionConfig("Main", "MovePosX", cfg, true); cfg = ezInputManager::GetInputActionConfig("Main", "MoveNegX"); cfg.m_sInputSlotTrigger[0] = ezInputSlot_MouseMoveNegX; cfg.m_bApplyTimeScaling = false; ezInputManager::SetInputActionConfig("Main", "MoveNegX", cfg, true); cfg = ezInputManager::GetInputActionConfig("Main", "MovePosY"); cfg.m_sInputSlotTrigger[0] = ezInputSlot_MouseMovePosY; cfg.m_bApplyTimeScaling = false; ezInputManager::SetInputActionConfig("Main", "MovePosY", cfg, true); cfg = ezInputManager::GetInputActionConfig("Main", "MoveNegY"); cfg.m_sInputSlotTrigger[0] = ezInputSlot_MouseMoveNegY; cfg.m_bApplyTimeScaling = false; ezInputManager::SetInputActionConfig("Main", "MoveNegY", cfg, true); cfg = ezInputManager::GetInputActionConfig("Main", "MouseDown"); cfg.m_sInputSlotTrigger[0] = ezInputSlot_MouseButton0; cfg.m_bApplyTimeScaling = false; ezInputManager::SetInputActionConfig("Main", "MouseDown", cfg, true); } // Create a window for rendering { ezWindowCreationDesc WindowCreationDesc; WindowCreationDesc.m_Resolution.width = g_uiWindowWidth; WindowCreationDesc.m_Resolution.height = g_uiWindowHeight; m_pWindow = EZ_DEFAULT_NEW(TextureSampleWindow); m_pWindow->Initialize(WindowCreationDesc); } // Create a device { ezGALDeviceCreationDescription DeviceInit; DeviceInit.m_bCreatePrimarySwapChain = true; DeviceInit.m_bDebugDevice = true; DeviceInit.m_PrimarySwapChainDescription.m_pWindow = m_pWindow; DeviceInit.m_PrimarySwapChainDescription.m_SampleCount = ezGALMSAASampleCount::None; DeviceInit.m_PrimarySwapChainDescription.m_bAllowScreenshots = true; m_pDevice = EZ_DEFAULT_NEW(ezGALDeviceDX11, DeviceInit); EZ_VERIFY(m_pDevice->Init() == EZ_SUCCESS, "Device init failed!"); ezGALDevice::SetDefaultDevice(m_pDevice); } // now that we have a window and device, tell the engine to initialize the rendering infrastructure ezStartup::StartupHighLevelSystems(); // Get the primary swapchain (this one will always be created by device init except if the user instructs no swap chain creation // explicitly) { ezGALSwapChainHandle hPrimarySwapChain = m_pDevice->GetPrimarySwapChain(); const ezGALSwapChain* pPrimarySwapChain = m_pDevice->GetSwapChain(hPrimarySwapChain); ezGALTextureCreationDescription texDesc; texDesc.m_uiWidth = g_uiWindowWidth; texDesc.m_uiHeight = g_uiWindowHeight; texDesc.m_Format = ezGALResourceFormat::D24S8; texDesc.m_bCreateRenderTarget = true; m_hDepthStencilTexture = m_pDevice->CreateTexture(texDesc); m_hBBRTV = m_pDevice->GetDefaultRenderTargetView(pPrimarySwapChain->GetBackBufferTexture()); m_hBBDSV = m_pDevice->GetDefaultRenderTargetView(m_hDepthStencilTexture); } // Create Rasterizer State { ezGALRasterizerStateCreationDescription RasterStateDesc; RasterStateDesc.m_CullMode = ezGALCullMode::Back; RasterStateDesc.m_bFrontCounterClockwise = true; m_hRasterizerState = m_pDevice->CreateRasterizerState(RasterStateDesc); EZ_ASSERT_DEV(!m_hRasterizerState.IsInvalidated(), "Couldn't create rasterizer state!"); } // Create Depth Stencil state { ezGALDepthStencilStateCreationDescription DepthStencilStateDesc; DepthStencilStateDesc.m_bDepthTest = false; DepthStencilStateDesc.m_bDepthWrite = true; m_hDepthStencilState = m_pDevice->CreateDepthStencilState(DepthStencilStateDesc); EZ_ASSERT_DEV(!m_hDepthStencilState.IsInvalidated(), "Couldn't create depth-stencil state!"); } // Setup Shaders and Materials { ezShaderManager::Configure("DX11_SM50", true); m_hMaterial = ezResourceManager::LoadResource<ezMaterialResource>("Materials/Texture.ezMaterial"); // Create the mesh that we use for rendering CreateSquareMesh(); } // Setup default resources { ezTexture2DResourceHandle hFallback = ezResourceManager::LoadResource<ezTexture2DResource>("Textures/Reference_D.dds"); ezTexture2DResourceHandle hMissing = ezResourceManager::LoadResource<ezTexture2DResource>("Textures/MissingTexture_D.dds"); ezResourceManager::SetResourceTypeLoadingFallback<ezTexture2DResource>(hFallback); ezResourceManager::SetResourceTypeMissingFallback<ezTexture2DResource>(hMissing); // redirect all texture load operations through our custom loader, so that we can duplicate the single source texture // that we have as often as we like (to waste memory) ezResourceManager::SetResourceTypeLoader<ezTexture2DResource>(&m_TextureResourceLoader); } // Setup constant buffer that this sample uses { m_hSampleConstants = ezRenderContext::CreateConstantBufferStorage(m_pSampleConstantBuffer); } // Pre-allocate all textures { // we only do this to be able to see the unloaded resources in the ezInspector // this does NOT preload the resources ezStringBuilder sResourceName; for (ezInt32 y = -g_iMaxHalfExtent; y < g_iMaxHalfExtent; ++y) { for (ezInt32 x = -g_iMaxHalfExtent; x < g_iMaxHalfExtent; ++x) { sResourceName.Printf("Loaded_%+03i_%+03i_D", x, y); ezTexture2DResourceHandle hTexture = ezResourceManager::LoadResource<ezTexture2DResource>(sResourceName); if (g_bPreloadAllTextures) ezResourceManager::PreloadResource(hTexture, ezTime::Seconds(1.0)); } } } }
ezResult CompileDXShader(const char* szFile, const char* szSource, bool bDebug, const char* szProfile, const char* szEntryPoint, ezDynamicArray<ezUInt8>& out_ByteCode) { out_ByteCode.Clear(); ID3DBlob* pResultBlob = nullptr; ID3DBlob* pErrorBlob = nullptr; const char* szCompileSource = szSource; ezStringBuilder sDebugSource; UINT flags1 = 0; if (bDebug) { flags1 = D3DCOMPILE_DEBUG | D3DCOMPILE_PREFER_FLOW_CONTROL | D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_ENABLE_STRICTNESS; // In debug mode we need to remove '#line' as any shader debugger won't work with them. sDebugSource = szSource; sDebugSource.ReplaceAll("#line ", "//ine "); szCompileSource = sDebugSource; } if (FAILED(D3DCompile( szCompileSource, strlen(szCompileSource), szFile, nullptr, nullptr, szEntryPoint, szProfile, flags1, 0, &pResultBlob, &pErrorBlob))) { if (bDebug) { // Try again with '#line' intact to get correct error messages with file and line info. pErrorBlob->Release(); pErrorBlob = nullptr; EZ_VERIFY(FAILED(D3DCompile( szSource, strlen(szSource), szFile, nullptr, nullptr, szEntryPoint, szProfile, flags1, 0, &pResultBlob, &pErrorBlob)), "Debug compilation with commented out '#line' failed but original version did not."); } const char* szError = static_cast<const char*>(pErrorBlob->GetBufferPointer()); EZ_LOG_BLOCK("Shader Compilation Failed", szFile); ezLog::Error("Could not compile shader '{0}' for profile '{1}'", szFile, szProfile); ezLog::Error("{0}", szError); pErrorBlob->Release(); return EZ_FAILURE; } if (pErrorBlob != nullptr) { const char* szError = static_cast<const char*>(pErrorBlob->GetBufferPointer()); EZ_LOG_BLOCK("Shader Compilation Error Message", szFile); ezLog::Dev("{0}", szError); pErrorBlob->Release(); } if (pResultBlob != nullptr) { out_ByteCode.SetCountUninitialized((ezUInt32)pResultBlob->GetBufferSize()); ezMemoryUtils::Copy(out_ByteCode.GetData(), static_cast<ezUInt8*>(pResultBlob->GetBufferPointer()), out_ByteCode.GetCount()); pResultBlob->Release(); } return EZ_SUCCESS; }