/* * 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 "LineGizmo.h" #include "DisplayContext.h" #include "../Viewport.h" #include "../DisplaySettings.h" #include "Objects/EntityObject.h" #include "Objects/Group.h" #include "GizmoManager.h" ////////////////////////////////////////////////////////////////////////// CLineGizmo::CLineGizmo() { m_color[0] = ColorF(0, 1, 1, 1); m_color[1] = ColorF(0, 1, 1, 1); } ////////////////////////////////////////////////////////////////////////// CLineGizmo::~CLineGizmo() { if (m_object[0]) { m_object[0]->RemoveEventListener(functor(*this, &CLineGizmo::OnObjectEvent)); } if (m_object[1]) { m_object[1]->RemoveEventListener(functor(*this, &CLineGizmo::OnObjectEvent)); } m_object[0] = 0; m_object[1] = 0; } ////////////////////////////////////////////////////////////////////////// void CLineGizmo::SetObjects(CBaseObject* pObject1, CBaseObject* pObject2, const QString& boneName) { assert(pObject1); assert(pObject2); m_object[0] = pObject1; m_object[1] = pObject2; m_boneName = boneName; m_object[0]->AddEventListener(functor(*this, &CLineGizmo::OnObjectEvent)); m_object[1]->AddEventListener(functor(*this, &CLineGizmo::OnObjectEvent)); CalcBounds(); } ////////////////////////////////////////////////////////////////////////// void CLineGizmo::OnObjectEvent(CBaseObject* object, int event) { if (event == CBaseObject::ON_TRANSFORM) { // One of objects transformed, recalc gizmo bounds. CalcBounds(); return; } if (event == CBaseObject::ON_DELETE) { // This gizmo must be deleted as well if one of the objects is deleted. GetIEditor()->GetObjectManager()->GetGizmoManager()->RemoveGizmo(this); return; } if (event == CBaseObject::ON_VISIBILITY) { // Check visibility of gizmo. bool bVisible = !m_object[0]->CheckFlags(OBJFLAG_INVISIBLE) && !m_object[1]->CheckFlags(OBJFLAG_INVISIBLE); if (bVisible) { SetFlags(GetFlags() & (~EGIZMO_HIDDEN)); } else { SetFlags(GetFlags() | EGIZMO_HIDDEN); } return; } } ////////////////////////////////////////////////////////////////////////// void CLineGizmo::Display(DisplayContext& dc) { if (dc.flags & DISPLAY_LINKS) { for (int i = 0; i < 2; ++i) { if (!m_object[i]->CheckFlags(OBJFLAG_PREFAB)) { continue; } if (m_object[i]->GetGroup() == NULL) { continue; } bool bGroupOpen = m_object[i]->GetGroup()->IsOpen(); bool bGroupSelected = m_object[i]->GetGroup()->IsSelected(); if (!bGroupOpen && !bGroupSelected) { return; } } // Draw line between objects. if (m_boneName.isEmpty() == false) { // If this is a bone attachment link, compute the exact position of the bone. assert(qobject_cast<CEntityObject*>(m_object[1])); IEntity* pIEntity = static_cast<CEntityObject*>(m_object[1].get())->GetIEntity(); if (pIEntity) { ICharacterInstance* pCharacter = pIEntity->GetCharacter(0); if (pCharacter) { IDefaultSkeleton& rIDefaultSkeleton = pCharacter->GetIDefaultSkeleton(); int jointID = rIDefaultSkeleton.GetJointIDByName(m_boneName.toUtf8().data()); if (jointID != -1) { m_point[1] = (QuatT(m_object[1]->GetWorldTM()) * pCharacter->GetISkeletonPose()->GetAbsJointByID(jointID)).t; } } } } dc.DrawLine(m_point[0], m_point[1], m_color[0], m_color[1]); //if (!(dc.flags & DISPLAY_HIDENAMES)) { Vec3 pos = 0.5f * (m_point[0] + m_point[1]); //dc.renderer->DrawLabelEx( p3+Vec3(0,0,0.3f),1.2f,col,true,true,m_name ); float camDist = dc.camera->GetPosition().GetDistance(pos); float maxDist = dc.settings->GetLabelsDistance(); if (camDist < dc.settings->GetLabelsDistance()) { float range = maxDist / 2.0f; float col[4] = { m_color[0].r, m_color[0].g, m_color[0].b, m_color[0].a }; if (camDist > range) { col[3] = col[3] * (1.0f - (camDist - range) / range); } dc.SetColor(col[0], col[1], col[2], col[3]); dc.DrawTextLabel(pos + Vec3(0, 0, 0.2f), 1.2f, m_name.toUtf8().data()); } } } } ////////////////////////////////////////////////////////////////////////// void CLineGizmo::CalcBounds() { m_bbox.Reset(); for (int i = 0; i < 2; i++) { bool IsObjectLight = false; if (qobject_cast<CEntityObject*>(m_object[i])) { CEntityObject* entityobject = static_cast<CEntityObject*>(m_object[i].get()); if (entityobject->IsLight()) { m_point[i] = entityobject->GetWorldPos(); IsObjectLight = true; } } if (IsObjectLight == false) { AABB box; m_object[i]->GetBoundBox(box); m_point[i] = 0.5f * Vec3(box.max + box.min); } m_bbox.Add(m_point[i]); } } ////////////////////////////////////////////////////////////////////////// void CLineGizmo::GetWorldBounds(AABB& bbox) { bbox = m_bbox; } ////////////////////////////////////////////////////////////////////////// void CLineGizmo::SetColor(const Vec3& color1, const Vec3& color2, float alpha1, float alpha2) { m_color[0] = ColorF(color1.x, color1.y, color1.z, alpha1); m_color[1] = ColorF(color2.x, color2.y, color2.z, alpha2); } ////////////////////////////////////////////////////////////////////////// void CLineGizmo::SetName(const char* sName) { m_name = sName; } ////////////////////////////////////////////////////////////////////////// bool CLineGizmo::HitTest(HitContext& hc) { return 0; /* if (hc.distanceTollerance != 0) return 0; Vec3 org = m_object->GetWorldPos(); float fScreenScale = hc.view->GetScreenScaleFactor(org); float size = gSettings.gizmo.axisGizmoSize * fScreenScale; Vec3 x(size,0,0); Vec3 y(0,size,0); Vec3 z(0,0,size); float hitDist = 0.01f * fScreenScale; ////////////////////////////////////////////////////////////////////////// // Calculate ray in local space of axis. ////////////////////////////////////////////////////////////////////////// Matrix34 tm; RefCoordSys refCoordSys = GetIEditor()->GetReferenceCoordSys(); if (refCoordSys == COORDS_LOCAL) { tm = m_object->GetWorldTM(); tm.NoScale(); } else { tm.SetIdentity(); tm.SetTranslation( m_object->GetWorldPos() ); } tm.Invert44(); Vec3 raySrc = tm.TransformPoint( hc.raySrc ); //CHANGED_BY_IVO //Vec3 rayDir = tm.TransformVector( hc.rayDir ); Vec3 rayDir = GetTransposed44(tm) * ( hc.rayDir ); ////////////////////////////////////////////////////////////////////////// Vec3 pnt; BBox box; box.min = - Vec3(hitDist*2,hitDist*2,hitDist*2); box.max = Vec3(size+hitDist*2,size+hitDist*2,size+hitDist*2); if (!box.IsIntersectRay( raySrc,rayDir,pnt )) { m_highlightAxis = 0; return false; } float axisdist[10]; Vec3 np[10]; Vec3 rayTrg = raySrc + rayDir*10000.0f; size *= 0.3f; Vec3 p1(size,size,0); Vec3 p2(size,0,size); Vec3 p3(0,size,size); axisdist[AXIS_X] = RayToLineDistance( raySrc,rayTrg,Vec3(0,0,0),x,np[AXIS_X] ); axisdist[AXIS_Y] = RayToLineDistance( raySrc,rayTrg,Vec3(0,0,0),y,np[AXIS_Y] ); axisdist[AXIS_Z] = RayToLineDistance( raySrc,rayTrg,Vec3(0,0,0),z,np[AXIS_Z] ); axisdist[AXIS_XY] = RayToLineDistance( raySrc,rayTrg,p1,p1-x*0.3f,np[AXIS_XY] ); axisdist[AXIS_XZ] = RayToLineDistance( raySrc,rayTrg,p2,p2-x*0.3f,np[AXIS_XZ] ); axisdist[AXIS_YZ] = RayToLineDistance( raySrc,rayTrg,p3,p3-y*0.3f,np[AXIS_YZ] ); float mindist = hitDist; int axis = 0; for (int i = AXIS_X; i <= AXIS_XZ; i++) { if (axisdist[i] < mindist) { mindist = axisdist[i]; axis = i; } } if (axis != 0) { hc.axis = axis; hc.object = m_object; hc.dist = GetDistance(raySrc,np[axis]); } m_highlightAxis = axis; return axis != 0; */ }