/* * 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 "StdAfx.h" #include #include #include "ModelViewport.h" #include "ThumbnailGenerator.h" #include "GameEngine.h" #include "ICryAnimation.h" #include "IAttachment.h" #include "CryCharMorphParams.h" #include "CryCharAnimationParams.h" #include "IFacialAnimation.h" #include "FileTypeUtils.h" #include "Objects/DisplayContext.h" #include "Material/MaterialManager.h" #include "ErrorReport.h" #include #if ENABLE_CRY_PHYSICS #include #endif #include #include "IRenderAuxGeom.h" #include "DisplaySettings.h" #include "IViewSystem.h" #include "IEntityHelper.h" #include #include #include #include #include #include #include uint32 g_ypos = 0; #define SKYBOX_NAME "InfoRedGal" namespace { int s_varsPanelId = 0; ReflectedPropertiesPanel* s_varsPanel = 0; } ///////////////////////////////////////////////////////////////////////////// // CModelViewport CModelViewport::CModelViewport(const char* settingsPath, QWidget* parent) : CRenderViewport(tr("Model View"), parent) { m_settingsPath = QString::fromLatin1(settingsPath); m_pCharacterBase = 0; m_bPaused = false; m_Camera.SetFrustum(800, 600, 3.14f / 4.0f, 0.02f, 10000); m_pAnimationSystem = GetIEditor()->GetSystem()->GetIAnimationSystem(); m_bInRotateMode = false; m_bInMoveMode = false; m_rollupIndex = 0; m_rollupIndex2 = 0; m_object = 0; m_weaponModel = 0; m_attachedCharacter = 0; m_camRadius = 10; m_moveSpeed = 0.1f; m_LightRotationRadian = 0.0f; m_weaponIK = false; m_pRESky = 0; m_pSkyboxName = 0; m_pSkyBoxShader = NULL; #if ENABLE_CRY_PHYSICS m_pPhysicalEntity = NULL; #endif m_attachBone = QStringLiteral("weapon_bone"); // Init variable. mv_objectAmbientColor = Vec3(0.25f, 0.25f, 0.25f); mv_backgroundColor = Vec3(0.25f, 0.25f, 0.25f); mv_lightDiffuseColor = Vec3(0.70f, 0.70f, 0.70f); mv_lightMultiplier = 3.0f; mv_lightOrbit = 15.0f; mv_lightRadius = 400.0f; mv_lightSpecMultiplier = 1.0f; mv_showPhysics = false; m_GridOrigin = Vec3(ZERO); m_arrAnimatedCharacterPath.resize(0x200, ZERO); m_arrSmoothEntityPath.resize(0x200, ZERO); m_arrRunStrafeSmoothing.resize(0x100); SetPlayerPos(); //-------------------------------------------------- // Register variables. //-------------------------------------------------- m_vars.AddVariable(mv_showPhysics, "Display Physics"); m_vars.AddVariable(mv_useCharPhysics, "Use Character Physics", functor(*this, &CModelViewport::OnCharPhysics)); mv_useCharPhysics = true; m_vars.AddVariable(mv_showGrid, "ShowGrid"); mv_showGrid = true; m_vars.AddVariable(mv_showBase, "ShowBase"); mv_showBase = false; m_vars.AddVariable(mv_showLocator, "ShowLocator"); mv_showLocator = 0; m_vars.AddVariable(mv_InPlaceMovement, "InPlaceMovement"); mv_InPlaceMovement = false; m_vars.AddVariable(mv_StrafingControl, "StrafingControl"); mv_StrafingControl = false; m_vars.AddVariable(mv_lighting, "Lighting"); mv_lighting = true; m_vars.AddVariable(mv_animateLights, "AnimLights"); m_vars.AddVariable(mv_backgroundColor, "BackgroundColor", functor(*this, &CModelViewport::OnLightColor), IVariable::DT_COLOR); m_vars.AddVariable(mv_objectAmbientColor, "ObjectAmbient", functor(*this, &CModelViewport::OnLightColor), IVariable::DT_COLOR); m_vars.AddVariable(mv_lightDiffuseColor, "LightDiffuse", functor(*this, &CModelViewport::OnLightColor), IVariable::DT_COLOR); m_vars.AddVariable(mv_lightMultiplier, "Light Multiplier", functor(*this, &CModelViewport::OnLightMultiplier), IVariable::DT_SIMPLE); m_vars.AddVariable(mv_lightSpecMultiplier, "Light Specular Multiplier", functor(*this, &CModelViewport::OnLightMultiplier), IVariable::DT_SIMPLE); m_vars.AddVariable(mv_lightRadius, "Light Radius", functor(*this, &CModelViewport::OnLightMultiplier), IVariable::DT_SIMPLE); m_vars.AddVariable(mv_lightOrbit, "Light Orbit", functor(*this, &CModelViewport::OnLightMultiplier), IVariable::DT_SIMPLE); m_vars.AddVariable(mv_showWireframe1, "ShowWireframe1"); m_vars.AddVariable(mv_showWireframe2, "ShowWireframe2"); m_vars.AddVariable(mv_showTangents, "ShowTangents"); m_vars.AddVariable(mv_showBinormals, "ShowBinormals"); m_vars.AddVariable(mv_showNormals, "ShowNormals"); m_vars.AddVariable(mv_showSkeleton, "ShowSkeleton"); m_vars.AddVariable(mv_showJointNames, "ShowJointNames"); m_vars.AddVariable(mv_showJointsValues, "ShowJointsValues"); m_vars.AddVariable(mv_showStartLocation, "ShowInvStartLocation"); m_vars.AddVariable(mv_showMotionParam, "ShowMotionParam"); m_vars.AddVariable(mv_printDebugText, "PrintDebugText"); m_vars.AddVariable(mv_UniformScaling, "UniformScaling"); mv_UniformScaling = 1.0f; mv_UniformScaling.SetLimits(0.01f, 2.0f); m_vars.AddVariable(mv_forceLODNum, "ForceLODNum"); mv_forceLODNum = 0; mv_forceLODNum.SetLimits(0, 10); m_vars.AddVariable(mv_showShaders, "ShowShaders", functor(*this, &CModelViewport::OnShowShaders)); m_vars.AddVariable(mv_AttachCamera, "AttachCamera"); m_vars.AddVariable(mv_fov, "FOV"); mv_fov = 60; mv_fov.SetLimits(1, 120); RestoreDebugOptions(); m_camRadius = 10; //YPR_Angle = Ang3(0,-1.0f,0); //SetViewTM( Matrix34(CCamera::CreateOrientationYPR(YPR_Angle), Vec3(0,-m_camRadius,0)) ); Vec3 camPos = Vec3(10, 10, 10); Matrix34 tm = Matrix33::CreateRotationVDir((Vec3(0, 0, 0) - camPos).GetNormalized()); tm.SetTranslation(camPos); SetViewTM(tm); #if ENABLE_CRY_PHYSICS if (GetIEditor()->IsInPreviewMode()) { // In preview mode create a simple physical grid, so we can register physical entities. int nCellSize = 4; IPhysicalWorld* pPhysWorld = gEnv->pPhysicalWorld; if (pPhysWorld) { pPhysWorld->SetupEntityGrid(2, Vec3(0, 0, 0), 10, 10, 1, 1); } } #endif // ENABLE_CRY_PHYSICS // Audio m_pAudioListener = NULL; m_AABB.Reset(); } ////////////////////////////////////////////////////////////////////////// void CModelViewport::SaveDebugOptions() const { QSettings settings; for (auto g : m_settingsPath.split('\\')) settings.beginGroup(g); CVarBlock* vb = GetVarObject()->GetVarBlock(); int32 vbCount = vb->GetNumVariables(); settings.setValue("iDebugOptionCount", vbCount); char keyType[64], keyValue[64]; for (int32 i = 0; i < vbCount; ++i) { IVariable* var = vb->GetVariable(i); IVariable::EType vType = var->GetType(); sprintf_s(keyType, "DebugOption_%s_type", var->GetName().toUtf8().data()); sprintf_s(keyValue, "DebugOption_%s_value", var->GetName().toUtf8().data()); switch (vType) { case IVariable::UNKNOWN: { break; } case IVariable::INT: { int32 value = 0; var->Get(value); settings.setValue(keyType, IVariable::INT); settings.setValue(keyValue, value); break; } case IVariable::BOOL: { bool value = 0; var->Get(value); settings.setValue(keyType, IVariable::BOOL); settings.setValue(keyValue, value); break; } case IVariable::FLOAT: { f32 value = 0; var->Get(value); settings.setValue(keyType, IVariable::FLOAT); settings.setValue(keyValue, value); break; } case IVariable::VECTOR: { Vec3 value; var->Get(value); f32 valueArray[3]; valueArray[0] = value.x; valueArray[1] = value.y; valueArray[2] = value.z; settings.setValue(keyType, IVariable::VECTOR); settings.setValue(keyValue, QByteArray(reinterpret_cast(&value), 3 * sizeof(f32))); break; } case IVariable::QUAT: { Quat value; var->Get(value); f32 valueArray[4]; valueArray[0] = value.w; valueArray[1] = value.v.x; valueArray[2] = value.v.y; valueArray[3] = value.v.z; settings.setValue(keyType, IVariable::QUAT); settings.setValue(keyValue, QByteArray(reinterpret_cast(&value), 4 * sizeof(f32))); break; } case IVariable::STRING: { QString value; var->Get(value); settings.setValue(keyType, IVariable::STRING); settings.setValue(keyValue, value); break; } case IVariable::ARRAY: { break; } default: break; } } } ////////////////////////////////////////////////////////////////////////// void CModelViewport::RestoreDebugOptions() { QSettings settings; for (auto g : m_settingsPath.split('\\')) settings.beginGroup(g); f32 floatValue = .0f; UINT byteNum = sizeof(f32); QString strRead = ""; int32 iRead = 0; BOOL bRead = FALSE; f32 fRead = .0f; QByteArray pbtData; UINT bytes = 0; CVarBlock* vb = m_vars.GetVarBlock(); int32 vbCount = vb->GetNumVariables(); char keyType[64], keyValue[64]; for (int32 i = 0; i < vbCount; ++i) { IVariable* var = vb->GetVariable(i); IVariable::EType vType = var->GetType(); sprintf_s(keyType, "DebugOption_%s_type", var->GetName().toUtf8().data()); int32 iType = settings.value(keyType, 0).toInt(); sprintf_s(keyValue, "DebugOption_%s_value", var->GetName().toUtf8().data()); switch (iType) { case IVariable::UNKNOWN: { break; } case IVariable::INT: { iRead = settings.value(keyValue, 0).toInt(); var->Set(iRead); break; } case IVariable::BOOL: { bRead = settings.value(keyValue, FALSE).toBool(); var->Set(bRead); break; } case IVariable::FLOAT: { fRead = settings.value(keyValue).toDouble(); var->Set(fRead); break; } case IVariable::VECTOR: { pbtData = settings.value(keyValue).toByteArray(); assert(pbtData.count() == 3 * sizeof(f32)); f32* pfRead = reinterpret_cast(pbtData.data()); Vec3 vecRead(pfRead[0], pfRead[1], pfRead[2]); var->Set(vecRead); break; } case IVariable::QUAT: { pbtData = settings.value(keyValue).toByteArray(); assert(pbtData.count() == 4 * sizeof(f32)); f32* pfRead = reinterpret_cast(pbtData.data()); Quat valueRead(pfRead[0], pfRead[1], pfRead[2], pfRead[3]); var->Set(valueRead); break; } case IVariable::STRING: { strRead = settings.value(keyValue, "").toString(); var->Set(strRead); break; } case IVariable::ARRAY: { break; } default: break; } } } ////////////////////////////////////////////////////////////////////////// CModelViewport::~CModelViewport() { OnDestroy(); ReleaseObject(); GetIEditor()->FlushUndo(); SaveDebugOptions(); // Audio if (m_pAudioListener != NULL) { gEnv->pEntitySystem->RemoveEntity(m_pAudioListener->GetId(), true); assert(m_pAudioListener == NULL); } #if ENABLE_CRY_PHYSICS gEnv->pPhysicalWorld->GetPhysVars()->helperOffset.zero(); #else // helper offset?? CRY_PHYSICS_REPLACEMENT_ASSERT(); #endif // ENABLE_CRY_PHYSICS GetIEditor()->SetConsoleVar("ca_UsePhysics", 1); } ///////////////////////////////////////////////////////////////////////////// // CModelViewport message handlers ///////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void CModelViewport::ReleaseObject() { if (m_object) { m_object->Release(); m_object = NULL; } if (GetCharacterBase()) { m_pCharacterBase = 0; #if defined(EDITOR_PCDEBUGCODE) m_pAnimationSystem->DeleteDebugInstances(); #endif // defined(EDITOR_PCDEBUGCODE) } if (m_weaponModel) { m_weaponModel->Release(); m_weaponModel = NULL; } } ////////////////////////////////////////////////////////////////////////// void CModelViewport::LoadObject(const QString& fileName, float scale) { m_bPaused = false; // Load object. QString file = Path::MakeGamePath(fileName); bool reload = false; if (m_loadedFile == file) { reload = true; } m_loadedFile = file; SetName(tr("Model View - %1").arg(file)); ReleaseObject(); // Enables display of warning after model have been loaded. CErrorsRecorder errRecorder; if (IsPreviewableFileType(file.toUtf8().data())) { const QString fileExt = QFileInfo(file).completeSuffix(); // Try Load character. const bool isSKEL = (0 == fileExt.compare(CRY_SKEL_FILE_EXT, Qt::CaseInsensitive)); const bool isSKIN = (0 == fileExt.compare(CRY_SKIN_FILE_EXT, Qt::CaseInsensitive)); const bool isCGA = (0 == fileExt.compare(CRY_ANIM_GEOMETRY_FILE_EXT, Qt::CaseInsensitive)); const bool isCDF = (0 == fileExt.compare(CRY_CHARACTER_DEFINITION_FILE_EXT, Qt::CaseInsensitive)); if (isSKEL || isSKIN || isCGA || isCDF) { m_pCharacterBase = m_pAnimationSystem->CreateInstance(file.toUtf8().data()); if (GetCharacterBase()) { f32 radius = GetCharacterBase()->GetAABB().GetRadius(); Vec3 center = GetCharacterBase()->GetAABB().GetCenter(); m_AABB.min = center - Vec3(radius, radius, radius); m_AABB.max = center + Vec3(radius, radius, radius); if (!reload) { m_camRadius = center.z + radius; } } } else { LoadStaticObject(file); } } else { QMessageBox::warning(this, tr("Preview Error"), tr("Preview of this file type not supported.")); return; } //-------------------------------------------------------------------------------- if (!s_varsPanel) { // Regedit variable panel. s_varsPanel = new ReflectedPropertiesPanel(this); s_varsPanel->Setup(); s_varsPanel->AddVars(m_vars.GetVarBlock()); s_varsPanelId = GetIEditor()->AddRollUpPage(ROLLUP_OBJECTS, "Debug Options", s_varsPanel); } if (!reload) { Vec3 v = m_AABB.max - m_AABB.min; float radius = v.GetLength() / 2.0f; m_camRadius = radius * 2; } if (GetIEditor()->IsInPreviewMode()) { Physicalize(); } } ////////////////////////////////////////////////////////////////////////// void CModelViewport::LoadStaticObject(const QString& file) { if (m_object) { m_object->Release(); } // Load Static object. m_object = m_engine->LoadStatObjUnsafeManualRef(file.toUtf8().data(), 0, 0, false); if (!m_object) { CLogFile::WriteLine("Loading of object failed."); return; } m_object->AddRef(); // Generate thumbnail for this cgf. CThumbnailGenerator thumbGen; thumbGen.GenerateForFile(file); m_AABB.min = m_object->GetBoxMin(); m_AABB.max = m_object->GetBoxMax(); } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnRender() { FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); const QRect rc = contentsRect(); ProcessKeys(); if (m_renderer) { PreWidgetRendering(); m_Camera.SetFrustum(m_Camera.GetViewSurfaceX(), m_Camera.GetViewSurfaceZ(), m_Camera.GetFov(), 0.02f, 10000, m_Camera.GetPixelAspectRatio()); const int w = rc.width(); const int h = rc.height(); m_Camera.SetFrustum(w, h, DEG2RAD(mv_fov), 0.0101f, 10000.0f); if (GetIEditor()->IsInPreviewMode()) { GetISystem()->SetViewCamera(m_Camera); } Vec3 clearColor = mv_backgroundColor; m_renderer->SetClearColor(clearColor); m_renderer->SetCamera(m_Camera); auto colorf = ColorF(clearColor, 1.0f); m_renderer->ClearTargetsImmediately(FRT_CLEAR | FRT_CLEAR_IMMEDIATE, colorf); m_renderer->ResetToDefault(); SRenderingPassInfo passInfo = SRenderingPassInfo::CreateGeneralPassRenderingInfo(m_Camera, SRenderingPassInfo::DEFAULT_FLAGS, true); { CScopedWireFrameMode scopedWireFrame(m_renderer, mv_showWireframe1 ? R_WIREFRAME_MODE : R_SOLID_MODE); DrawModel(passInfo); } ICharacterManager* pCharMan = gEnv->pCharacterManager; if (pCharMan) { pCharMan->UpdateStreaming(-1, -1); } PostWidgetRendering(); } } ////////////////////////////////////////////////////////////////////////// void CModelViewport::DrawSkyBox(const SRenderingPassInfo& passInfo) { CRenderObject* pObj = m_renderer->EF_GetObject_Temp(passInfo.ThreadID()); pObj->m_II.m_Matrix.SetTranslationMat(GetViewTM().GetTranslation()); if (m_pSkyboxName) { SShaderItem skyBoxShaderItem(m_pSkyBoxShader); m_renderer->EF_AddEf(m_pRESky, skyBoxShaderItem, pObj, passInfo, EFSLIST_GENERAL, 1, SRendItemSorter::CreateRendItemSorter(passInfo)); } } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnAnimBack() { // TODO: Add your command handler code here } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnAnimFastBack() { // TODO: Add your command handler code here } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnAnimFastForward() { // TODO: Add your command handler code here } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnAnimFront() { // TODO: Add your command handler code here } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnAnimPlay() { // TODO: Add your command handler code here } ////////////////////////////////////////////////////////////////////////// void CModelViewport::mouseDoubleClickEvent(QMouseEvent* event) { // TODO: Add your message handler code here and/or call default CRenderViewport::mouseDoubleClickEvent(event); if (event->button() != Qt::LeftButton) { return; } Matrix34 tm; tm.SetIdentity(); SetViewTM(tm); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void CModelViewport::keyPressEvent(QKeyEvent* event) { if (GetCharacterBase()) { const UINT nChar = event->nativeVirtualKey(); const UINT nFlags = event->nativeModifiers(); int index = -1; if (nChar >= Qt::Key_0 && nChar <= Qt::Key_9 && (nFlags& Qt::KeypadModifier) == 0) { if (nChar == Qt::Key_0) { index = 10; } else { index = nChar - Qt::Key_1; } } if (nChar >= Qt::Key_0 && nChar <= Qt::Key_9 && (nFlags& Qt::KeypadModifier) != 0) { index = nChar - Qt::Key_0 + 10; if (nChar == Qt::Key_0) { index = 20; } } //if (nFlags& MK_CONTROL IAnimationSet* pAnimations = GetCharacterBase()->GetIAnimationSet(); if (pAnimations) { uint32 numAnims = pAnimations->GetAnimationCount(); if (index >= 0 && index < numAnims) { const char* animName = pAnimations->GetNameByAnimID(index); PlayAnimation(animName); } } } CRenderViewport::keyPressEvent(event); } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnLightColor(IVariable* var) { } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnShowNormals(IVariable* var) { bool enable = mv_showNormals; GetIEditor()->SetConsoleVar("r_ShowNormals", (enable) ? 1 : 0); } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnShowTangents(IVariable* var) { bool enable = mv_showTangents; GetIEditor()->SetConsoleVar("r_ShowTangents", (enable) ? 1 : 0); } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnCharPhysics(IVariable* var) { bool enable = mv_useCharPhysics; GetIEditor()->SetConsoleVar("ca_UsePhysics", enable); } ////////////////////////////////////////////////////////////////////////// void CModelViewport::AttachObjectToBone(const QString& model, const QString& bone) { if (!GetCharacterBase()) { return; } IAttachmentObject* pBindable = NULL; m_attachedCharacter = m_pAnimationSystem->CreateInstance(model.toUtf8().data()); if (m_attachedCharacter) { m_attachedCharacter->AddRef(); } if (m_weaponModel) { SAFE_RELEASE(m_weaponModel); } if (!m_attachedCharacter) { m_weaponModel = m_engine->LoadStatObjUnsafeManualRef(model.toUtf8().data(), 0, 0, false); m_weaponModel->AddRef(); } m_attachBone = bone; if (!pBindable) { const QString str = QStringLiteral("Loading of weapon model %1 failed.").arg(model); QMessageBox::critical(this, QString(), str); CLogFile::WriteLine(str.toUtf8().data()); return; } IAttachmentManager* pIAttachments = GetCharacterBase()->GetIAttachmentManager(); if (!m_attachedCharacter) { IAttachment* pAttachment = pIAttachments->CreateAttachment("BoneAttachment", CA_BONE, bone.toUtf8().data()); assert(pAttachment); pAttachment->AddBinding(pBindable); } } ////////////////////////////////////////////////////////////////////////// void CModelViewport::AttachObjectToFace(const QString& model) { if (!GetCharacterBase()) { return; } if (m_weaponModel) { m_weaponModel->Release(); } IAttachmentObject* pBindable = NULL; m_weaponModel = m_engine->LoadStatObjUnsafeManualRef(model.toUtf8().data(), 0, 0, false); m_weaponModel->AddRef(); if (!pBindable) { const QString str = QStringLiteral("Loading of weapon model %1 failed.").arg(model); QMessageBox::critical(this, QString(), str); CLogFile::WriteLine(str.toUtf8().data()); return; } IAttachmentManager* pAttachments = GetCharacterBase()->GetIAttachmentManager(); IAttachment* pIAttachment = pAttachments->CreateAttachment("FaceAttachment", CA_FACE); pIAttachment->AddBinding(pBindable); } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnShowShaders(IVariable* var) { bool bEnable = mv_showShaders; GetIEditor()->SetConsoleVar("r_ProfileShaders", bEnable); } void CModelViewport::OnDestroy() { ReleaseObject(); if (m_pRESky) { m_pRESky->Release(false); } if (m_rollupIndex) { GetIEditor()->RemoveRollUpPage(ROLLUP_OBJECTS, m_rollupIndex); m_rollupIndex = 0; } if (m_rollupIndex2) { GetIEditor()->RemoveRollUpPage(ROLLUP_OBJECTS, m_rollupIndex2); m_rollupIndex2 = 0; } if (s_varsPanelId) { GetIEditor()->RemoveRollUpPage(ROLLUP_OBJECTS, s_varsPanelId); s_varsPanelId = 0; } s_varsPanel = 0; } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnActivate() { } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnDeactivate() { } ////////////////////////////////////////////////////////////////////////// void CModelViewport::Update() { FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); CRenderViewport::Update(); if (m_pAudioListener != NULL) { m_pAudioListener->SetWorldTM(m_viewTM); } // Audio: listener update per viewport // Update particle effects. m_effectManager.Update(QuatT(m_PhysicalLocation)); DrawInfo(); } ////////////////////////////////////////////////////////////////////////// void CModelViewport::DrawInfo() const { if (GetIEditor()->Get3DEngine()) { ICVar* pDisplayInfo = gEnv->pConsole->GetCVar("r_DisplayInfo"); if (pDisplayInfo && pDisplayInfo->GetIVal() != 0) { const float fps = gEnv->pTimer->GetFrameRate(); const float x = (float)gEnv->pRenderer->GetWidth() - 5.0f; gEnv->p3DEngine->DrawTextRightAligned(x, 1, "FPS: %.2f", fps); int nPolygons, nShadowVolPolys; gEnv->pRenderer->GetPolyCount(nPolygons, nShadowVolPolys); int nDrawCalls = gEnv->pRenderer->GetCurrentNumberOfDrawCalls(); gEnv->p3DEngine->DrawTextRightAligned(x, 20, "Tris:%2d,%03d - DP:%d", nPolygons / 1000, nPolygons % 1000, nDrawCalls); } } } ////////////////////////////////////////////////////////////////////////// void CModelViewport::SetCustomMaterial(CMaterial* pMaterial) { m_pCurrentMaterial = pMaterial; } ////////////////////////////////////////////////////////////////////////// CMaterial* CModelViewport::GetMaterial() { if (m_pCurrentMaterial) { return m_pCurrentMaterial; } else { _smart_ptr pMtl = 0; if (m_object) { pMtl = m_object->GetMaterial(); } else if (GetCharacterBase()) { pMtl = GetCharacterBase()->GetIMaterial(); } CMaterial* pCMaterial = GetIEditor()->GetMaterialManager()->FromIMaterial(pMtl); return pCMaterial; } } ////////////////////////////////////////////////////////////////////////// bool CModelViewport::CanDrop(const QPoint& point, IDataBaseItem* pItem) { if (!pItem) { return false; } if (pItem->GetType() == EDB_TYPE_MATERIAL) { SetCustomMaterial((CMaterial*)pItem); } return true; } ////////////////////////////////////////////////////////////////////////// void CModelViewport::Drop(const QPoint& point, IDataBaseItem* pItem) { if (!pItem) { SetCustomMaterial(NULL); return; } if (pItem->GetType() == EDB_TYPE_MATERIAL) { SetCustomMaterial((CMaterial*)pItem); } } ////////////////////////////////////////////////////////////////////////// void CModelViewport::Physicalize() { #if ENABLE_CRY_PHYSICS IPhysicalWorld* pPhysWorld = gEnv->pPhysicalWorld; if (!pPhysWorld) { return; } if (!m_object && !GetCharacterBase()) { return; } if (m_pPhysicalEntity) { pPhysWorld->DestroyPhysicalEntity(m_pPhysicalEntity); if (GetCharacterBase()) { if (GetCharacterBase()->GetISkeletonPose()->GetCharacterPhysics(-1)) { pPhysWorld->DestroyPhysicalEntity(GetCharacterBase()->GetISkeletonPose()->GetCharacterPhysics(-1)); } GetCharacterBase()->GetISkeletonPose()->SetCharacterPhysics(NULL); } } // Add geometries. if (m_object) { m_pPhysicalEntity = pPhysWorld->CreatePhysicalEntity(PE_STATIC); if (!m_pPhysicalEntity) { return; } pe_geomparams params; params.flags = geom_colltype_ray; for (int i = 0; i < 4; i++) { if (m_object->GetPhysGeom(i)) { m_pPhysicalEntity->AddGeometry(m_object->GetPhysGeom(i), ¶ms); } } // Add all sub mesh geometries. for (int nobj = 0; nobj < m_object->GetSubObjectCount(); nobj++) { IStatObj* pStatObj = m_object->GetSubObject(nobj)->pStatObj; if (pStatObj) { params.pMtx3x4 = &m_object->GetSubObject(nobj)->tm; for (int i = 0; i < 4; i++) { if (pStatObj->GetPhysGeom(i)) { m_pPhysicalEntity->AddGeometry(pStatObj->GetPhysGeom(i), ¶ms); } } } } } else { if (GetCharacterBase()) { GetCharacterBase()->GetISkeletonPose()->DestroyCharacterPhysics(); m_pPhysicalEntity = pPhysWorld->CreatePhysicalEntity(PE_LIVING); IPhysicalEntity* pCharPhys = GetCharacterBase()->GetISkeletonPose()->CreateCharacterPhysics(m_pPhysicalEntity, 80.0f, -1, 70.0f); GetCharacterBase()->GetISkeletonPose()->CreateAuxilaryPhysics(pCharPhys, Matrix34(IDENTITY)); if (pCharPhys) { // make sure the skeleton goes before the ropes in the list pe_params_pos pp; pp.iSimClass = 6; pCharPhys->SetParams(&pp); pp.iSimClass = 4; pCharPhys->SetParams(&pp); } pe_player_dynamics pd; pd.bActive = 0; m_pPhysicalEntity->SetParams(&pd); } } // Set materials. CMaterial* pMaterial = GetMaterial(); if (pMaterial) { // Assign custom material to physics. int surfaceTypesId[MAX_SUB_MATERIALS]; memset(surfaceTypesId, 0, sizeof(surfaceTypesId)); int numIds = pMaterial->GetMatInfo()->FillSurfaceTypeIds(surfaceTypesId); pe_params_part ppart; ppart.nMats = numIds; ppart.pMatMapping = surfaceTypesId; (GetCharacterBase() && GetCharacterBase()->GetISkeletonPose()->GetCharacterPhysics() ? GetCharacterBase()->GetISkeletonPose()->GetCharacterPhysics() : m_pPhysicalEntity)->SetParams(&ppart); } #endif // ENABLE_CRY_PHYSICS } ////////////////////////////////////////////////////////////////////////// void CModelViewport::RePhysicalize() { #if ENABLE_CRY_PHYSICS m_pPhysicalEntity = NULL; #endif Physicalize(); } ////////////////////////////////////////////////////////////////////////// void CModelViewport::OnEntityEvent(IEntity* pEntity, SEntityEvent& event) { switch (event.event) { case ENTITY_EVENT_DONE: { // In case something destroys our listener entity before we had the chance to remove it. if (pEntity->GetId() == m_pAudioListener->GetId()) { gEnv->pEntitySystem->RemoveEntityEventListener(m_pAudioListener->GetId(), ENTITY_EVENT_DONE, this); m_pAudioListener = NULL; } break; } default: { break; } } } ////////////////////////////////////////////////////////////////////////// void CModelViewport::CreateAudioListener() { if (m_pAudioListener == NULL && gEnv->pEntitySystem) { SEntitySpawnParams oEntitySpawnParams; oEntitySpawnParams.sName = "AudioListener"; oEntitySpawnParams.pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("AudioListener"); m_pAudioListener = gEnv->pEntitySystem->SpawnEntity(oEntitySpawnParams, true); if (m_pAudioListener != NULL) { m_pAudioListener->SetFlags(m_pAudioListener->GetFlags() | ENTITY_FLAG_TRIGGER_AREAS); m_pAudioListener->SetFlagsExtended(m_pAudioListener->GetFlagsExtended() | ENTITY_FLAG_EXTENDED_AUDIO_LISTENER); gEnv->pEntitySystem->AddEntityEventListener(m_pAudioListener->GetId(), ENTITY_EVENT_DONE, this); CryFixedStringT<64> sTemp; sTemp.Format("AudioListener(%d)", static_cast(m_pAudioListener->GetId())); m_pAudioListener->SetName(sTemp.c_str()); IComponentAudioPtr pAudioComponent = m_pAudioListener->GetOrCreateComponent(); CRY_ASSERT(pAudioComponent.get()); } else { CryFatalError("