Merge branch 'main' into ly-as-sdk/LYN-2948
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
#Ignore these directories
|
||||
SDKs
|
||||
|
||||
#ignore these files
|
||||
*.user
|
||||
@@ -1,629 +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 "BackgroundScheduleManager.h"
|
||||
|
||||
namespace BackgroundScheduleManager
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CScheduleItem::CScheduleItem(const char* szName)
|
||||
: m_name(szName)
|
||||
, m_refCount(1)
|
||||
, m_state(eScheduleItemState_Pending)
|
||||
{
|
||||
}
|
||||
|
||||
CScheduleItem::~CScheduleItem()
|
||||
{
|
||||
CRY_ASSERT(m_refCount == 0);
|
||||
|
||||
for (TWorkItems::const_iterator it = m_workItems.begin();
|
||||
it != m_workItems.end(); ++it)
|
||||
{
|
||||
(*it)->Release();
|
||||
}
|
||||
}
|
||||
|
||||
const char* CScheduleItem::GetDescription() const
|
||||
{
|
||||
return m_name.c_str();
|
||||
}
|
||||
|
||||
EScheduleItemState CScheduleItem::GetState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
const float CScheduleItem::GetProgress() const
|
||||
{
|
||||
if (m_workItems.empty())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float totalProgress = 0.0f;
|
||||
|
||||
for (TWorkItems::const_iterator it = m_workItems.begin();
|
||||
it != m_workItems.end(); ++it)
|
||||
{
|
||||
totalProgress += (*it)->GetProgress();
|
||||
}
|
||||
|
||||
return totalProgress / (float)m_workItems.size();
|
||||
}
|
||||
}
|
||||
|
||||
const uint32 CScheduleItem::GetNumWorkItems() const
|
||||
{
|
||||
return m_workItems.size();
|
||||
}
|
||||
|
||||
IBackgroundScheduleItemWork* CScheduleItem::GetWorkItem(const uint32 index) const
|
||||
{
|
||||
return m_workItems[index];
|
||||
}
|
||||
|
||||
void CScheduleItem::AddWorkItem(IBackgroundScheduleItemWork* pWork)
|
||||
{
|
||||
// cannot add new work items when item has finished or failed
|
||||
if (m_state == eScheduleItemState_Failed || m_state == eScheduleItemState_Completed)
|
||||
{
|
||||
CryFatalError("Cannot add new work items when item has finished or failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// add to the work list
|
||||
if (m_state == eScheduleItemState_Processing)
|
||||
{
|
||||
m_addedWorkItems.push_back(pWork);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_workItems.push_back(pWork);
|
||||
}
|
||||
}
|
||||
|
||||
void CScheduleItem::AddRef()
|
||||
{
|
||||
CryInterlockedIncrement(&m_refCount);
|
||||
}
|
||||
|
||||
void CScheduleItem::Release()
|
||||
{
|
||||
const int nCount = CryInterlockedDecrement(&m_refCount);
|
||||
assert(nCount >= 0);
|
||||
if (nCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
else if (nCount < 0)
|
||||
{
|
||||
assert(0);
|
||||
CryFatalError("Deleting Reference Counted Object Twice");
|
||||
}
|
||||
}
|
||||
|
||||
void CScheduleItem::RequestStop()
|
||||
{
|
||||
if (m_state == eScheduleItemState_Pending)
|
||||
{
|
||||
// we can stop right away :)
|
||||
m_state = eScheduleItemState_Failed;
|
||||
}
|
||||
else if (m_state == eScheduleItemState_Processing)
|
||||
{
|
||||
m_state = eScheduleItemState_Stopping;
|
||||
|
||||
// signal all pending work to stop
|
||||
uint32 curIndex = 0;
|
||||
while (curIndex < m_processedWorkItems.size())
|
||||
{
|
||||
IBackgroundScheduleItemWork* pWork = m_processedWorkItems[curIndex];
|
||||
if (pWork->OnStop())
|
||||
{
|
||||
// if the work was stopped remove it from list
|
||||
m_processedWorkItems.erase(m_processedWorkItems.begin() + curIndex);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this work item cannot be stopped this frame
|
||||
curIndex += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if all pending work has been stopped we can assume the failed state
|
||||
if (m_processedWorkItems.empty())
|
||||
{
|
||||
m_state = eScheduleItemState_Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EScheduleWorkItemStatus CScheduleItem::Update()
|
||||
{
|
||||
EScheduleWorkItemStatus retStatus = eScheduleWorkItemStatus_NotFinished;
|
||||
|
||||
switch (m_state)
|
||||
{
|
||||
// finial state - work failed
|
||||
case eScheduleItemState_Failed:
|
||||
{
|
||||
retStatus = eScheduleWorkItemStatus_Failed;
|
||||
break;
|
||||
}
|
||||
|
||||
// final state - work completed
|
||||
case eScheduleItemState_Completed:
|
||||
{
|
||||
retStatus = eScheduleWorkItemStatus_Finished;
|
||||
break;
|
||||
}
|
||||
|
||||
// first update, start all the work items
|
||||
case eScheduleItemState_Pending:
|
||||
{
|
||||
// start all of the tasks
|
||||
bool bHasFailedStarts = false;
|
||||
for (TWorkItems::const_iterator it = m_workItems.begin();
|
||||
it != m_workItems.end(); ++it)
|
||||
{
|
||||
IBackgroundScheduleItemWork* pWork = (*it);
|
||||
|
||||
if (pWork->OnStart())
|
||||
{
|
||||
m_processedWorkItems.push_back(pWork);
|
||||
}
|
||||
else
|
||||
{
|
||||
bHasFailedStarts = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bHasFailedStarts)
|
||||
{
|
||||
m_state = eScheduleItemState_Stopping;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = eScheduleItemState_Processing;
|
||||
/* FALLS THROUGHT TO PROCESSING STATE */
|
||||
}
|
||||
}
|
||||
|
||||
// work processing state
|
||||
case eScheduleItemState_Processing:
|
||||
{
|
||||
// process new work items that were added while the schedule was created
|
||||
if (!m_addedWorkItems.empty())
|
||||
{
|
||||
for (TWorkItems::const_iterator it = m_addedWorkItems.begin();
|
||||
it != m_addedWorkItems.end(); ++it)
|
||||
{
|
||||
IBackgroundScheduleItemWork* pWork = (*it);
|
||||
pWork->OnStart();
|
||||
m_processedWorkItems.push_back(pWork);
|
||||
m_workItems.push_back(pWork);
|
||||
}
|
||||
|
||||
m_addedWorkItems.clear();
|
||||
}
|
||||
|
||||
// update work items
|
||||
bool bHasFailedItems = false;
|
||||
TWorkItems completedItems;
|
||||
for (TWorkItems::const_iterator it = m_processedWorkItems.begin();
|
||||
it != m_processedWorkItems.end(); ++it)
|
||||
{
|
||||
IBackgroundScheduleItemWork* pWork = (*it);
|
||||
|
||||
// update given work item
|
||||
const EScheduleWorkItemStatus status = pWork->OnUpdate();
|
||||
if (status == eScheduleWorkItemStatus_Finished)
|
||||
{
|
||||
completedItems.push_back(pWork);
|
||||
continue;
|
||||
}
|
||||
|
||||
// item failed - we need to stop other tasks
|
||||
if (status == eScheduleWorkItemStatus_Failed)
|
||||
{
|
||||
bHasFailedItems = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup completed items
|
||||
for (TWorkItems::iterator it = completedItems.begin();
|
||||
it != completedItems.end(); ++it)
|
||||
{
|
||||
IBackgroundScheduleItemWork* pWork = (*it);
|
||||
TWorkItems::iterator jt = std::find(m_processedWorkItems.begin(), m_processedWorkItems.end(), pWork);
|
||||
m_processedWorkItems.erase(jt);
|
||||
}
|
||||
|
||||
if (!bHasFailedItems)
|
||||
{
|
||||
// all work has finished
|
||||
if (m_processedWorkItems.empty())
|
||||
{
|
||||
retStatus = eScheduleWorkItemStatus_Finished;
|
||||
m_state = eScheduleItemState_Completed;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// some of the items failed
|
||||
m_state = eScheduleItemState_Stopping;
|
||||
/* FALL THROUGH TO STOPPING STATE */
|
||||
}
|
||||
}
|
||||
|
||||
// We are stopping failed work
|
||||
case eScheduleItemState_Stopping:
|
||||
{
|
||||
uint32 curIndex = 0;
|
||||
while (curIndex < m_processedWorkItems.size())
|
||||
{
|
||||
IBackgroundScheduleItemWork* pWork = m_processedWorkItems[curIndex];
|
||||
if (pWork->OnStop())
|
||||
{
|
||||
// if the work was stopped remove it from list
|
||||
m_processedWorkItems.erase(m_processedWorkItems.begin() + curIndex);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this work item cannot be stopped this frame
|
||||
curIndex += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if all pending work has been stopped we can assume the failed state
|
||||
if (m_processedWorkItems.empty())
|
||||
{
|
||||
m_state = eScheduleItemState_Failed;
|
||||
return eScheduleWorkItemStatus_Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CSchedule::CSchedule(const char* szName)
|
||||
: m_name(szName)
|
||||
, m_refCount(1)
|
||||
, m_bCanceled(false)
|
||||
, m_currentItem(0)
|
||||
, m_state(eScheduleState_Pending)
|
||||
{
|
||||
}
|
||||
|
||||
CSchedule::~CSchedule()
|
||||
{
|
||||
CRY_ASSERT(m_refCount == 0);
|
||||
|
||||
for (TItems::const_iterator it = m_items.begin();
|
||||
it != m_items.end(); ++it)
|
||||
{
|
||||
CScheduleItem* pItem = *it;
|
||||
SAFE_RELEASE(pItem);
|
||||
}
|
||||
|
||||
m_items.clear();
|
||||
}
|
||||
|
||||
const char* CSchedule::GetDescription() const
|
||||
{
|
||||
return m_name.c_str();
|
||||
}
|
||||
|
||||
float CSchedule::GetProgress() const
|
||||
{
|
||||
if (m_currentItem >= m_items.size())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float itemProgress = 1.0f / (float)(m_items.size());
|
||||
const IBackgroundScheduleItem* pItem = m_items[m_currentItem];
|
||||
return (m_currentItem + pItem->GetProgress()) * itemProgress;
|
||||
}
|
||||
}
|
||||
|
||||
IBackgroundScheduleItem* CSchedule::GetProcessedItem() const
|
||||
{
|
||||
if (m_currentItem >= m_items.size())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
IBackgroundScheduleItem* pItem = m_items[m_currentItem];
|
||||
return pItem;
|
||||
}
|
||||
}
|
||||
|
||||
const uint32 CSchedule::GetNumItems() const
|
||||
{
|
||||
return m_items.size();
|
||||
}
|
||||
|
||||
IBackgroundScheduleItem* CSchedule::GetItem(const uint32 index) const
|
||||
{
|
||||
return m_items[index];
|
||||
}
|
||||
|
||||
EScheduleState CSchedule::GetState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void CSchedule::Cancel()
|
||||
{
|
||||
m_bCanceled = true;
|
||||
}
|
||||
|
||||
bool CSchedule::IsCanceled() const
|
||||
{
|
||||
return m_bCanceled;
|
||||
}
|
||||
|
||||
void CSchedule::AddItem(IBackgroundScheduleItem* pItem)
|
||||
{
|
||||
if (NULL == pItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we can add items only in the "pending" state
|
||||
if (pItem->GetState() != eScheduleItemState_Pending)
|
||||
{
|
||||
CryFatalError("Schedule items can be added to schedule only before their work starts");
|
||||
return;
|
||||
}
|
||||
|
||||
// item has no jobs, do not add
|
||||
if (pItem->GetNumWorkItems() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_items.push_back(static_cast<CScheduleItem*>(pItem));
|
||||
pItem->AddRef();
|
||||
}
|
||||
|
||||
void CSchedule::AddRef()
|
||||
{
|
||||
CryInterlockedIncrement(&m_refCount);
|
||||
}
|
||||
|
||||
void CSchedule::Release()
|
||||
{
|
||||
const int nCount = CryInterlockedDecrement(&m_refCount);
|
||||
assert(nCount >= 0);
|
||||
if (nCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
else if (nCount < 0)
|
||||
{
|
||||
assert(0);
|
||||
CryFatalError("Deleting Reference Counted Object Twice");
|
||||
}
|
||||
}
|
||||
|
||||
EScheduleWorkItemStatus CSchedule::Update()
|
||||
{
|
||||
EScheduleWorkItemStatus retStatus = eScheduleWorkItemStatus_NotFinished;
|
||||
|
||||
// we have a cancel request
|
||||
if (m_bCanceled)
|
||||
{
|
||||
CryLog("Schedule '%s' was canceled", GetDescription());
|
||||
|
||||
if (m_state == eScheduleState_Processing && m_currentItem < m_items.size())
|
||||
{
|
||||
// stop the current item
|
||||
CScheduleItem* pItem = m_items[m_currentItem];
|
||||
pItem->RequestStop();
|
||||
m_state = eSccheduleState_Stopping;
|
||||
}
|
||||
else if (m_state != eScheduleState_Completed)
|
||||
{
|
||||
m_state = eScheduleState_Failed;
|
||||
return eScheduleWorkItemStatus_Failed;
|
||||
}
|
||||
}
|
||||
|
||||
// process internal state machine
|
||||
switch (m_state)
|
||||
{
|
||||
// final state - work failed
|
||||
case eScheduleState_Failed:
|
||||
{
|
||||
retStatus = eScheduleWorkItemStatus_Failed;
|
||||
break;
|
||||
}
|
||||
|
||||
// final state - work completed
|
||||
case eScheduleState_Completed:
|
||||
{
|
||||
retStatus = eScheduleWorkItemStatus_Finished;
|
||||
break;
|
||||
}
|
||||
|
||||
// stopping current task
|
||||
case eSccheduleState_Stopping:
|
||||
{
|
||||
if (m_currentItem < m_items.size())
|
||||
{
|
||||
CScheduleItem* pItem = m_items[m_currentItem];
|
||||
if (pItem->Update() != eScheduleWorkItemStatus_NotFinished)
|
||||
{
|
||||
// task was finally stopped
|
||||
m_state = eScheduleState_Failed;
|
||||
retStatus = eScheduleWorkItemStatus_Failed;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// first update, switch to processing
|
||||
case eScheduleState_Pending:
|
||||
{
|
||||
m_state = eScheduleState_Processing;
|
||||
m_currentItem = 0;
|
||||
/* FALLS THROUGHT */
|
||||
}
|
||||
|
||||
// if we were in the processing phase inform the current schedule item to stop all it's work
|
||||
case eScheduleState_Processing:
|
||||
{
|
||||
// update schedule items
|
||||
while (m_currentItem < m_items.size())
|
||||
{
|
||||
CScheduleItem* pItem = m_items[m_currentItem];
|
||||
|
||||
const EScheduleWorkItemStatus itemStatus = pItem->Update();
|
||||
if (itemStatus == eScheduleWorkItemStatus_Finished)
|
||||
{
|
||||
m_currentItem += 1;
|
||||
continue;
|
||||
}
|
||||
else if (itemStatus == eScheduleWorkItemStatus_Failed)
|
||||
{
|
||||
m_state = eScheduleState_Failed;
|
||||
retStatus = eScheduleWorkItemStatus_Failed;
|
||||
gEnv->pLog->LogWarning("Schedule '%s' failed on item '%s'.", GetDescription(), pItem->GetDescription());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// all items updated
|
||||
if (m_currentItem >= m_items.size())
|
||||
{
|
||||
// empty schedule, complete in one tick
|
||||
m_state = eScheduleState_Completed;
|
||||
retStatus = eScheduleWorkItemStatus_Finished;
|
||||
CryLog("Schedule '%s' completed", GetDescription());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CScheduleManager::CScheduleManager()
|
||||
{
|
||||
GetIEditor()->RegisterNotifyListener(this);
|
||||
}
|
||||
|
||||
CScheduleManager::~CScheduleManager()
|
||||
{
|
||||
GetIEditor()->UnregisterNotifyListener(this);
|
||||
|
||||
for (TSchedules::const_iterator it = m_schedules.begin();
|
||||
it != m_schedules.end(); ++it)
|
||||
{
|
||||
CSchedule* pSchedule = *it;
|
||||
SAFE_RELEASE(pSchedule);
|
||||
}
|
||||
|
||||
m_schedules.clear();
|
||||
}
|
||||
|
||||
IBackgroundSchedule* CScheduleManager::CreateSchedule(const char* szName)
|
||||
{
|
||||
return new CSchedule(szName);
|
||||
}
|
||||
|
||||
IBackgroundScheduleItem* CScheduleManager::CreateScheduleItem(const char* szName)
|
||||
{
|
||||
return new CScheduleItem(szName);
|
||||
}
|
||||
|
||||
void CScheduleManager::SubmitSchedule(IBackgroundSchedule* pSchedule)
|
||||
{
|
||||
if (NULL != pSchedule)
|
||||
{
|
||||
if (pSchedule->GetState() != eScheduleState_Pending)
|
||||
{
|
||||
CryFatalError("Only schedules with pending state can be submitted");
|
||||
return;
|
||||
}
|
||||
|
||||
pSchedule->AddRef();
|
||||
m_schedules.push_back(static_cast<CSchedule*>(pSchedule));
|
||||
}
|
||||
}
|
||||
|
||||
const uint32 CScheduleManager::GetNumSchedules() const
|
||||
{
|
||||
return m_schedules.size();
|
||||
}
|
||||
|
||||
IBackgroundSchedule* CScheduleManager::GetSchedule(const uint32 index) const
|
||||
{
|
||||
return m_schedules[index];
|
||||
}
|
||||
|
||||
void CScheduleManager::Update()
|
||||
{
|
||||
while (!m_schedules.empty())
|
||||
{
|
||||
CSchedule* pSchedule = m_schedules[0];
|
||||
|
||||
const EScheduleWorkItemStatus status = pSchedule->Update();
|
||||
if (status == eScheduleWorkItemStatus_NotFinished)
|
||||
{
|
||||
// we need more work next frame
|
||||
break;
|
||||
}
|
||||
|
||||
// schedule has finished, remove current reference
|
||||
m_schedules.erase(m_schedules.begin());
|
||||
SAFE_RELEASE(pSchedule);
|
||||
}
|
||||
}
|
||||
|
||||
void CScheduleManager::OnEditorNotifyEvent(EEditorNotifyEvent ev)
|
||||
{
|
||||
switch (ev)
|
||||
{
|
||||
case eNotify_OnQuit:
|
||||
GetIEditor()->UnregisterNotifyListener(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
} // BackgroundScheduleManager
|
||||
@@ -1,117 +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_BACKGROUNDSCHEDULEMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_BACKGROUNDSCHEDULEMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include "Include/IBackgroundScheduleManager.h"
|
||||
|
||||
namespace BackgroundScheduleManager
|
||||
{
|
||||
class CScheduleItem
|
||||
: public IBackgroundScheduleItem
|
||||
{
|
||||
private:
|
||||
std::string m_name;
|
||||
volatile int m_refCount;
|
||||
|
||||
EScheduleItemState m_state;
|
||||
|
||||
typedef std::vector<IBackgroundScheduleItemWork*> TWorkItems;
|
||||
TWorkItems m_workItems;
|
||||
TWorkItems m_addedWorkItems;
|
||||
TWorkItems m_processedWorkItems;
|
||||
|
||||
public:
|
||||
CScheduleItem(const char* szName);
|
||||
virtual ~CScheduleItem();
|
||||
|
||||
// IBackgroundScheduleItem interface
|
||||
virtual const char* GetDescription() const;
|
||||
virtual EScheduleItemState GetState() const;
|
||||
virtual const float GetProgress() const;
|
||||
virtual const uint32 GetNumWorkItems() const;
|
||||
virtual IBackgroundScheduleItemWork* GetWorkItem(const uint32 index) const;
|
||||
virtual void AddWorkItem(IBackgroundScheduleItemWork* pWork);
|
||||
virtual void AddRef();
|
||||
virtual void Release();
|
||||
|
||||
// Update schedule item
|
||||
EScheduleWorkItemStatus Update();
|
||||
|
||||
// Request to stop work in this item
|
||||
void RequestStop();
|
||||
};
|
||||
|
||||
class CSchedule
|
||||
: public IBackgroundSchedule
|
||||
{
|
||||
private:
|
||||
std::string m_name;
|
||||
volatile int m_refCount;
|
||||
bool m_bCanceled;
|
||||
|
||||
EScheduleState m_state;
|
||||
|
||||
typedef std::vector<CScheduleItem*> TItems;
|
||||
TItems m_items;
|
||||
|
||||
uint32 m_currentItem;
|
||||
|
||||
public:
|
||||
CSchedule(const char* szName);
|
||||
virtual ~CSchedule();
|
||||
|
||||
// IBackgroundSchedule interface
|
||||
virtual const char* GetDescription() const;
|
||||
virtual float GetProgress() const;
|
||||
virtual IBackgroundScheduleItem* GetProcessedItem() const;
|
||||
virtual const uint32 GetNumItems() const;
|
||||
virtual IBackgroundScheduleItem* GetItem(const uint32 index) const;
|
||||
virtual EScheduleState GetState() const;
|
||||
virtual void Cancel();
|
||||
virtual bool IsCanceled() const;
|
||||
virtual void AddItem(IBackgroundScheduleItem* pItem);
|
||||
virtual void AddRef();
|
||||
virtual void Release();
|
||||
|
||||
// Update schedule item
|
||||
EScheduleWorkItemStatus Update();
|
||||
};
|
||||
|
||||
class CScheduleManager
|
||||
: public IBackgroundScheduleManager
|
||||
, public IEditorNotifyListener
|
||||
{
|
||||
private:
|
||||
typedef std::vector<CSchedule*> TSchedules;
|
||||
TSchedules m_schedules;
|
||||
|
||||
public:
|
||||
CScheduleManager();
|
||||
virtual ~CScheduleManager();
|
||||
|
||||
// IBackgroundScheduleManager interface
|
||||
virtual IBackgroundSchedule* CreateSchedule(const char* szName);
|
||||
virtual IBackgroundScheduleItem* CreateScheduleItem(const char* szName);
|
||||
virtual void SubmitSchedule(IBackgroundSchedule* pSchedule);
|
||||
virtual const uint32 GetNumSchedules() const;
|
||||
virtual IBackgroundSchedule* GetSchedule(const uint32 index) const;
|
||||
virtual void Update();
|
||||
|
||||
// IEditorNotifyListener interface implementation
|
||||
virtual void OnEditorNotifyEvent(EEditorNotifyEvent ev) override;
|
||||
};
|
||||
}
|
||||
#endif // CRYINCLUDE_EDITOR_BACKGROUNDSCHEDULEMANAGER_H
|
||||
@@ -1,410 +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 "BackgroundTaskManager.h"
|
||||
|
||||
namespace BackgroundTaskManager
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CTaskManager::CThread::CThread(class CTaskManager* pManager, CQueue* pQueue)
|
||||
: m_pManager(pManager)
|
||||
, m_pQueue(pQueue)
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
CTaskManager::CThread::~CThread()
|
||||
{
|
||||
}
|
||||
|
||||
void CTaskManager::CThread::WaitForThread()
|
||||
{
|
||||
wait();
|
||||
}
|
||||
|
||||
void CTaskManager::CThread::run()
|
||||
{
|
||||
CryThreadSetName(-1, "BackgroundTaskThread");
|
||||
|
||||
while (!m_pManager->IsStopped())
|
||||
{
|
||||
STaskHandle taskHandle;
|
||||
|
||||
// This blocks on Semaphore waiting for task from queue
|
||||
m_pQueue->PopTask(taskHandle);
|
||||
|
||||
// Should not happen but it's a stupid way to crash :)
|
||||
if (NULL == taskHandle.pTask)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (taskHandle.pTask->IsCanceled())
|
||||
{
|
||||
// Task was canceled before we got here
|
||||
m_pManager->AddCompletedTask(taskHandle, eTaskResult_Canceled);
|
||||
}
|
||||
else
|
||||
{
|
||||
const ETaskResult state = taskHandle.pTask->Work();
|
||||
|
||||
if (state == eTaskResult_Resume)
|
||||
{
|
||||
// Put it back into queue, so more important task can take over.
|
||||
m_pManager->AddTask(taskHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Finish task
|
||||
m_pManager->AddCompletedTask(taskHandle, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CTaskManager::CQueue::CQueue()
|
||||
: m_semaphore(INT_MAX, 0) // no good maximum value, assume worst case
|
||||
{
|
||||
}
|
||||
|
||||
void CTaskManager::CQueue::AddTask(const STaskHandle& taskHandle)
|
||||
{
|
||||
{
|
||||
CryAutoLock<CryMutex> lock(m_lock);
|
||||
|
||||
// TODO: use heap?
|
||||
m_pendingTasks.insert(m_pendingTasks.begin(), taskHandle);
|
||||
std::stable_sort(m_pendingTasks.begin(), m_pendingTasks.end());
|
||||
}
|
||||
|
||||
taskHandle.pTask->SetState(eTaskState_Pending);
|
||||
|
||||
// release internal semaphore so threads can pick up the work
|
||||
m_semaphore.Release();
|
||||
}
|
||||
|
||||
void CTaskManager::CQueue::PopTask(STaskHandle& outTaskHandle)
|
||||
{
|
||||
// wait for job
|
||||
m_semaphore.Acquire();
|
||||
|
||||
{
|
||||
CryAutoLock<CryMutex> lock(m_lock);
|
||||
|
||||
if (m_pendingTasks.empty())
|
||||
{
|
||||
outTaskHandle.pTask = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
outTaskHandle = m_pendingTasks.back();
|
||||
outTaskHandle.pTask->SetState(eTaskState_Working);
|
||||
m_pendingTasks.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTaskManager::CQueue::ReleaseSemaphore()
|
||||
{
|
||||
m_semaphore.Release();
|
||||
}
|
||||
|
||||
void CTaskManager::CQueue::Clear()
|
||||
{
|
||||
CryAutoLock<CryMutex> lock(m_lock);
|
||||
for (uint i = 0; i < m_pendingTasks.size(); ++i)
|
||||
{
|
||||
m_pendingTasks[i].pTask->Release();
|
||||
}
|
||||
|
||||
m_pendingTasks.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CTaskManager::CTaskManager()
|
||||
: m_bStop(false)
|
||||
, m_nextTaskID(1)
|
||||
, m_listeners(1)
|
||||
{
|
||||
GetIEditor()->RegisterNotifyListener(this);
|
||||
}
|
||||
|
||||
CTaskManager::~CTaskManager()
|
||||
{
|
||||
if (!m_bStop)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void CTaskManager::Start(const uint32 threadCount /*=kDefaultThreadCount*/)
|
||||
{
|
||||
m_bStop = false;
|
||||
|
||||
if (m_pThreads.empty())
|
||||
{
|
||||
// Always create one IO thread
|
||||
{
|
||||
CThread* pThread = new CThread(this, &m_pendingTasks[ eTaskThreadMask_IO ]);
|
||||
m_pThreads.push_back(pThread);
|
||||
}
|
||||
|
||||
// We also need at least one generic thread
|
||||
const uint32 numGenericThreads = max<uint32>(threadCount, 1);
|
||||
for (uint32 i = 0; i < numGenericThreads; ++i)
|
||||
{
|
||||
CThread* pThread = new CThread(this, &m_pendingTasks[ eTaskThreadMask_Any ]);
|
||||
m_pThreads.push_back(pThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTaskManager::StartScheduledTasks()
|
||||
{
|
||||
CryAutoLock<CryMutex> lock(m_tasksLock);
|
||||
|
||||
if (!m_scheduledTasks.empty())
|
||||
{
|
||||
const unsigned int time = GetTickCount();
|
||||
while (!m_scheduledTasks.empty())
|
||||
{
|
||||
const int delta = (int)(time - m_scheduledTasks[0].time);
|
||||
if (delta > 0)
|
||||
{
|
||||
// the soonest task on the list is still in the future, no point in looking at the next entries in the list
|
||||
break;
|
||||
}
|
||||
|
||||
// promote the scheduled task to be a full task
|
||||
AddTask(m_scheduledTasks[0].handle);
|
||||
|
||||
// We held a reference to the task on list, release it
|
||||
m_scheduledTasks[0].handle.pTask->Release();
|
||||
|
||||
m_scheduledTasks.erase(m_scheduledTasks.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTaskManager::Stop()
|
||||
{
|
||||
if (!m_bStop)
|
||||
{
|
||||
m_bStop = true;
|
||||
GetIEditor()->UnregisterNotifyListener(this);
|
||||
|
||||
// clear queues - no new tasks will be processed
|
||||
for (uint32 i = 0; i < eTaskThreadMask_COUNT; ++i)
|
||||
{
|
||||
m_pendingTasks[i].Clear();
|
||||
}
|
||||
|
||||
// kick all the threads to allow them to quit
|
||||
for (uint32 j = 0; j < m_pThreads.size(); ++j)
|
||||
{
|
||||
for (uint32 i = 0; i < eTaskThreadMask_COUNT; ++i)
|
||||
{
|
||||
m_pendingTasks[i].ReleaseSemaphore();
|
||||
}
|
||||
}
|
||||
|
||||
// Stop threads
|
||||
for (TWorkerThreads::iterator it = m_pThreads.begin();
|
||||
it != m_pThreads.end(); ++it)
|
||||
{
|
||||
(*it)->WaitForThread();
|
||||
delete *it;
|
||||
}
|
||||
|
||||
m_pThreads.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CTaskManager::AddListener(IBackgroundTaskManagerListener* pListener, const char* name)
|
||||
{
|
||||
m_listeners.Add(pListener, name);
|
||||
}
|
||||
|
||||
void CTaskManager::RemoveListener(IBackgroundTaskManagerListener* pListener)
|
||||
{
|
||||
m_listeners.Remove(pListener);
|
||||
}
|
||||
|
||||
void CTaskManager::AddTask(IBackgroundTask* pTask, ETaskPriority priority, ETaskThreadMask threadMask)
|
||||
{
|
||||
MAKE_SURE(pTask != 0, return );
|
||||
|
||||
// keep an extra reference to the task in the manager
|
||||
pTask->AddRef();
|
||||
|
||||
STaskHandle handle;
|
||||
handle.id = CryInterlockedIncrement(&m_nextTaskID);
|
||||
handle.priority = priority;
|
||||
handle.threadMask = threadMask;
|
||||
handle.pTask = pTask;
|
||||
|
||||
AddTask(handle);
|
||||
|
||||
for (TListeners::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next())
|
||||
{
|
||||
notifier->OnBackgroundTaskAdded(pTask->Description());
|
||||
}
|
||||
}
|
||||
|
||||
void CTaskManager::ScheduleTask(IBackgroundTask* pTask, ETaskPriority priority, int delayMilliseconds, ETaskThreadMask threadMask)
|
||||
{
|
||||
MAKE_SURE(delayMilliseconds >= 0, return );
|
||||
MAKE_SURE(pTask != 0, return );
|
||||
|
||||
// keep an extra reference to the task in the manager
|
||||
pTask->AddRef();
|
||||
|
||||
SScheduledTask task;
|
||||
task.time = GetTickCount() + delayMilliseconds;
|
||||
task.handle.pTask = pTask;
|
||||
task.handle.id = CryInterlockedIncrement(&m_nextTaskID);
|
||||
task.handle.threadMask = threadMask;
|
||||
task.handle.priority = priority;
|
||||
|
||||
{
|
||||
CryAutoLock<CryMutex> lock(m_tasksLock);
|
||||
m_scheduledTasks.push_back(task);
|
||||
}
|
||||
|
||||
for (TListeners::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next())
|
||||
{
|
||||
notifier->OnBackgroundTaskAdded(pTask->Description());
|
||||
}
|
||||
}
|
||||
|
||||
void CTaskManager::AddTask(const STaskHandle& handle)
|
||||
{
|
||||
MAKE_SURE(handle.pTask != 0, return );
|
||||
MAKE_SURE(handle.id != 0, return );
|
||||
|
||||
// add task to appropriate queue (every thread mask has it's own queue)
|
||||
m_pendingTasks[handle.threadMask].AddTask(handle);
|
||||
}
|
||||
|
||||
void CTaskManager::AddCompletedTask(const STaskHandle& handle, ETaskResult resultState)
|
||||
{
|
||||
CryAutoLock<CryMutex> lock(m_tasksLock);
|
||||
|
||||
CRY_ASSERT(handle.pTask->GetState() == eTaskState_Working);
|
||||
CRY_ASSERT(resultState != eTaskResult_Resume);
|
||||
|
||||
// Update task state
|
||||
switch (resultState)
|
||||
{
|
||||
case eTaskResult_Canceled:
|
||||
{
|
||||
handle.pTask->SetState(eTaskState_Canceled);
|
||||
break;
|
||||
}
|
||||
|
||||
case eTaskResult_Completed:
|
||||
{
|
||||
handle.pTask->SetState(eTaskState_Completed);
|
||||
break;
|
||||
}
|
||||
|
||||
case eTaskResult_Failed:
|
||||
{
|
||||
handle.pTask->SetState(eTaskState_Failed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add to the list of completed tasks (for calling the Finalize)
|
||||
// TODO: some of the tasks do not require Finalize() and they could be released here instead of the main thread
|
||||
SCompletedTask info;
|
||||
info.pTask = handle.pTask;
|
||||
info.id = handle.id;
|
||||
info.state = resultState;
|
||||
m_completedTasks.push_back(info);
|
||||
}
|
||||
|
||||
void CTaskManager::Update()
|
||||
{
|
||||
std::vector<SCompletedTask> completedTasks;
|
||||
{
|
||||
CryAutoLock<CryMutex> lock(m_tasksLock);
|
||||
m_completedTasks.swap(completedTasks);
|
||||
}
|
||||
|
||||
// call finalize for the completed tasks
|
||||
for (size_t i = 0; i < completedTasks.size(); ++i)
|
||||
{
|
||||
SCompletedTask& handle = completedTasks[i];
|
||||
|
||||
if (NULL != handle.pTask)
|
||||
{
|
||||
string description = handle.pTask->Description(); // copy string as the description is used after pTask is destroyed
|
||||
|
||||
if (handle.state == eTaskResult_Completed)
|
||||
{
|
||||
if (description && description[0] != '\0')
|
||||
{
|
||||
gEnv->pLog->Log("Task Completed: %s", description.c_str());
|
||||
}
|
||||
}
|
||||
else if (handle.state == eTaskResult_Failed)
|
||||
{
|
||||
if (description && description[0] != '\0' && !handle.pTask->FailReported())
|
||||
{
|
||||
gEnv->pLog->LogError("Task Failed: %s ", description.c_str());
|
||||
|
||||
const char* errorMessage = handle.pTask->ErrorMessage();
|
||||
if (errorMessage && errorMessage[0] != '\0')
|
||||
{
|
||||
gEnv->pLog->LogError("\tReason: [%s]", errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle.pTask->Finalize();
|
||||
|
||||
// release the internal (task manager) reference.
|
||||
// Tthis is usually the last reference to the task so it gets deleted here.
|
||||
handle.pTask->Release();
|
||||
|
||||
for (TListeners::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next())
|
||||
{
|
||||
notifier->OnBackgroundTaskCompleted(handle.state, description.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTaskManager::OnEditorNotifyEvent(EEditorNotifyEvent ev)
|
||||
{
|
||||
switch (ev)
|
||||
{
|
||||
case eNotify_OnInit:
|
||||
Start();
|
||||
break;
|
||||
case eNotify_OnIdleUpdate:
|
||||
Update();
|
||||
break;
|
||||
case eNotify_OnQuit:
|
||||
Stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,161 +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_BACKGROUNDTASKMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_BACKGROUNDTASKMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include "Include/IBackgroundTaskManager.h"
|
||||
#include "CryListenerSet.h"
|
||||
|
||||
#include <QThread>
|
||||
|
||||
namespace BackgroundTaskManager
|
||||
{
|
||||
typedef int TTaskID;
|
||||
|
||||
struct STaskHandle
|
||||
{
|
||||
ETaskPriority priority;
|
||||
ETaskThreadMask threadMask;
|
||||
TTaskID id;
|
||||
IBackgroundTask* pTask;
|
||||
|
||||
bool operator<(const STaskHandle& rhs) const
|
||||
{
|
||||
if (priority < rhs.priority)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (priority > rhs.priority)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return id < rhs.id;
|
||||
}
|
||||
};
|
||||
|
||||
struct SCompletedTask
|
||||
{
|
||||
ETaskResult state;
|
||||
TTaskID id;
|
||||
ETaskThreadMask threadMask;
|
||||
IBackgroundTask* pTask;
|
||||
};
|
||||
|
||||
struct SScheduledTask
|
||||
{
|
||||
unsigned int time;
|
||||
STaskHandle handle;
|
||||
};
|
||||
|
||||
class CTaskManager
|
||||
: public IBackgroundTaskManager
|
||||
, public IEditorNotifyListener
|
||||
{
|
||||
public:
|
||||
CTaskManager();
|
||||
~CTaskManager();
|
||||
|
||||
// IBackgroundTaskManager interface implementation
|
||||
virtual void AddTask(IBackgroundTask* pTask, ETaskPriority priority, ETaskThreadMask threadMask) override;
|
||||
virtual void ScheduleTask(IBackgroundTask* pTask, ETaskPriority priority, int delayMilliseconds, ETaskThreadMask threadMask) override;
|
||||
void AddListener(IBackgroundTaskManagerListener* pListener, const char* name) override;
|
||||
void RemoveListener(IBackgroundTaskManagerListener* pListener) override;
|
||||
|
||||
private:
|
||||
// IEditorNotifyListener interface implementation
|
||||
virtual void OnEditorNotifyEvent(EEditorNotifyEvent ev) override;
|
||||
|
||||
void Start(const uint32 threadCount = kDefaultThreadCount);
|
||||
void Stop();
|
||||
void StartScheduledTasks();
|
||||
void AddTask(const STaskHandle& outTask);
|
||||
void AddCompletedTask(const STaskHandle& outTask, ETaskResult resultState);
|
||||
void Update();
|
||||
|
||||
inline bool IsStopped() const
|
||||
{
|
||||
return m_bStop;
|
||||
}
|
||||
|
||||
private:
|
||||
// Internal queue (per thread mask)
|
||||
class CQueue
|
||||
{
|
||||
public:
|
||||
CQueue();
|
||||
|
||||
// Add task to list
|
||||
void AddTask(const STaskHandle& taskHandle);
|
||||
|
||||
// Pop task from list
|
||||
void PopTask(STaskHandle& outTaskHandle);
|
||||
|
||||
// Release thread semaphore without adding a task
|
||||
void ReleaseSemaphore();
|
||||
|
||||
// Remove all pending tasks
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
CrySemaphore m_semaphore;
|
||||
std::vector<STaskHandle> m_pendingTasks;
|
||||
CryMutex m_lock;
|
||||
};
|
||||
|
||||
// Worker thread class implementation
|
||||
class CThread : public QThread
|
||||
{
|
||||
public:
|
||||
CThread(CTaskManager* pManager, CQueue* pQueue);
|
||||
~CThread();
|
||||
|
||||
void WaitForThread();
|
||||
|
||||
private:
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
CTaskManager* m_pManager;
|
||||
CQueue* m_pQueue;
|
||||
};
|
||||
|
||||
private:
|
||||
static const uint32 kMaxThreadCloseWaitTime = 10000; // ms
|
||||
static const uint32 kDefaultThreadCount = 4; // good enough for LiveCreate (main user right now), do not set to less than 2
|
||||
|
||||
CQueue m_pendingTasks[ eTaskThreadMask_COUNT ];
|
||||
|
||||
// Task scheduled for execution in the future
|
||||
std::vector<SScheduledTask> m_scheduledTasks;
|
||||
|
||||
// Completed tasks (waiting for the "finalize" call)
|
||||
std::vector<SCompletedTask> m_completedTasks;
|
||||
|
||||
volatile TTaskID m_nextTaskID;
|
||||
|
||||
typedef std::vector<CThread*> TWorkerThreads;
|
||||
TWorkerThreads m_pThreads;
|
||||
|
||||
CryMutex m_tasksLock;
|
||||
bool m_bStop;
|
||||
|
||||
typedef CListenerSet<IBackgroundTaskManagerListener*> TListeners;
|
||||
TListeners m_listeners;
|
||||
};
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_BACKGROUNDTASKMANAGER_H
|
||||
@@ -112,7 +112,6 @@ ly_add_target(
|
||||
3rdParty::zlib
|
||||
3rdParty::AWSNativeSDK::STS
|
||||
Legacy::CryCommon
|
||||
Legacy::CryCommon.EngineSettings.Static
|
||||
Legacy::EditorCommon
|
||||
AZ::AzCore
|
||||
AZ::AzToolsFramework
|
||||
|
||||
@@ -1,821 +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 "CurveEditorCtrl.h"
|
||||
|
||||
// Qt
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
|
||||
namespace CurveEditor
|
||||
{
|
||||
const int kHandleSize = 6;
|
||||
const int kHandleSizeHalf = kHandleSize / 2;
|
||||
const int kDefaultPadding = 10;
|
||||
const int kInfoFontSize = 7;
|
||||
const int kGrid = 4;
|
||||
const QColor kColor_SelectCross(132, 132, 132);
|
||||
const QColor kColor_DisabledCross(90, 90, 90);
|
||||
const QColor kColor_MiddleLines(80, 80, 80);
|
||||
const QColor kColor_Background(41, 41, 41);
|
||||
const QColor kColor_Disabled(60, 60, 60);
|
||||
const QColor kColor_PaddingBorder(128, 128, 128);
|
||||
const QColor kColor_Text(128, 128, 128);
|
||||
const QColor kColor_TextCrtPos(187, 187, 187);
|
||||
const QColor kColor_Curve(255, 0, 0);
|
||||
const QColor kColor_SelHandle(200, 200, 200);
|
||||
const QColor kColor_NormalHandle(30, 30, 30);
|
||||
const QColor kColor_HandleLight(60, 60, 60);
|
||||
const QColor kColor_HandleShadow(0, 0, 0);
|
||||
const QColor kColor_MarkLines(0, 255, 0);
|
||||
}
|
||||
|
||||
|
||||
CCurveEditorCtrl::CCurveEditorCtrl(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_domainMinX = 0.0f;
|
||||
m_domainMinY = 0.0f;
|
||||
m_domainMaxX = 1.0f;
|
||||
m_domainMaxY = 1.0f;
|
||||
m_bMouseDown = m_bDragging = false;
|
||||
m_bAllowMouse = true;
|
||||
m_padding = CurveEditor::kDefaultPadding;
|
||||
m_flags = eFlag_ShowVerticalRuler
|
||||
| eFlag_ShowHorizontalRuler
|
||||
| eFlag_ShowVerticalRulerText
|
||||
| eFlag_ShowHorizontalRulerText
|
||||
| eFlag_ShowPaddingBorder
|
||||
| eFlag_ShowMovingPointAxis
|
||||
| eFlag_ShowPointHandles;
|
||||
m_gridSplits.set(CurveEditor::kGrid, CurveEditor::kGrid);
|
||||
m_fntInfo.setFamily("Arial");
|
||||
m_fntInfo.setPointSize(CurveEditor::kInfoFontSize);
|
||||
m_bHovered = false;
|
||||
m_selCrossPen = QPen(CurveEditor::kColor_SelectCross);
|
||||
|
||||
GenerateDefaultCurve();
|
||||
}
|
||||
|
||||
CCurveEditorCtrl::~CCurveEditorCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::SetFlags(UINT aFlags)
|
||||
{
|
||||
m_flags = aFlags;
|
||||
}
|
||||
|
||||
UINT CCurveEditorCtrl::GetFlags() const
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
bool CCurveEditorCtrl::SetDomainBounds(float aMinX, float aMinY, float aMaxX, float aMaxY)
|
||||
{
|
||||
assert(aMinX < aMaxX);
|
||||
assert(aMinY < aMaxY);
|
||||
|
||||
if (aMinX >= aMaxX)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aMinY >= aMaxY)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_domainMinX = aMinX;
|
||||
m_domainMinY = aMinY;
|
||||
m_domainMaxX = aMaxX;
|
||||
m_domainMaxY = aMaxY;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::GetDomainBounds(float& rMinX, float& rMinY, float& rMaxX, float& rMaxY) const
|
||||
{
|
||||
rMinX = m_domainMinX;
|
||||
rMinY = m_domainMinY;
|
||||
rMaxX = m_domainMaxX;
|
||||
rMaxY = m_domainMaxY;
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::SetGrid(UINT aHorizontalSplits, UINT aVerticalSplits, const QStringList& labelsX, const QStringList& labelsY)
|
||||
{
|
||||
assert(aHorizontalSplits);
|
||||
assert(aVerticalSplits);
|
||||
|
||||
if (!aHorizontalSplits)
|
||||
{
|
||||
// defaults
|
||||
aHorizontalSplits = 2;
|
||||
}
|
||||
|
||||
if (!aVerticalSplits)
|
||||
{
|
||||
// defaults
|
||||
aVerticalSplits = 2;
|
||||
}
|
||||
|
||||
m_gridSplits.x = aHorizontalSplits;
|
||||
m_gridSplits.y = aVerticalSplits;
|
||||
|
||||
if (!labelsX.isEmpty())
|
||||
{
|
||||
m_labelsX = labelsX;
|
||||
}
|
||||
|
||||
if (!labelsY.isEmpty())
|
||||
{
|
||||
m_labelsY = labelsY;
|
||||
}
|
||||
}
|
||||
|
||||
QPoint CCurveEditorCtrl::ProjectPoint(float x, float y)
|
||||
{
|
||||
QPoint pt;
|
||||
|
||||
pt.setX(m_padding + (width() - m_padding * 2) * (x - m_domainMinX) / (m_domainMaxX - m_domainMinX));
|
||||
pt.setY(m_padding + (height() - m_padding * 2) * (1.0f - (y - m_domainMinY) / (m_domainMaxY - m_domainMinY)));
|
||||
|
||||
return pt;
|
||||
}
|
||||
|
||||
Vec2 CCurveEditorCtrl::UnprojectPoint(const QPoint& pt)
|
||||
{
|
||||
Vec2 vec;
|
||||
int y = height() - pt.y();
|
||||
float dx = (width() - m_padding * 2);
|
||||
float dy = (height() - m_padding * 2);
|
||||
const float kEpsilon = 0.00000001f;
|
||||
|
||||
if (fabs(dx) <= kEpsilon)
|
||||
{
|
||||
dx = 1.0f;
|
||||
}
|
||||
|
||||
if (fabs(dy) <= kEpsilon)
|
||||
{
|
||||
dy = 1.0f;
|
||||
}
|
||||
|
||||
vec.x = m_domainMinX + (float)(pt.x() - m_padding) / dx * (m_domainMaxX - m_domainMinX);
|
||||
vec.y = m_domainMinY + (float)(y - m_padding) / dy * (m_domainMaxY - m_domainMinY);
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::SetControlPointCount(UINT aCount)
|
||||
{
|
||||
m_points.resize(aCount);
|
||||
m_projectedPoints.clear();
|
||||
}
|
||||
|
||||
UINT CCurveEditorCtrl::GetControlPointCount() const
|
||||
{
|
||||
return m_points.size();
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::AddControlPoint(const Vec2& rPosition)
|
||||
{
|
||||
m_points.push_back(CurvePoint(rPosition.x, rPosition.y));
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::ClearControlPoints()
|
||||
{
|
||||
m_points.clear();
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::SetControlPoint(UINT aIndex, const Vec2& rPosition)
|
||||
{
|
||||
assert(aIndex < m_points.size());
|
||||
|
||||
if (aIndex >= m_points.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_points[aIndex].pos = rPosition;
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::SetControlPointTangents(UINT aIndex, const Vec2& rLeft, const Vec2& rRight)
|
||||
{
|
||||
assert(aIndex < m_points.size());
|
||||
|
||||
if (aIndex >= m_points.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_points[aIndex].tanA = rLeft;
|
||||
m_points[aIndex].tanB = rRight;
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::GetControlPoint(UINT aIndex, Vec2& rOutPosition) const
|
||||
{
|
||||
assert(aIndex < m_points.size());
|
||||
|
||||
if (aIndex >= m_points.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rOutPosition = m_points[aIndex].pos;
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::GetControlPointTangents(UINT aIndex, Vec2& rOutLeft, Vec2& rOutRight) const
|
||||
{
|
||||
assert(aIndex < m_points.size());
|
||||
|
||||
if (aIndex >= m_points.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rOutLeft = m_points[aIndex].tanA;
|
||||
rOutRight = m_points[aIndex].tanB;
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QWidget::paintEvent(event);
|
||||
|
||||
QPainter dc(this);
|
||||
|
||||
QRect rc = geometry();
|
||||
QString str;
|
||||
QRect textSize;
|
||||
|
||||
dc.setFont(m_fntInfo);
|
||||
QFontMetrics fntMetrics(m_fntInfo);
|
||||
|
||||
if (m_flags & eFlag_Disabled)
|
||||
{
|
||||
// If disabled, just draw a blank square.
|
||||
dc.fillRect(rc, CurveEditor::kColor_Disabled);
|
||||
|
||||
dc.setPen(CurveEditor::kColor_DisabledCross);
|
||||
dc.drawLine(0, 0, rc.width(), rc.height());
|
||||
|
||||
dc.drawLine(rc.width(), 0, 0, rc.height());
|
||||
return;
|
||||
}
|
||||
|
||||
dc.fillRect(rc, CurveEditor::kColor_Background);
|
||||
|
||||
dc.setPen(CurveEditor::kColor_MiddleLines);
|
||||
|
||||
if (m_flags & eFlag_ShowVerticalRuler)
|
||||
{
|
||||
float y = m_domainMinY;
|
||||
float grid = (m_domainMaxY - m_domainMinY) / m_gridSplits.y;
|
||||
QPoint p;
|
||||
|
||||
for (int i = 0; i <= m_gridSplits.y; ++i)
|
||||
{
|
||||
p = ProjectPoint(0, y);
|
||||
dc.drawLine(m_padding, p.y(), rc.width() - m_padding, p.y());
|
||||
|
||||
if (m_flags & eFlag_ShowVerticalRulerText)
|
||||
{
|
||||
if (m_labelsY.empty())
|
||||
{
|
||||
str.asprintf("%0.2f", y);
|
||||
}
|
||||
else
|
||||
{
|
||||
str = m_labelsY[i];
|
||||
}
|
||||
textSize = fntMetrics.tightBoundingRect(str);
|
||||
dc.drawText(2, p.y(), str);
|
||||
}
|
||||
|
||||
y += grid;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flags & eFlag_ShowHorizontalRuler)
|
||||
{
|
||||
float x = m_domainMinX;
|
||||
float grid = (m_domainMaxX - m_domainMinX) / m_gridSplits.x;
|
||||
QPoint p;
|
||||
|
||||
for (int i = 0; i <= m_gridSplits.x; ++i)
|
||||
{
|
||||
p = ProjectPoint(x, 0);
|
||||
dc.drawLine(p.x(), m_padding, p.x(), rc.height() - m_padding);
|
||||
|
||||
if (m_flags & eFlag_ShowHorizontalRulerText)
|
||||
{
|
||||
if (m_labelsX.empty())
|
||||
{
|
||||
str.asprintf("%0.2f", x);
|
||||
}
|
||||
else
|
||||
{
|
||||
str = m_labelsX[i];
|
||||
}
|
||||
textSize = fntMetrics.tightBoundingRect(str);
|
||||
|
||||
p.setX(p.x() + 2);
|
||||
|
||||
if (p.x() + textSize.width() > width())
|
||||
{
|
||||
p.setX(width() - textSize.width());
|
||||
}
|
||||
|
||||
dc.drawText(p.x(), height() - m_padding + textSize.height() + 2, str);
|
||||
}
|
||||
|
||||
x += grid;
|
||||
}
|
||||
}
|
||||
|
||||
dc.setPen(CurveEditor::kColor_MarkLines);
|
||||
|
||||
if (m_flags & eFlag_ShowVerticalRuler)
|
||||
{
|
||||
QPoint p;
|
||||
for (size_t i = 0; i < m_marksY.size(); ++i)
|
||||
{
|
||||
float v = m_marksY[i];
|
||||
if (v < m_domainMinY || v > m_domainMaxY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
p = ProjectPoint(0, v);
|
||||
dc.drawLine(m_padding, p.y(), width() - m_padding, p.y());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flags & eFlag_ShowHorizontalRuler)
|
||||
{
|
||||
QPoint p;
|
||||
for (size_t i = 0; i < m_marksX.size(); ++i)
|
||||
{
|
||||
float v = m_marksX[i];
|
||||
if (v < m_domainMinX || v > m_domainMaxX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
p = ProjectPoint(v, 0);
|
||||
dc.drawLine(p.x(), m_padding, p.x(), height() - m_padding);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flags & eFlag_ShowPaddingBorder)
|
||||
{
|
||||
dc.setPen(CurveEditor::kColor_PaddingBorder);
|
||||
dc.drawRect(m_padding, m_padding, width() - m_padding * 2, height() - m_padding * 2);
|
||||
}
|
||||
|
||||
if (m_bDragging
|
||||
&& !m_selectedIndices.empty()
|
||||
&& (m_flags & eFlag_ShowMovingPointAxis))
|
||||
{
|
||||
const Vec2& crtPos = m_points[m_selectedIndices[0]].pos;
|
||||
|
||||
dc.setBrush(CurveEditor::kColor_TextCrtPos);
|
||||
str.asprintf("(%0.2f,%0.2f)", crtPos.x, crtPos.y);
|
||||
textSize = fntMetrics.tightBoundingRect(str);
|
||||
const int kOffsetFromPointer = 5;
|
||||
QPoint txtPos(m_lastMousePoint.x() + kOffsetFromPointer, m_lastMousePoint.y() + kOffsetFromPointer);
|
||||
|
||||
if (txtPos.x() + textSize.width() > width())
|
||||
{
|
||||
txtPos.setX(width() - textSize.width());
|
||||
}
|
||||
|
||||
if (txtPos.y() + textSize.height() > height())
|
||||
{
|
||||
txtPos.setY(height() - textSize.height());
|
||||
}
|
||||
|
||||
dc.drawText(txtPos, str);
|
||||
}
|
||||
|
||||
ComputeTangents();
|
||||
UpdateProjectedPoints();
|
||||
|
||||
// for curve debug, tangents poly, don't delete
|
||||
// dc.setPen(Qt::black);
|
||||
// dc.drawPolyline(m_projectedPoints.data(), m_projectedPoints.size());
|
||||
|
||||
dc.setPen(CurveEditor::kColor_Curve);
|
||||
|
||||
// curve
|
||||
QPainterPath bezierPath;
|
||||
bezierPath.moveTo(m_projectedPoints[0]);
|
||||
for (int i = 1; i < m_projectedPoints.size(); i += 3)
|
||||
{
|
||||
bezierPath.cubicTo(m_projectedPoints[i], m_projectedPoints[i + 1], m_projectedPoints[i + 2]);
|
||||
}
|
||||
dc.drawPath(bezierPath);
|
||||
|
||||
// curve control point handles
|
||||
if (m_flags & eFlag_ShowPointHandles)
|
||||
{
|
||||
for (size_t i = 0; i < m_points.size(); ++i)
|
||||
{
|
||||
QPoint ptProj = ProjectPoint(m_points[i].pos.x, m_points[i].pos.y);
|
||||
QRect rcHandle(0, 0, CurveEditor::kHandleSize, CurveEditor::kHandleSize);
|
||||
rcHandle.moveCenter(ptProj);
|
||||
|
||||
std::vector<int>::iterator iter =
|
||||
std::find(m_selectedIndices.begin(), m_selectedIndices.end(), i);
|
||||
|
||||
bool bSelected = (iter != m_selectedIndices.end());
|
||||
|
||||
if (bSelected && m_bDragging)
|
||||
{
|
||||
dc.setPen(m_selCrossPen);
|
||||
dc.drawLine(0, ptProj.y(), width(), ptProj.y());
|
||||
dc.drawLine(ptProj.x(), 0, ptProj.x(), height());
|
||||
}
|
||||
|
||||
dc.fillRect(rcHandle, bSelected
|
||||
? CurveEditor::kColor_SelHandle
|
||||
: CurveEditor::kColor_NormalHandle);
|
||||
|
||||
dc.setPen(CurveEditor::kColor_HandleLight);
|
||||
dc.drawLine(ptProj.x() - CurveEditor::kHandleSizeHalf, ptProj.y() - CurveEditor::kHandleSizeHalf,
|
||||
ptProj.x() - CurveEditor::kHandleSizeHalf, ptProj.y() + CurveEditor::kHandleSizeHalf);
|
||||
dc.drawLine(ptProj.x() - CurveEditor::kHandleSizeHalf, ptProj.y() + CurveEditor::kHandleSizeHalf,
|
||||
ptProj.x() + CurveEditor::kHandleSizeHalf, ptProj.y() + CurveEditor::kHandleSizeHalf);
|
||||
dc.setPen(CurveEditor::kColor_HandleShadow);
|
||||
dc.drawLine(ptProj.x() + CurveEditor::kHandleSizeHalf, ptProj.y() + CurveEditor::kHandleSizeHalf,
|
||||
ptProj.x() + CurveEditor::kHandleSizeHalf, ptProj.y() - CurveEditor::kHandleSizeHalf);
|
||||
dc.drawLine(ptProj.x() + CurveEditor::kHandleSizeHalf, ptProj.y() - CurveEditor::kHandleSizeHalf,
|
||||
ptProj.x() - CurveEditor::kHandleSizeHalf, ptProj.y() - CurveEditor::kHandleSizeHalf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::ComputeTangents()
|
||||
{
|
||||
for (size_t i = 0; i < m_points.size(); ++i)
|
||||
{
|
||||
m_points[i].tanA = m_points[i].pos;
|
||||
m_points[i].tanB = m_points[i].pos;
|
||||
}
|
||||
|
||||
int maxIndex = m_points.size() - 1;
|
||||
|
||||
for (size_t i = 0; i < m_points.size(); ++i)
|
||||
{
|
||||
if (i > maxIndex)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Vec2& p2 = m_points[i].pos;
|
||||
Vec2& back = m_points[i].tanA;
|
||||
Vec2& forw = m_points[i].tanB;
|
||||
const float kEpsilon = 0.000001f;
|
||||
|
||||
// first point
|
||||
if (i == 0)
|
||||
{
|
||||
back = p2;
|
||||
|
||||
if (maxIndex == 1)
|
||||
{
|
||||
Vec2& p3 = m_points[i + 1].pos;
|
||||
forw = p2 + (p3 - p2) / 3.0f;
|
||||
}
|
||||
else if (maxIndex > 0)
|
||||
{
|
||||
Vec2& p3 = m_points[i + 1].pos;
|
||||
Vec2& pb3 = m_points[i + 1].tanA;
|
||||
|
||||
float lenOsn = (pb3 - p2).GetLength();
|
||||
float lenb = (p3 - p2).GetLength();
|
||||
|
||||
if (lenOsn > kEpsilon && lenb > kEpsilon)
|
||||
{
|
||||
forw = p2 + (pb3 - p2) / (lenOsn / lenb * 3.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
forw = p2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i == maxIndex)
|
||||
{
|
||||
forw = p2;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
Vec2& p1 = m_points[i - 1].pos;
|
||||
Vec2& pf1 = m_points[i - 1].tanB;
|
||||
|
||||
float lenOsn = (pf1 - p2).GetLength();
|
||||
float lenf = (p1 - p2).GetLength();
|
||||
|
||||
if (lenOsn > kEpsilon && lenf > kEpsilon)
|
||||
{
|
||||
back = p2 + (pf1 - p2) / (lenOsn / lenf * 3.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
back = p2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (i >= 1 && i <= maxIndex - 1)
|
||||
{
|
||||
Vec2& p1 = m_points[i - 1].pos;
|
||||
Vec2& p3 = m_points[i + 1].pos;
|
||||
|
||||
float lenOsn = (p3 - p1).GetLength();
|
||||
float lenb = (p1 - p2).GetLength();
|
||||
float lenf = (p3 - p2).GetLength();
|
||||
|
||||
if (lenOsn > kEpsilon
|
||||
&& lenf > kEpsilon
|
||||
&& lenb > kEpsilon)
|
||||
{
|
||||
back = p2 + (p1 - p3) * (lenb / lenOsn / 3.0f);
|
||||
forw = p2 + (p3 - p1) * (lenf / lenOsn / 3.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ClampToDomain(back);
|
||||
ClampToDomain(forw);
|
||||
}
|
||||
|
||||
// fix tangents in relation of one to another
|
||||
for (size_t i = 0; i < m_points.size(); ++i)
|
||||
{
|
||||
Vec2& p = m_points[i].pos;
|
||||
Vec2& tanA = m_points[i].tanA;
|
||||
Vec2& tanB = m_points[i].tanB;
|
||||
|
||||
if (i < m_points.size() - 1)
|
||||
{
|
||||
if (tanB.x > m_points[i + 1].tanA.x)
|
||||
{
|
||||
tanB.x = (m_points[i + 1].pos.x + p.x) * 0.5f;
|
||||
}
|
||||
}
|
||||
if (i > 0)
|
||||
{
|
||||
if (tanA.x < m_points[i - 1].tanB.x)
|
||||
{
|
||||
tanA.x = (m_points[i - 1].pos.x + p.x) * 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::UpdateProjectedPoints()
|
||||
{
|
||||
m_projectedPoints.resize(m_points.size() * 3 - 2);
|
||||
|
||||
int numPts = 0;
|
||||
|
||||
for (size_t i = 0; i < m_points.size(); ++i)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
m_projectedPoints[numPts++] = ProjectPoint(m_points[i].pos.x, m_points[i].pos.y);
|
||||
m_projectedPoints[numPts++] = ProjectPoint(m_points[i].tanB.x, m_points[i].tanB.y);
|
||||
}
|
||||
else if (i == m_points.size() - 1)
|
||||
{
|
||||
m_projectedPoints[numPts++] = ProjectPoint(m_points[i].tanA.x, m_points[i].tanA.y);
|
||||
m_projectedPoints[numPts++] = ProjectPoint(m_points[i].pos.x, m_points[i].pos.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_projectedPoints[numPts++] = ProjectPoint(m_points[i].tanA.x, m_points[i].tanA.y);
|
||||
m_projectedPoints[numPts++] = ProjectPoint(m_points[i].pos.x, m_points[i].pos.y);
|
||||
m_projectedPoints[numPts++] = ProjectPoint(m_points[i].tanB.x, m_points[i].tanB.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::ClampToDomain(Vec2& rVec)
|
||||
{
|
||||
if (rVec.x < m_domainMinX)
|
||||
{
|
||||
rVec.x = m_domainMinX;
|
||||
}
|
||||
else if (rVec.x > m_domainMaxX)
|
||||
{
|
||||
rVec.x = m_domainMaxX;
|
||||
}
|
||||
|
||||
if (rVec.y < m_domainMinY)
|
||||
{
|
||||
rVec.y = m_domainMinY;
|
||||
}
|
||||
else if (rVec.y > m_domainMaxY)
|
||||
{
|
||||
rVec.y = m_domainMaxY;
|
||||
}
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::GenerateDefaultCurve()
|
||||
{
|
||||
m_points.clear();
|
||||
m_domainMinX = 0.0f;
|
||||
m_domainMinY = 0.0f;
|
||||
m_domainMaxX = 1.0f;
|
||||
m_domainMaxY = 1.0f;
|
||||
m_points.push_back(CurvePoint(0.00f, 0.00f));
|
||||
m_points.push_back(CurvePoint(0.25f, 0.25f));
|
||||
m_points.push_back(CurvePoint(0.50f, 0.50f));
|
||||
m_points.push_back(CurvePoint(0.75f, 0.75f));
|
||||
m_points.push_back(CurvePoint(1.00f, 1.00f));
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
QWidget::mousePressEvent(event);
|
||||
if (event->button() != Qt::LeftButton)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const QPoint point = event->pos();
|
||||
if (m_bAllowMouse)
|
||||
{
|
||||
bool bSimpleSelect = !(event->modifiers() & Qt::ShiftModifier) && !(event->modifiers() & Qt::ControlModifier);
|
||||
|
||||
if (bSimpleSelect)
|
||||
{
|
||||
m_selectedIndices.clear();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_points.size(); ++i)
|
||||
{
|
||||
QPoint ptProj = ProjectPoint(m_points[i].pos.x, m_points[i].pos.y);
|
||||
|
||||
QRect rcHandle(0, 0, CurveEditor::kHandleSize, CurveEditor::kHandleSize);
|
||||
rcHandle.moveCenter(ptProj);
|
||||
|
||||
if (rcHandle.contains(point))
|
||||
{
|
||||
if (bSimpleSelect)
|
||||
{
|
||||
m_selectedIndices.push_back(i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (event->modifiers() & Qt::ShiftModifier)
|
||||
{
|
||||
m_selectedIndices.push_back(i);
|
||||
}
|
||||
else if (event->modifiers() & Qt::ControlModifier)
|
||||
{
|
||||
std::vector<int>::iterator iter =
|
||||
std::find(m_selectedIndices.begin(), m_selectedIndices.end(), i);
|
||||
|
||||
if (iter == m_selectedIndices.end())
|
||||
{
|
||||
m_selectedIndices.push_back(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_selectedIndices.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bMouseDown = true;
|
||||
m_lastMousePoint = point;
|
||||
}
|
||||
|
||||
grabMouse();
|
||||
update();
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
if (event->button() != Qt::LeftButton)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_bMouseDown = false;
|
||||
m_bDragging = false;
|
||||
m_selectedIndices.clear();
|
||||
|
||||
releaseMouse();
|
||||
update();
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
if (m_bMouseDown && !m_bDragging)
|
||||
{
|
||||
m_bDragging = true;
|
||||
}
|
||||
|
||||
m_bHovered = true;
|
||||
if (m_flags & eFlag_ShowCursorAlways)
|
||||
{
|
||||
m_bHovered = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bHovered = false;
|
||||
|
||||
for (size_t i = 0; i < m_points.size(); ++i)
|
||||
{
|
||||
QPoint ptProj = ProjectPoint(m_points[i].pos.x, m_points[i].pos.y);
|
||||
QRect rcHandle(0, 0, CurveEditor::kHandleSize, CurveEditor::kHandleSize);
|
||||
rcHandle.moveCenter(ptProj);
|
||||
|
||||
if (rcHandle.contains(event->pos()))
|
||||
{
|
||||
m_bHovered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bDragging)
|
||||
{
|
||||
Vec2 v1 = UnprojectPoint(m_lastMousePoint);
|
||||
Vec2 v2 = UnprojectPoint(event->pos());
|
||||
Vec2 v = v1 - v2;
|
||||
|
||||
for (size_t i = 0; i < m_selectedIndices.size(); ++i)
|
||||
{
|
||||
int index = m_selectedIndices[i];
|
||||
CurvePoint& cpt = m_points[index];
|
||||
|
||||
// do not move first and last points on X
|
||||
if (index > 0 && index < m_points.size() - 1)
|
||||
{
|
||||
cpt.pos.x -= v.x;
|
||||
}
|
||||
|
||||
cpt.pos.y -= v.y;
|
||||
|
||||
// lets check if the point is overlapping its neighbours
|
||||
if (index > 0 && (index - 1) > 0)
|
||||
{
|
||||
if (cpt.pos.x < m_points[index - 1].pos.x)
|
||||
{
|
||||
CurvePoint p = m_points[index];
|
||||
|
||||
// swap!
|
||||
m_points[index] = m_points[index - 1];
|
||||
m_points[index - 1] = p;
|
||||
m_selectedIndices[i] = index - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < m_points.size() - 1 && (index + 1) < m_points.size() - 1)
|
||||
{
|
||||
if (cpt.pos.x > m_points[index + 1].pos.x)
|
||||
{
|
||||
CurvePoint p = m_points[index];
|
||||
|
||||
// swap!
|
||||
m_points[index] = m_points[index + 1];
|
||||
m_points[index + 1] = p;
|
||||
m_selectedIndices[i] = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
ClampToDomain(cpt.pos);
|
||||
}
|
||||
|
||||
update();
|
||||
m_lastMousePoint = event->pos();
|
||||
}
|
||||
|
||||
QWidget::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::MarkX(float value)
|
||||
{
|
||||
m_marksX.push_back(value);
|
||||
}
|
||||
|
||||
void CCurveEditorCtrl::MarkY(float value)
|
||||
{
|
||||
m_marksY.push_back(value);
|
||||
}
|
||||
@@ -1,112 +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_CONTROLS_CURVEEDITORCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_CONTROLS_CURVEEDITORCTRL_H
|
||||
#pragma once
|
||||
#include "Util/GdiUtil.h"
|
||||
#include <QWidget>
|
||||
#include <QPen>
|
||||
|
||||
|
||||
class CCurveEditorCtrl
|
||||
: public QWidget
|
||||
{
|
||||
public:
|
||||
enum EFlags
|
||||
{
|
||||
eFlag_ShowVerticalRuler = (1 << 0),
|
||||
eFlag_ShowHorizontalRuler = (1 << 1),
|
||||
eFlag_ShowVerticalRulerText = (1 << 2),
|
||||
eFlag_ShowHorizontalRulerText = (1 << 3),
|
||||
eFlag_ShowPaddingBorder = (1 << 4),
|
||||
eFlag_ShowMovingPointAxis = (1 << 5),
|
||||
eFlag_ShowPointHandles = (1 << 6),
|
||||
eFlag_ShowCursorAlways = (1 << 7),
|
||||
eFlag_Disabled = (1 << 8) // special case, when disabling preview window.
|
||||
};
|
||||
|
||||
CCurveEditorCtrl(QWidget* parent);
|
||||
virtual ~CCurveEditorCtrl();
|
||||
|
||||
void SetFlags(UINT aFlags);
|
||||
UINT GetFlags() const;
|
||||
void SetMouseEnable(bool bEnable = true) { m_bAllowMouse = bEnable; }
|
||||
bool GetMouseEnable() const {return m_bAllowMouse; }
|
||||
bool SetDomainBounds(float aMinX, float aMinY, float aMaxX, float aMaxY);
|
||||
void GetDomainBounds(float& rMinX, float& rMinY, float& rMaxX, float& rMaxY) const;
|
||||
// labelsX/labelsY must be null (to use default labels)
|
||||
// or contain aHorizontalSplits+1/aVerticalSplits+1 items.
|
||||
void SetGrid(UINT aHorizontalSplits, UINT aVerticalSplits, const QStringList& labelsX = QStringList(), const QStringList& labelsY = QStringList());
|
||||
void SetPadding(float padding) { m_padding = padding; }
|
||||
void MarkX(float value);
|
||||
void MarkY(float value);
|
||||
void AddControlPoint(const Vec2& rPosition);
|
||||
void ClearControlPoints();
|
||||
void SetControlPointCount(UINT aCount);
|
||||
UINT GetControlPointCount() const;
|
||||
void SetControlPoint(UINT aIndex, const Vec2& rPosition);
|
||||
void SetControlPointTangents(UINT aIndex, const Vec2& rLeft, const Vec2& rRight);
|
||||
void GetControlPoint(UINT aIndex, Vec2& rOutPosition) const;
|
||||
void GetControlPointTangents(UINT aIndex, Vec2& rOutLeft, Vec2& rOutRight) const;
|
||||
QPoint ProjectPoint(float x, float y);
|
||||
Vec2 UnprojectPoint(const QPoint& pt);
|
||||
void UpdateProjectedPoints();
|
||||
|
||||
protected:
|
||||
struct CurvePoint
|
||||
{
|
||||
CurvePoint(float aX = 0.0f, float aY = 0.0f)
|
||||
{
|
||||
pos.x = aX;
|
||||
pos.y = aY;
|
||||
}
|
||||
|
||||
Vec2 pos;
|
||||
Vec2 tanA, tanB;
|
||||
};
|
||||
|
||||
void ComputeTangents();
|
||||
void ClampToDomain(Vec2& rVec);
|
||||
void GenerateDefaultCurve();
|
||||
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
std::vector<CurvePoint> m_points;
|
||||
std::vector<QPoint> m_projectedPoints;
|
||||
float m_domainMinX;
|
||||
float m_domainMinY;
|
||||
float m_domainMaxX;
|
||||
float m_domainMaxY;
|
||||
Vec2 m_gridSplits;
|
||||
int m_padding;
|
||||
bool m_bMouseDown, m_bDragging, m_bAllowMouse;
|
||||
bool m_bHovered;
|
||||
QPoint m_lastMousePoint;
|
||||
std::vector<int> m_selectedIndices;
|
||||
QFont m_fntInfo;
|
||||
QPen m_pen, m_selCrossPen;
|
||||
UINT m_flags;
|
||||
QStringList m_labelsX;
|
||||
QStringList m_labelsY;
|
||||
std::vector<float> m_marksX;
|
||||
std::vector<float> m_marksY;
|
||||
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_CONTROLS_CURVEEDITORCTRL_H
|
||||
@@ -85,7 +85,6 @@ AZ_POP_DISABLE_WARNING
|
||||
// Editor
|
||||
#include "Settings.h"
|
||||
|
||||
#include "Include/IBackgroundScheduleManager.h"
|
||||
#include "GameExporter.h"
|
||||
#include "GameResourcesExporter.h"
|
||||
|
||||
@@ -2314,15 +2313,6 @@ int CCryEditApp::IdleProcessing(bool bBackgroundUpdate)
|
||||
#endif
|
||||
}
|
||||
|
||||
// process the work schedule - regardless if the app is active or not
|
||||
GetIEditor()->GetBackgroundScheduleManager()->Update();
|
||||
|
||||
// if there are active schedules keep updating the application
|
||||
if (GetIEditor()->GetBackgroundScheduleManager()->GetNumSchedules() > 0)
|
||||
{
|
||||
bActive = true;
|
||||
}
|
||||
|
||||
m_bPrevActive = bActive;
|
||||
|
||||
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
|
||||
|
||||
@@ -420,7 +420,6 @@ AZ::Outcome<void, AZStd::string> CGameEngine::Init(
|
||||
#else
|
||||
sip.hWnd = hwndForInputSystem;
|
||||
#endif
|
||||
sip.hWndForInputSystem = hwndForInputSystem;
|
||||
|
||||
sip.pLogCallback = &m_logFile;
|
||||
sip.sLogFileName = "@log@/Editor.log";
|
||||
@@ -503,7 +502,6 @@ AZ::Outcome<void, AZStd::string> CGameEngine::Init(
|
||||
|
||||
bool CGameEngine::InitGame(const char*)
|
||||
{
|
||||
// in editor we do it later, bExecuteCommandLine was set to false
|
||||
m_pISystem->ExecuteCommandLine();
|
||||
|
||||
return true;
|
||||
@@ -608,8 +606,6 @@ void CGameEngine::SwitchToInGame()
|
||||
|
||||
GetIEditor()->Notify(eNotify_OnBeginGameMode);
|
||||
|
||||
m_pISystem->SetThreadState(ESubsys_Physics, false);
|
||||
|
||||
m_pISystem->GetIMovieSystem()->EnablePhysicsEvents(true);
|
||||
m_bInGameMode = true;
|
||||
|
||||
@@ -646,8 +642,6 @@ void CGameEngine::SwitchToInEditor()
|
||||
}
|
||||
m_pISystem->GetIMovieSystem()->Reset(false, false);
|
||||
|
||||
m_pISystem->SetThreadState(ESubsys_Physics, false);
|
||||
|
||||
CViewport* pGameViewport = GetIEditor()->GetViewManager()->GetGameViewport();
|
||||
|
||||
m_pISystem->GetIMovieSystem()->EnablePhysicsEvents(m_bSimulationMode);
|
||||
@@ -791,8 +785,6 @@ void CGameEngine::SetSimulationMode(bool enabled, bool bOnlyPhysics)
|
||||
// Enables engine to know about simulation mode.
|
||||
gEnv->SetIsEditorSimulationMode(enabled);
|
||||
|
||||
m_pISystem->SetThreadState(ESubsys_Physics, false);
|
||||
|
||||
if (m_bSimulationMode)
|
||||
{
|
||||
// [Anton] the order of the next 3 calls changed, since, EVENT_INGAME loads physics state (if any),
|
||||
@@ -903,19 +895,6 @@ void CGameEngine::Update()
|
||||
// [marco] check current sound and vis areas for music etc.
|
||||
// but if in game mode, 'cos is already done in the above call to game->update()
|
||||
unsigned int updateFlags = ESYSUPDATE_EDITOR;
|
||||
|
||||
if (!m_bSimulationMode)
|
||||
{
|
||||
updateFlags |= ESYSUPDATE_IGNORE_PHYSICS;
|
||||
}
|
||||
|
||||
bool bUpdateAIPhysics = GetSimulationMode();
|
||||
|
||||
if (bUpdateAIPhysics)
|
||||
{
|
||||
updateFlags |= ESYSUPDATE_EDITOR_AI_PHYSICS;
|
||||
}
|
||||
|
||||
GetIEditor()->GetAnimation()->Update();
|
||||
GetIEditor()->GetSystem()->UpdatePreTickBus(updateFlags);
|
||||
componentApplication->Tick(gEnv->pTimer->GetFrameTime(ITimer::ETIMER_GAME));
|
||||
|
||||
@@ -550,7 +550,6 @@ struct IEditor
|
||||
virtual class CViewManager* GetViewManager() = 0;
|
||||
virtual class CViewport* GetActiveView() = 0;
|
||||
virtual void SetActiveView(CViewport* viewport) = 0;
|
||||
virtual struct IBackgroundTaskManager* GetBackgroundTaskManager() = 0;
|
||||
virtual struct IEditorFileMonitor* GetFileMonitor() = 0;
|
||||
|
||||
// These are needed for Qt integration:
|
||||
@@ -720,7 +719,6 @@ struct IEditor
|
||||
virtual ESystemConfigPlatform GetEditorConfigPlatform() const = 0;
|
||||
virtual void ReloadTemplates() = 0;
|
||||
virtual IResourceSelectorHost* GetResourceSelectorHost() = 0;
|
||||
virtual struct IBackgroundScheduleManager* GetBackgroundScheduleManager() = 0;
|
||||
virtual void ShowStatusText(bool bEnable) = 0;
|
||||
|
||||
// Provides a way to extend the context menu of an object. The function gets called every time the menu is opened.
|
||||
|
||||
@@ -66,12 +66,9 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "Objects/SelectionGroup.h"
|
||||
#include "Objects/ObjectManager.h"
|
||||
|
||||
#include "BackgroundTaskManager.h"
|
||||
#include "BackgroundScheduleManager.h"
|
||||
#include "EditorFileMonitor.h"
|
||||
#include "MainStatusBar.h"
|
||||
|
||||
#include "SettingsBlock.h"
|
||||
#include "ResourceSelectorHost.h"
|
||||
#include "Util/FileUtil_impl.h"
|
||||
#include "Util/ImageUtil_impl.h"
|
||||
@@ -177,8 +174,6 @@ CEditorImpl::CEditorImpl()
|
||||
regCtx.pCommandManager = m_pCommandManager;
|
||||
regCtx.pClassFactory = m_pClassFactory;
|
||||
m_pEditorFileMonitor.reset(new CEditorFileMonitor());
|
||||
m_pBackgroundTaskManager.reset(new BackgroundTaskManager::CTaskManager);
|
||||
m_pBackgroundScheduleManager.reset(new BackgroundScheduleManager::CScheduleManager);
|
||||
m_pUIEnumsDatabase = new CUIEnumsDatabase;
|
||||
m_pDisplaySettings = new CDisplaySettings;
|
||||
m_pDisplaySettings->LoadRegistry();
|
||||
@@ -844,16 +839,6 @@ IIconManager* CEditorImpl::GetIconManager()
|
||||
return m_pIconManager;
|
||||
}
|
||||
|
||||
IBackgroundTaskManager* CEditorImpl::GetBackgroundTaskManager()
|
||||
{
|
||||
return m_pBackgroundTaskManager.get();
|
||||
}
|
||||
|
||||
IBackgroundScheduleManager* CEditorImpl::GetBackgroundScheduleManager()
|
||||
{
|
||||
return m_pBackgroundScheduleManager.get();
|
||||
}
|
||||
|
||||
IEditorFileMonitor* CEditorImpl::GetFileMonitor()
|
||||
{
|
||||
return m_pEditorFileMonitor.get();
|
||||
@@ -1624,8 +1609,6 @@ ESystemConfigPlatform CEditorImpl::GetEditorConfigPlatform() const
|
||||
|
||||
void CEditorImpl::InitFinished()
|
||||
{
|
||||
SProjectSettingsBlock::Load();
|
||||
|
||||
if (!m_bInitialized)
|
||||
{
|
||||
m_bInitialized = true;
|
||||
|
||||
@@ -43,15 +43,12 @@ class CGameEngine;
|
||||
class CExportManager;
|
||||
class CErrorsDlg;
|
||||
class CIconManager;
|
||||
class CBackgroundTaskManager;
|
||||
class CTrackViewSequenceManager;
|
||||
class CEditorFileMonitor;
|
||||
class AzAssetWindow;
|
||||
class AzAssetBrowserRequestHandler;
|
||||
class AssetEditorRequestsHandler;
|
||||
class CAlembicCompiler;
|
||||
struct IBackgroundTaskManager;
|
||||
struct IBackgroundScheduleManager;
|
||||
struct IEditorFileMonitor;
|
||||
class CVegetationMap;
|
||||
|
||||
@@ -61,16 +58,6 @@ namespace Editor
|
||||
class EditorQtApplication;
|
||||
}
|
||||
|
||||
namespace BackgroundScheduleManager
|
||||
{
|
||||
class CScheduleManager;
|
||||
}
|
||||
|
||||
namespace BackgroundTaskManager
|
||||
{
|
||||
class CTaskManager;
|
||||
}
|
||||
|
||||
namespace WinWidget
|
||||
{
|
||||
class WinWidgetManager;
|
||||
@@ -179,8 +166,6 @@ public:
|
||||
IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType);
|
||||
CMusicManager* GetMusicManager() { return m_pMusicManager; };
|
||||
|
||||
IBackgroundTaskManager* GetBackgroundTaskManager() override;
|
||||
IBackgroundScheduleManager* GetBackgroundScheduleManager() override;
|
||||
IEditorFileMonitor* GetFileMonitor() override;
|
||||
void RegisterEventLoopHook(IEventLoopHook* pHook) override;
|
||||
void UnregisterEventLoopHook(IEventLoopHook* pHook) override;
|
||||
@@ -394,8 +379,6 @@ protected:
|
||||
|
||||
//! Export manager for exporting objects and a terrain from the game to DCC tools
|
||||
CExportManager* m_pExportManager;
|
||||
std::unique_ptr<BackgroundTaskManager::CTaskManager> m_pBackgroundTaskManager;
|
||||
std::unique_ptr<BackgroundScheduleManager::CScheduleManager> m_pBackgroundScheduleManager;
|
||||
std::unique_ptr<CEditorFileMonitor> m_pEditorFileMonitor;
|
||||
std::unique_ptr<IResourceSelectorHost> m_pResourceSelectorHost;
|
||||
QString m_selectFileBuffer;
|
||||
|
||||
@@ -1,207 +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.
|
||||
|
||||
//
|
||||
// IBackgroundScheduleManager manages schedule of group of larger operations that should be run in sequence
|
||||
//
|
||||
// Schedules are derived from IBackgroundSchedule and consist of a list of IBackgroundScheduleItems.
|
||||
// Each schedule item is executed IN ORDER for the previous item to complete first.
|
||||
// Each IBackgroundScheduleItems consists of list of user defined work via IBackgroundScheduleItemsWork classes.
|
||||
// Each schedule item work is executed IN PARALEL (they are all started when the item starts).
|
||||
//
|
||||
// Whenever a work item fails to complete the other work items are stopped, the schedule item is marked as "failed"
|
||||
// and so is the whole schedule.
|
||||
//
|
||||
// All logic is performed on the main thread although schedule items are free to use threads.
|
||||
// It is recommended to use IBackgroundTaskManager for dispatching a task list for every schedule work item.
|
||||
//
|
||||
// All objects in the schedule system are reference counted.
|
||||
//
|
||||
|
||||
// State of the whole schedule
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_INCLUDE_IBACKGROUNDSCHEDULEMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_INCLUDE_IBACKGROUNDSCHEDULEMANAGER_H
|
||||
#pragma once
|
||||
enum EScheduleState
|
||||
{
|
||||
// Item has not started yet but is on the list
|
||||
eScheduleState_Pending,
|
||||
|
||||
// We are processing this item
|
||||
eScheduleState_Processing,
|
||||
|
||||
// We are stopping the schedule
|
||||
eSccheduleState_Stopping,
|
||||
|
||||
// Schedule item has failed
|
||||
eScheduleState_Failed,
|
||||
|
||||
// Schedule item was canceled
|
||||
eScheduleState_Canceled,
|
||||
|
||||
// Schedule item has completed it's work
|
||||
eScheduleState_Completed,
|
||||
};
|
||||
|
||||
// State of the single schedule item
|
||||
enum EScheduleItemState
|
||||
{
|
||||
// Item has not started yet but is on the list
|
||||
eScheduleItemState_Pending,
|
||||
|
||||
// We are processing this item
|
||||
eScheduleItemState_Processing,
|
||||
|
||||
// We are stopping this item
|
||||
eScheduleItemState_Stopping,
|
||||
|
||||
// Schedule item has failed
|
||||
eScheduleItemState_Failed,
|
||||
|
||||
// Schedule item has completed it's work
|
||||
eScheduleItemState_Completed,
|
||||
};
|
||||
|
||||
// Work item status
|
||||
enum EScheduleWorkItemStatus
|
||||
{
|
||||
// Work is still not finished
|
||||
eScheduleWorkItemStatus_NotFinished,
|
||||
|
||||
// Work has failed
|
||||
eScheduleWorkItemStatus_Failed,
|
||||
|
||||
// Work has finished
|
||||
eScheduleWorkItemStatus_Finished,
|
||||
};
|
||||
|
||||
struct IBackgroundScheduleItemWork
|
||||
{
|
||||
// Get human readable description
|
||||
virtual const char* GetDescription() const = 0;
|
||||
|
||||
// Get work item progress
|
||||
virtual float GetProgress() const = 0;
|
||||
|
||||
// Called when the schedule item containing this work piece has started
|
||||
// If the work cannot be started for any reason return false.
|
||||
virtual bool OnStart() = 0;
|
||||
|
||||
// Called when the schedule item containing this work piece has been canceled or failed externally
|
||||
// Not called when schedule item completed without errors.
|
||||
// If the work cannot be stopped this frame return false.
|
||||
virtual bool OnStop() = 0;
|
||||
|
||||
// Called every frame to advance and check the work state
|
||||
// Should return one of the EBackgroundScheduleWorkItemStatus value
|
||||
virtual EScheduleWorkItemStatus OnUpdate() = 0;
|
||||
|
||||
// Reference counting
|
||||
virtual void AddRef() = 0;
|
||||
virtual void Release() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~IBackgroundScheduleItemWork() {};
|
||||
};
|
||||
|
||||
struct IBackgroundScheduleItem
|
||||
{
|
||||
// Get name of the schedule (debug & display)
|
||||
virtual const char* GetDescription() const = 0;
|
||||
|
||||
// Get interal state
|
||||
virtual EScheduleItemState GetState() const = 0;
|
||||
|
||||
// Get overall progress of this schedule item
|
||||
virtual const float GetProgress() const = 0;
|
||||
|
||||
// Get number of work items in this schedule item
|
||||
virtual const uint32 GetNumWorkItems() const = 0;
|
||||
|
||||
// Get n-th work item from the schedule item
|
||||
virtual IBackgroundScheduleItemWork* GetWorkItem(const uint32 index) const = 0;
|
||||
|
||||
// Add work item to the schedule item
|
||||
virtual void AddWorkItem(IBackgroundScheduleItemWork* pWork) = 0;
|
||||
|
||||
// Reference counting
|
||||
virtual void AddRef() = 0;
|
||||
virtual void Release() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~IBackgroundScheduleItem() {};
|
||||
};
|
||||
|
||||
struct IBackgroundSchedule
|
||||
{
|
||||
// Get name of the schedule (debug & display)
|
||||
virtual const char* GetDescription() const = 0;
|
||||
|
||||
// Get overall progress of the whole schedule
|
||||
virtual float GetProgress() const = 0;
|
||||
|
||||
// Get item being currently processed
|
||||
virtual IBackgroundScheduleItem* GetProcessedItem() const = 0;
|
||||
|
||||
// Get number of items in the schedule
|
||||
virtual const uint32 GetNumItems() const = 0;
|
||||
|
||||
// Get single schedule item
|
||||
virtual IBackgroundScheduleItem* GetItem(const uint32 index) const = 0;
|
||||
|
||||
// Get schedule item
|
||||
virtual EScheduleState GetState() const = 0;
|
||||
|
||||
// Cancel the whole schedule
|
||||
virtual void Cancel() = 0;
|
||||
|
||||
// Is the schedule canceled ?
|
||||
virtual bool IsCanceled() const = 0;
|
||||
|
||||
// Add schedule item at the end of the list
|
||||
virtual void AddItem(IBackgroundScheduleItem* pItem) = 0;
|
||||
|
||||
// Reference counting
|
||||
virtual void AddRef() = 0;
|
||||
virtual void Release() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~IBackgroundSchedule() {};
|
||||
};
|
||||
|
||||
struct IBackgroundScheduleManager
|
||||
{
|
||||
virtual ~IBackgroundScheduleManager() {};
|
||||
|
||||
// Create empty schedule
|
||||
virtual IBackgroundSchedule* CreateSchedule(const char* szName) = 0;
|
||||
|
||||
// Create empty schedule item
|
||||
virtual IBackgroundScheduleItem* CreateScheduleItem(const char* szName) = 0;
|
||||
|
||||
// Issue a schedule to the list (will start processing it)
|
||||
virtual void SubmitSchedule(IBackgroundSchedule* pSchedule) = 0;
|
||||
|
||||
// Get number of schedules on the list
|
||||
virtual const uint32 GetNumSchedules() const = 0;
|
||||
|
||||
// Get n-th schedule
|
||||
virtual IBackgroundSchedule* GetSchedule(const uint32 index) const = 0;
|
||||
|
||||
// Advance work on the schedules
|
||||
virtual void Update() = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_INCLUDE_IBACKGROUNDSCHEDULEMANAGER_H
|
||||
@@ -1,230 +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.
|
||||
|
||||
//
|
||||
// IBackgroundTaskManager runs background tasks in worker thread.
|
||||
//
|
||||
// Tasks are derived from IBackgroundTask. Each task is split in two parts for:
|
||||
// Work - done in background thread.
|
||||
// Finalize - called afterward in main thread to apply results.
|
||||
//
|
||||
// Task objects are reference counted. Task manager will hold its own reference to the task object
|
||||
// for as long as the task is pending or being executed. If you want to keep the task object around
|
||||
// in your code you will have to call AddRef() and Release() on the task object by yourself so there
|
||||
// will be an extra reference to the task object held by your code.
|
||||
//
|
||||
// Work returns the state of the task. Task can be resumed, then the Work
|
||||
// method will be called again. Other tasks can work between calls to Work.
|
||||
// It is possible to Cancel task. Work method is not invoked any more for
|
||||
// Canceled tasks.
|
||||
//
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_INCLUDE_IBACKGROUNDTASKMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_INCLUDE_IBACKGROUNDTASKMANAGER_H
|
||||
#pragma once
|
||||
|
||||
enum ETaskPriority
|
||||
{
|
||||
eTaskPriority_FileUpdateFinal,
|
||||
eTaskPriority_BackgroundScan,
|
||||
eTaskPriority_FileUpdate,
|
||||
eTaskPriority_RealtimePreview
|
||||
};
|
||||
|
||||
// Result code returned by task Work() function
|
||||
enum ETaskResult
|
||||
{
|
||||
// Task has not yet completed, add it back to the task queue with the same parameters (priority and thread mask)
|
||||
eTaskResult_Resume,
|
||||
|
||||
// Task has completed without errors (it's assumed that the result the task was supposed to achieve was achieved)
|
||||
eTaskResult_Completed,
|
||||
|
||||
// Task was canceled
|
||||
eTaskResult_Canceled,
|
||||
|
||||
// Task has failed to complete it's work
|
||||
eTaskResult_Failed,
|
||||
};
|
||||
|
||||
// Internal task tracking state
|
||||
enum ETaskState
|
||||
{
|
||||
// Task was just created.
|
||||
eTaskState_Created,
|
||||
|
||||
// Task was scheduled to be executed in the future.
|
||||
eTaskState_Scheduled,
|
||||
|
||||
// Task was added to the task queue and is waiting for it's time to be executed.
|
||||
eTaskState_Pending,
|
||||
|
||||
// Task is being processed right now.
|
||||
eTaskState_Working,
|
||||
|
||||
// Task was canceled before it has finished (indication that TaskManager has seen the Cancel() call).
|
||||
eTaskState_Canceled,
|
||||
|
||||
// Task Work() function was called but it ended with an error code.
|
||||
eTaskState_Failed,
|
||||
|
||||
// Task has completed it's Work() function without errors.
|
||||
eTaskState_Completed,
|
||||
};
|
||||
|
||||
// Thread mask controls which on which threads given task can be executed.
|
||||
enum ETaskThreadMask
|
||||
{
|
||||
// Task can run only on the IO thread (default)
|
||||
// There is only one IO thread so all task with this flag are run in a sequence.
|
||||
eTaskThreadMask_IO,
|
||||
|
||||
// Task can run on any thread (concurrent tasks allowed)
|
||||
// There can be many threads with this mask so there's no limit on the concurrent task count.
|
||||
eTaskThreadMask_Any,
|
||||
|
||||
eTaskThreadMask_COUNT,
|
||||
};
|
||||
|
||||
struct IBackgroundTask
|
||||
{
|
||||
public:
|
||||
IBackgroundTask()
|
||||
: m_bCanceled(false)
|
||||
, m_state(eTaskState_Created)
|
||||
, m_progress(-1.0f)
|
||||
, m_refCount(0)
|
||||
, m_bFailReported(false)
|
||||
{}
|
||||
|
||||
void Cancel()
|
||||
{
|
||||
m_bCanceled = true;
|
||||
}
|
||||
|
||||
bool IsCanceled() const
|
||||
{
|
||||
return m_bCanceled;
|
||||
}
|
||||
|
||||
bool HasFinished() const
|
||||
{
|
||||
return (m_state == eTaskState_Canceled) ||
|
||||
(m_state == eTaskState_Completed) ||
|
||||
(m_state == eTaskState_Failed);
|
||||
}
|
||||
|
||||
bool HasFinishedWithoutError() const
|
||||
{
|
||||
return (m_state == eTaskState_Completed);
|
||||
}
|
||||
|
||||
ETaskState GetState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void SetState(ETaskState state)
|
||||
{
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
float GetProgress() const
|
||||
{
|
||||
return m_progress;
|
||||
}
|
||||
|
||||
int AddRef()
|
||||
{
|
||||
return CryInterlockedIncrement(&m_refCount);
|
||||
}
|
||||
|
||||
int Release()
|
||||
{
|
||||
const int nCount = CryInterlockedDecrement(&m_refCount);
|
||||
assert(nCount >= 0);
|
||||
if (nCount == 0)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
else if (nCount < 0)
|
||||
{
|
||||
assert(0);
|
||||
CryFatalError("Deleting Reference Counted Object Twice");
|
||||
}
|
||||
return nCount;
|
||||
}
|
||||
|
||||
bool FailReported() const{ return m_bFailReported; }
|
||||
|
||||
// Get the user readable description (name) of this task, used for logging
|
||||
virtual const char* Description() const { return ""; }
|
||||
|
||||
// Get the user readable error message (in case when the task fails), used for logging the errors
|
||||
virtual const char* ErrorMessage() const { return ""; }
|
||||
|
||||
// Called from main thread after task is completed just before the task gets destroyed
|
||||
virtual void Finalize() {}
|
||||
|
||||
// Since there's a possibility that task object were created using different allocator
|
||||
// we need a way to delete the task object once we are done with it
|
||||
virtual void Delete() = 0;
|
||||
|
||||
// Invoked from worker thread, actual work is done here
|
||||
virtual ETaskResult Work() = 0;
|
||||
|
||||
protected:
|
||||
void SetProgress(float progress) { m_progress = progress; }
|
||||
void SetFailReported() { m_bFailReported = true; }
|
||||
|
||||
// destructor is hidden to indicate that we should use Release() method
|
||||
virtual ~IBackgroundTask() {}
|
||||
|
||||
private:
|
||||
volatile int m_refCount;
|
||||
ETaskState m_state;
|
||||
float m_progress;
|
||||
bool m_bCanceled;
|
||||
bool m_bFailReported;
|
||||
};
|
||||
|
||||
struct IBackgroundTaskManagerListener
|
||||
{
|
||||
virtual ~IBackgroundTaskManagerListener() {}
|
||||
|
||||
virtual void OnBackgroundTaskAdded(const char* description) = 0;
|
||||
virtual void OnBackgroundTaskCompleted(ETaskResult taskResult, const char* description) = 0;
|
||||
};
|
||||
|
||||
struct IBackgroundTaskManager
|
||||
{
|
||||
enum
|
||||
{
|
||||
BACKGROUND_TASK_ID_INVALID = 0
|
||||
};
|
||||
|
||||
virtual ~IBackgroundTaskManager() {}
|
||||
|
||||
// Add task to the queue with given priority and thread mask
|
||||
virtual void AddTask(IBackgroundTask* pTask, ETaskPriority priority, ETaskThreadMask threadMask) = 0;
|
||||
|
||||
// Schedule task to be executed in the future
|
||||
virtual void ScheduleTask(IBackgroundTask* pTask, ETaskPriority priority, int delayMilliseconds, ETaskThreadMask threadMask) = 0;
|
||||
|
||||
virtual void AddListener(IBackgroundTaskManagerListener* pListener, const char* name) = 0;
|
||||
|
||||
virtual void RemoveListener(IBackgroundTaskManagerListener* pListener) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_INCLUDE_IBACKGROUNDTASKMANAGER_H
|
||||
@@ -28,16 +28,6 @@
|
||||
// }
|
||||
// REGISTER_RESOURCE_SELECTOR("Sound", SoundFileSelector, "Icons/sound_16x16.png")
|
||||
//
|
||||
// To expose it to serialization:
|
||||
//
|
||||
// #include "Serialization/Decorators/Resources.h"
|
||||
// template<class TString>
|
||||
// ResourceSelector<TString> SoundName(TString& s) { return ResourceSelector<TString>(s, "Sound"); }
|
||||
//
|
||||
// To use in serialization:
|
||||
//
|
||||
// ar(Serialization::SoundName(soundString), "soundString", "Sound String");
|
||||
//
|
||||
// Here is how it can be invoked directly:
|
||||
//
|
||||
// SResourceSelectorContext x;
|
||||
@@ -56,19 +46,7 @@
|
||||
//
|
||||
// QString SoundFileSelector(const SResourceSelectorContext& x, const QString& previousValue,
|
||||
// SoundFileList* list) // your context argument
|
||||
//
|
||||
// And provide this value through serialization context:
|
||||
//
|
||||
// struct SourceFileList
|
||||
// {
|
||||
// void Serialize(IArchive& ar)
|
||||
// {
|
||||
// Serialization::SContext<SourceFileList> context(ar, this);
|
||||
// ...
|
||||
// }
|
||||
// }
|
||||
|
||||
#include <Serialization/TypeID.h>
|
||||
#include <QString>
|
||||
|
||||
class QWidget;
|
||||
@@ -82,7 +60,6 @@ struct SResourceSelectorContext
|
||||
|
||||
unsigned int entityId;
|
||||
void* contextObject;
|
||||
Serialization::TypeID contextObjectType;
|
||||
|
||||
SResourceSelectorContext()
|
||||
: parentWidget(0)
|
||||
@@ -107,7 +84,6 @@ struct IResourceSelectorHost
|
||||
virtual ~IResourceSelectorHost() = default;
|
||||
virtual QString SelectResource(const SResourceSelectorContext& context, const QString& previousValue) = 0;
|
||||
virtual const char* ResourceIconPath(const char* typeName) const = 0;
|
||||
virtual Serialization::TypeID ResourceContextType(const char* typeName) const = 0;
|
||||
|
||||
virtual void RegisterResourceSelector(const SStaticResourceSelectorEntry* entry) = 0;
|
||||
|
||||
@@ -128,7 +104,6 @@ struct SStaticResourceSelectorEntry
|
||||
TResourceSelectionFunction function;
|
||||
TResourceSelectionFunctionWithContext functionWithContext;
|
||||
const char* iconPath;
|
||||
Serialization::TypeID contextType;
|
||||
|
||||
static SStaticResourceSelectorEntry*& GetFirst() { static SStaticResourceSelectorEntry* first; return first; }
|
||||
SStaticResourceSelectorEntry* next;
|
||||
@@ -150,7 +125,6 @@ struct SStaticResourceSelectorEntry
|
||||
, functionWithContext(TResourceSelectionFunctionWithContext(function))
|
||||
, iconPath(icon)
|
||||
{
|
||||
contextType = Serialization::TypeID::get<T>();
|
||||
next = GetFirst();
|
||||
GetFirst() = this;
|
||||
}
|
||||
|
||||
@@ -97,10 +97,6 @@ void CLevelInfo::ValidateObjects()
|
||||
|
||||
pObject->Validate(m_pReport);
|
||||
|
||||
CUsedResources rs;
|
||||
pObject->GatherUsedResources(rs);
|
||||
rs.Validate(m_pReport);
|
||||
|
||||
m_pReport->SetCurrentValidatorObject(NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,6 @@ public:
|
||||
MOCK_METHOD0(GetViewManager, class CViewManager* ());
|
||||
MOCK_METHOD0(GetActiveView, class CViewport* ());
|
||||
MOCK_METHOD1(SetActiveView, void(CViewport*));
|
||||
MOCK_METHOD0(GetBackgroundTaskManager, struct IBackgroundTaskManager* ());
|
||||
MOCK_METHOD0(GetFileMonitor, struct IEditorFileMonitor* ());
|
||||
MOCK_METHOD1(RegisterEventLoopHook, void(IEventLoopHook* ));
|
||||
MOCK_METHOD1(UnregisterEventLoopHook, void(IEventLoopHook* ));
|
||||
@@ -184,7 +183,6 @@ public:
|
||||
MOCK_CONST_METHOD0(GetEditorConfigPlatform, ESystemConfigPlatform());
|
||||
MOCK_METHOD0(ReloadTemplates, void());
|
||||
MOCK_METHOD0(GetResourceSelectorHost, IResourceSelectorHost* ());
|
||||
MOCK_METHOD0(GetBackgroundScheduleManager, struct IBackgroundScheduleManager* ());
|
||||
MOCK_METHOD1(ShowStatusText, void(bool ));
|
||||
MOCK_METHOD1(RegisterObjectContextMenuExtension, void(TContextMenuExtensionFunc ));
|
||||
MOCK_METHOD0(GetEnv, SSystemGlobalEnvironment* ());
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <MainStatusBar.h>
|
||||
#include <IBackgroundTaskManager.h>
|
||||
#include <IRenderer.h>
|
||||
#include <QMutex>
|
||||
#include <QString>
|
||||
|
||||
@@ -92,7 +92,6 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "ErrorReportDialog.h"
|
||||
|
||||
#include "Dialogs/PythonScriptsDialog.h"
|
||||
#include "EngineSettingsManager.h"
|
||||
|
||||
#include "AzAssetBrowser/AzAssetBrowserWindow.h"
|
||||
#include "AssetEditor/AssetEditorWindow.h"
|
||||
@@ -695,8 +694,6 @@ void MainWindow::InitActions()
|
||||
am->AddAction(ID_TOOLBAR_WIDGET_REDO, QString());
|
||||
am->AddAction(ID_TOOLBAR_WIDGET_SNAP_ANGLE, QString());
|
||||
am->AddAction(ID_TOOLBAR_WIDGET_SNAP_GRID, QString());
|
||||
am->AddAction(ID_TOOLBAR_WIDGET_ENVIRONMENT_MODE, QString());
|
||||
am->AddAction(ID_TOOLBAR_WIDGET_DEBUG_MODE, QString());
|
||||
am->AddAction(ID_TOOLBAR_WIDGET_SPACER_RIGHT, QString());
|
||||
|
||||
// File actions
|
||||
@@ -1253,44 +1250,6 @@ QToolButton* MainWindow::CreateUndoRedoButton(int command)
|
||||
return button;
|
||||
}
|
||||
|
||||
QToolButton* MainWindow::CreateEnvironmentModeButton()
|
||||
{
|
||||
QToolButton* environmentModeButton = new QToolButton(this);
|
||||
environmentModeButton->setAutoRaise(true);
|
||||
environmentModeButton->setPopupMode(QToolButton::InstantPopup);
|
||||
environmentModeButton->setIcon(Style::icon("Environment"));
|
||||
environmentModeButton->setStatusTip(tr("Select from a variety of environment mode options"));
|
||||
environmentModeButton->setToolTip(tr("Environment modes"));
|
||||
|
||||
CVarMenu* environmentModeMenu = new CVarMenu(this);
|
||||
connect(environmentModeMenu, &QMenu::aboutToShow, [this, environmentModeMenu]()
|
||||
{
|
||||
InitEnvironmentModeMenu(environmentModeMenu);
|
||||
});
|
||||
environmentModeButton->setMenu(environmentModeMenu);
|
||||
|
||||
return environmentModeButton;
|
||||
}
|
||||
|
||||
QToolButton* MainWindow::CreateDebugModeButton()
|
||||
{
|
||||
QToolButton* debugModeButton = new QToolButton(this);
|
||||
debugModeButton->setAutoRaise(true);
|
||||
debugModeButton->setPopupMode(QToolButton::InstantPopup);
|
||||
debugModeButton->setIcon(Style::icon("Debugging"));
|
||||
debugModeButton->setStatusTip(tr("Select from a variety of debug/view mode options"));
|
||||
debugModeButton->setToolTip(tr("Debug modes"));
|
||||
|
||||
CVarMenu* debugModeMenu = new CVarMenu(this);
|
||||
connect(debugModeMenu, &QMenu::aboutToShow, [this, debugModeMenu]()
|
||||
{
|
||||
InitDebugModeMenu(debugModeMenu);
|
||||
});
|
||||
debugModeButton->setMenu(debugModeMenu);
|
||||
|
||||
return debugModeButton;
|
||||
}
|
||||
|
||||
QWidget* MainWindow::CreateSpacerRightWidget()
|
||||
{
|
||||
QWidget* spacer = new QWidget(this);
|
||||
@@ -1299,93 +1258,6 @@ QWidget* MainWindow::CreateSpacerRightWidget()
|
||||
return spacer;
|
||||
}
|
||||
|
||||
void MainWindow::InitEnvironmentModeMenu(CVarMenu* environmentModeMenu)
|
||||
{
|
||||
environmentModeMenu->clear();
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Fog", tr("Hide Global Fog"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "r_FogVolumes", tr("Hide Fog Volumes"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Clouds", tr("Hide Clouds"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Wind", tr("Hide Wind"), 0, 1 });
|
||||
environmentModeMenu->AddSeparator();
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Sun", tr("Hide Sun"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Skybox", tr("Hide Skybox"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "r_SSReflections", tr("Hide Screen Space Reflection"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Shadows", tr("Hide Shadows"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "r_TransparentPasses", tr("Hide Transparent Objects"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "r_ssdo", tr("Hide Screen Space Directional Occlusion"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_DynamicLights", tr("Hide All Dynamic Lights"), 0, 1 });
|
||||
environmentModeMenu->AddSeparator();
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Entities", tr("Hide Entities"), 0, 1 });
|
||||
environmentModeMenu->AddSeparator();
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Vegetation", tr("Hide Vegetation"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Terrain", tr("Hide Terrain"), 0, 1 });
|
||||
environmentModeMenu->AddSeparator();
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Particles", tr("Hide Particles"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Flares", tr("Hide Flares"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_Decals", tr("Hide Decals"), 0, 1 });
|
||||
environmentModeMenu->AddSeparator();
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_WaterOcean", tr("Hide Ocean Water (for legacy)"), 0, 1 });
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_WaterVolumes", tr("Hide Water Volumes"), 0, 1 });
|
||||
environmentModeMenu->AddSeparator();
|
||||
environmentModeMenu->AddCVarToggleItem({ "e_BBoxes", tr("Hide BBoxes"), 0, 1 });
|
||||
environmentModeMenu->AddSeparator();
|
||||
environmentModeMenu->AddResetCVarsItem();
|
||||
}
|
||||
|
||||
void MainWindow::InitDebugModeMenu(CVarMenu* debugModeMenu)
|
||||
{
|
||||
debugModeMenu->clear();
|
||||
debugModeMenu->AddCVarValuesItem("r_DebugGBuffer", tr("GBuffers"),
|
||||
{
|
||||
{tr("Full Shading Mode (Default)"), 0},
|
||||
{tr("Normal Visualization"), 1},
|
||||
{tr("Smoothness"), 2},
|
||||
{tr("Reflectance"), 3},
|
||||
{tr("Albedo"), 4},
|
||||
{tr("Lighting Model"), 5},
|
||||
{tr("Translucency"), 6},
|
||||
{tr("Sun Self Shadowing"), 7},
|
||||
{tr("Subsurface Scattering"), 8},
|
||||
{tr("Specular Validation Overlay"), 9}
|
||||
}, 0);
|
||||
debugModeMenu->AddSeparator();
|
||||
debugModeMenu->AddCVarValuesItem("r_Stats", tr("Profiling"),
|
||||
{
|
||||
{tr("Frame Timing"), 1},
|
||||
{tr("Object Timing"), 3},
|
||||
{tr("Instance Draw Calls"), 6},
|
||||
}, 0);
|
||||
debugModeMenu->AddSeparator();
|
||||
debugModeMenu->AddUniqueCVarsItem(tr("Wireframe"),
|
||||
{
|
||||
{"r_wireframe", tr("Wireframe Rendering Mode"), 1, 0},
|
||||
{"r_showlines", tr("Wireframe Overlay"), 1, 0}
|
||||
}),
|
||||
debugModeMenu->AddCVarValuesItem("e_debugdraw", tr("Art Info"),
|
||||
{
|
||||
{tr("Texture Memory Usage"), 4},
|
||||
{tr("Renderable Material Count"), 5},
|
||||
{tr("LOD Vertex Count"), 22}
|
||||
}, 0);
|
||||
|
||||
debugModeMenu->AddSeparator();
|
||||
debugModeMenu->AddCVarValuesItem("e_defaultmaterial", tr("Default Material on all Objects"),
|
||||
{
|
||||
{tr("Gray Material with Normal Maps"), 1},
|
||||
}, 0);
|
||||
|
||||
debugModeMenu->AddCVarValuesItem("r_DeferredShadingTiledDebugAlbedo", tr("Debug Visualization of Deferred Lighting"),
|
||||
{
|
||||
{tr("White Albedo"), 1},
|
||||
}, 0);
|
||||
|
||||
debugModeMenu->AddCVarToggleItem({ "r_ShowTangents", tr("Show Tangents"), 1, 0 });
|
||||
debugModeMenu->AddCVarToggleItem({ "p_draw_helpers", tr("Show Collision Shapes (Proxy)"), 1, 0 });
|
||||
|
||||
debugModeMenu->AddSeparator();
|
||||
debugModeMenu->AddResetCVarsItem();
|
||||
}
|
||||
|
||||
UndoRedoToolButton::UndoRedoToolButton(QWidget* parent)
|
||||
: QToolButton(parent)
|
||||
{
|
||||
@@ -2068,12 +1940,6 @@ void MainWindow::ConnectivityStateChanged(const AzToolsFramework::SourceControlS
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
CEngineSettingsManager settingsManager;
|
||||
settingsManager.SetModuleSpecificBoolEntry("RC_EnableSourceControl", connected);
|
||||
settingsManager.StoreData();
|
||||
#endif
|
||||
|
||||
gSettings.enableSourceControl = connected;
|
||||
gSettings.SaveEnableSourceControlFlag(false);
|
||||
}
|
||||
@@ -2150,12 +2016,6 @@ QWidget* MainWindow::CreateToolbarWidget(int actionId)
|
||||
case ID_TOOLBAR_WIDGET_SNAP_ANGLE:
|
||||
w = CreateSnapToAngleWidget();
|
||||
break;
|
||||
case ID_TOOLBAR_WIDGET_ENVIRONMENT_MODE:
|
||||
w = CreateEnvironmentModeButton();
|
||||
break;
|
||||
case ID_TOOLBAR_WIDGET_DEBUG_MODE:
|
||||
w = CreateDebugModeButton();
|
||||
break;
|
||||
case ID_TOOLBAR_WIDGET_SPACER_RIGHT:
|
||||
w = CreateSpacerRightWidget();
|
||||
break;
|
||||
|
||||
@@ -208,11 +208,6 @@ private:
|
||||
|
||||
QToolButton* CreateUndoRedoButton(int command);
|
||||
|
||||
QToolButton* CreateEnvironmentModeButton();
|
||||
QToolButton* CreateDebugModeButton();
|
||||
void InitEnvironmentModeMenu(CVarMenu* environmentModeMenu);
|
||||
void InitDebugModeMenu(CVarMenu* debugModeMenu);
|
||||
|
||||
private Q_SLOTS:
|
||||
void ShowKeyboardCustomization();
|
||||
void ExportKeyboardShortcuts();
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
|
||||
class CEntityObject;
|
||||
class QMenu;
|
||||
class IOpticsElementBase;
|
||||
|
||||
/*!
|
||||
* CEntityEventTarget is an Entity event target and type.
|
||||
|
||||
@@ -72,16 +72,6 @@ public:
|
||||
return "";
|
||||
}
|
||||
|
||||
Serialization::TypeID ResourceContextType(const char* typeName) const override
|
||||
{
|
||||
TTypeMap::const_iterator it = m_typeMap.find(typeName);
|
||||
if (it != m_typeMap.end())
|
||||
{
|
||||
return it->second->contextType;
|
||||
}
|
||||
return Serialization::TypeID();
|
||||
}
|
||||
|
||||
void RegisterResourceSelector(const SStaticResourceSelectorEntry* entry) override
|
||||
{
|
||||
m_typeMap[entry->typeName] = entry;
|
||||
|
||||
@@ -1,26 +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
|
||||
#ifndef CRYINCLUDE_EDITOR_SERIALIZATION_H
|
||||
#define CRYINCLUDE_EDITOR_SERIALIZATION_H
|
||||
|
||||
#include <Serialization/STL.h>
|
||||
#include <Serialization/SmartPtr.h>
|
||||
#include <Serialization/ClassFactory.h>
|
||||
#include <Serialization/IArchive.h>
|
||||
#include <Serialization/Enum.h>
|
||||
|
||||
using Serialization::IArchive;
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_SERIALIZATION_H
|
||||
@@ -1,283 +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 "VariableIArchive.h"
|
||||
|
||||
// Editor
|
||||
#include "Serialization/Decorators/Resources.h"
|
||||
#include "Serialization/Decorators/Range.h"
|
||||
|
||||
|
||||
using Serialization::CVariableIArchive;
|
||||
|
||||
namespace VarUtil
|
||||
{
|
||||
_smart_ptr< IVariable > FindChildVariable(const _smart_ptr< IVariable >& pParent, const int childIndexOverride, const char* const name)
|
||||
{
|
||||
if (0 <= childIndexOverride)
|
||||
{
|
||||
return pParent->GetVariable(childIndexOverride);
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool shouldSearchRecursively = false;
|
||||
return pParent->FindVariable(name, shouldSearchRecursively);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template< typename T, typename TOut >
|
||||
bool ReadChildVariableAs(const _smart_ptr< IVariable >& pParent, const int childIndexOverride, const char* const name, TOut& valueOut)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = FindChildVariable(pParent, childIndexOverride, name);
|
||||
if (pVariable)
|
||||
{
|
||||
T tmp;
|
||||
pVariable->Get(tmp);
|
||||
valueOut = static_cast< TOut >(tmp);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template< typename T >
|
||||
bool ReadChildVariable(const _smart_ptr< IVariable >& pParent, const int childIndexOverride, const char* const name, T& valueOut)
|
||||
{
|
||||
return ReadChildVariableAs< T >(pParent, childIndexOverride, name, valueOut);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CVariableIArchive::CVariableIArchive(const _smart_ptr< IVariable >& pVariable)
|
||||
: IArchive(IArchive::INPUT | IArchive::EDIT | IArchive::NO_EMPTY_NAMES)
|
||||
, m_pVariable(pVariable)
|
||||
, m_childIndexOverride(-1)
|
||||
{
|
||||
CRY_ASSERT(m_pVariable);
|
||||
|
||||
m_structHandlers[ TypeID::get < Serialization::IResourceSelector > ().name() ] = &CVariableIArchive::SerializeResourceSelector;
|
||||
m_structHandlers[ TypeID::get < Serialization::RangeDecorator < float >> ().name() ] = &CVariableIArchive::SerializeRangeFloat;
|
||||
m_structHandlers[ TypeID::get < Serialization::RangeDecorator < int >> ().name() ] = &CVariableIArchive::SerializeRangeInt;
|
||||
m_structHandlers[ TypeID::get < Serialization::RangeDecorator < unsigned int >> ().name() ] = &CVariableIArchive::SerializeRangeUInt;
|
||||
m_structHandlers[ TypeID::get < StringListStaticValue > ().name() ] = &CVariableIArchive::SerializeStringListStaticValue;
|
||||
}
|
||||
|
||||
|
||||
CVariableIArchive::~CVariableIArchive()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(bool& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< bool >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(Serialization::IString& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
QString stringValue;
|
||||
const bool readSuccess = VarUtil::ReadChildVariableAs< QString >(m_pVariable, m_childIndexOverride, name, stringValue);
|
||||
if (readSuccess)
|
||||
{
|
||||
value.set(stringValue.toUtf8().data());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()([[maybe_unused]] Serialization::IWString& value, [[maybe_unused]] const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
CryFatalError("CVariableIArchive::operator() with IWString is not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(float& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< float >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(double& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< float >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(int16& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(uint16& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(int32& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(uint32& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(int64& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(uint64& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(int8& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(uint8& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(char& value, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
const char* const typeName = ser.type().name();
|
||||
HandlersMap::const_iterator it = m_structHandlers.find(typeName);
|
||||
const bool handlerFound = (it != m_structHandlers.end());
|
||||
if (handlerFound)
|
||||
{
|
||||
StructHandlerFunctionPtr pHandler = it->second;
|
||||
return (this->*pHandler)(ser, name, label);
|
||||
}
|
||||
|
||||
return SerializeStruct(ser, name, label);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::operator()(Serialization::IContainer& ser, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pChild = VarUtil::FindChildVariable(m_pVariable, m_childIndexOverride, name);
|
||||
if (pChild)
|
||||
{
|
||||
const int elementCount = pChild->GetNumVariables();
|
||||
ser.resize(elementCount);
|
||||
|
||||
if (0 < elementCount)
|
||||
{
|
||||
CVariableIArchive childArchive(pChild);
|
||||
childArchive.SetFilter(GetFilter());
|
||||
childArchive.SetInnerContext(GetInnerContext());
|
||||
|
||||
for (int i = 0; i < elementCount; ++i)
|
||||
{
|
||||
childArchive.m_childIndexOverride = i;
|
||||
|
||||
ser(childArchive, "", "");
|
||||
ser.next();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::SerializeStruct(const Serialization::SStruct& ser, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pChild = VarUtil::FindChildVariable(m_pVariable, m_childIndexOverride, name);
|
||||
if (pChild)
|
||||
{
|
||||
CVariableIArchive childArchive(pChild);
|
||||
childArchive.SetFilter(GetFilter());
|
||||
childArchive.SetInnerContext(GetInnerContext());
|
||||
|
||||
ser(childArchive);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CVariableIArchive::SerializeResourceSelector(const Serialization::SStruct& ser, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
Serialization::IResourceSelector* pSelector = reinterpret_cast< Serialization::IResourceSelector* >(ser.pointer());
|
||||
|
||||
QString stringValue;
|
||||
const bool readSuccess = VarUtil::ReadChildVariableAs< QString >(m_pVariable, m_childIndexOverride, name, stringValue);
|
||||
if (readSuccess)
|
||||
{
|
||||
pSelector->SetValue(stringValue.toUtf8().data());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::SerializeStringListStaticValue(const Serialization::SStruct& ser, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
StringListStaticValue* const pStringListStaticValue = reinterpret_cast< StringListStaticValue* >(ser.pointer());
|
||||
|
||||
_smart_ptr< IVariable > pChild = VarUtil::FindChildVariable(m_pVariable, m_childIndexOverride, name);
|
||||
if (pChild)
|
||||
{
|
||||
int index = -1;
|
||||
pChild->Get(index);
|
||||
*pStringListStaticValue = index;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::SerializeRangeFloat(const Serialization::SStruct& ser, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
const Serialization::RangeDecorator< float >* const pRange = reinterpret_cast< Serialization::RangeDecorator< float >* >(ser.pointer());
|
||||
return VarUtil::ReadChildVariableAs< float >(m_pVariable, m_childIndexOverride, name, *pRange->value);
|
||||
}
|
||||
|
||||
|
||||
bool CVariableIArchive::SerializeRangeInt(const Serialization::SStruct& ser, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
const Serialization::RangeDecorator< int >* const pRange = reinterpret_cast< Serialization::RangeDecorator< int >* >(ser.pointer());
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, *pRange->value);
|
||||
}
|
||||
|
||||
bool CVariableIArchive::SerializeRangeUInt(const Serialization::SStruct& ser, const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
const Serialization::RangeDecorator< unsigned int >* const pRange = reinterpret_cast< Serialization::RangeDecorator< unsigned int >* >(ser.pointer());
|
||||
return VarUtil::ReadChildVariableAs< int >(m_pVariable, m_childIndexOverride, name, *pRange->value);
|
||||
}
|
||||
@@ -1,71 +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 "Util/Variable.h"
|
||||
#include "Serialization.h"
|
||||
|
||||
namespace Serialization
|
||||
{
|
||||
class CVariableIArchive
|
||||
: public IArchive
|
||||
{
|
||||
public:
|
||||
CVariableIArchive(const _smart_ptr< IVariable >& pVariable);
|
||||
virtual ~CVariableIArchive();
|
||||
|
||||
// IArchive
|
||||
virtual bool operator()(bool& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(IString& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(IWString& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(float& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(double& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(int16& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(uint16& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(int32& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(uint32& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(int64& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(uint64& value, const char* name = "", const char* label = 0) override;
|
||||
|
||||
virtual bool operator()(int8& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(uint8& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(char& value, const char* name = "", const char* label = 0);
|
||||
|
||||
virtual bool operator()(const SStruct& ser, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(IContainer& ser, const char* name = "", const char* label = 0) override;
|
||||
//virtual bool operator()( IPointer& ptr, const char* name = "", const char* label = 0 ) override;
|
||||
// ~IArchive
|
||||
|
||||
using IArchive::operator();
|
||||
|
||||
private:
|
||||
bool SerializeResourceSelector(const SStruct& ser, const char* name, const char* label);
|
||||
|
||||
bool SerializeStruct(const SStruct& ser, const char* name, const char* label);
|
||||
|
||||
bool SerializeStringListStaticValue(const SStruct& ser, const char* name, const char* label);
|
||||
|
||||
bool SerializeRangeFloat(const SStruct& ser, const char* name, const char* label);
|
||||
bool SerializeRangeInt(const SStruct& ser, const char* name, const char* label);
|
||||
bool SerializeRangeUInt(const SStruct& ser, const char* name, const char* label);
|
||||
|
||||
private:
|
||||
_smart_ptr< IVariable > m_pVariable;
|
||||
int m_childIndexOverride;
|
||||
|
||||
typedef bool ( CVariableIArchive::* StructHandlerFunctionPtr )(const SStruct&, const char*, const char*);
|
||||
typedef std::map< string, StructHandlerFunctionPtr > HandlersMap;
|
||||
HandlersMap m_structHandlers; // TODO: have only one of these.
|
||||
};
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "VariableOArchive.h"
|
||||
|
||||
// Editor
|
||||
#include "Serialization/Decorators/Resources.h"
|
||||
#include "Serialization/Decorators/Range.h"
|
||||
|
||||
|
||||
using Serialization::CVariableOArchive;
|
||||
|
||||
namespace VarUtil
|
||||
{
|
||||
template< typename T >
|
||||
_smart_ptr< IVariable > AddChildVariable(const _smart_ptr< IVariable >& pVariableArray, const T& value, const char* const name, const char* label)
|
||||
{
|
||||
CRY_ASSERT(pVariableArray);
|
||||
|
||||
_smart_ptr< IVariable > pVariable = new CVariable< T >();
|
||||
pVariable->SetName(name);
|
||||
pVariable->SetHumanName(label);
|
||||
pVariable->Set(value);
|
||||
|
||||
pVariableArray->AddVariable(pVariable);
|
||||
|
||||
return pVariable;
|
||||
}
|
||||
|
||||
template< typename TMin, typename TMax >
|
||||
void SetLimits(const _smart_ptr< IVariable >& pVariable, const TMin minValue, const TMax maxValue)
|
||||
{
|
||||
pVariable->SetLimits(static_cast< float >(minValue), static_cast< float >(maxValue));
|
||||
}
|
||||
}
|
||||
|
||||
CVariableOArchive::CVariableOArchive()
|
||||
: IArchive(IArchive::OUTPUT | IArchive::EDIT | IArchive::NO_EMPTY_NAMES)
|
||||
, m_pVariable(new CVariableArray())
|
||||
{
|
||||
m_resourceHandlers[ "Animation" ] = &CVariableOArchive::SerializeAnimationName;
|
||||
m_resourceHandlers[ "Sound" ] = &CVariableOArchive::SerializeSoundName;
|
||||
m_resourceHandlers[ "Model" ] = &CVariableOArchive::SerializeObjectFilename;
|
||||
|
||||
m_structHandlers[ TypeID::get < Serialization::IResourceSelector > ().name() ] = &CVariableOArchive::SerializeIResourceSelector;
|
||||
m_structHandlers[ TypeID::get < Serialization::RangeDecorator < float >> ().name() ] = &CVariableOArchive::SerializeRangeFloat;
|
||||
m_structHandlers[ TypeID::get < Serialization::RangeDecorator < int >> ().name() ] = &CVariableOArchive::SerializeRangeInt;
|
||||
m_structHandlers[ TypeID::get < Serialization::RangeDecorator < unsigned int >> ().name() ] = &CVariableOArchive::SerializeRangeUInt;
|
||||
m_structHandlers[ TypeID::get < StringListStaticValue > ().name() ] = &CVariableOArchive::SerializeStringListStaticValue;
|
||||
}
|
||||
|
||||
|
||||
CVariableOArchive::~CVariableOArchive()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
_smart_ptr< IVariable > CVariableOArchive::GetIVariable() const
|
||||
{
|
||||
return m_pVariable;
|
||||
}
|
||||
|
||||
|
||||
CVarBlockPtr CVariableOArchive::GetVarBlock() const
|
||||
{
|
||||
CVarBlockPtr pVarBlock = new CVarBlock();
|
||||
pVarBlock->AddVariable(m_pVariable);
|
||||
return pVarBlock;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(bool& value, const char* name, const char* label)
|
||||
{
|
||||
VarUtil::AddChildVariable< bool >(m_pVariable, value, name, label);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(Serialization::IString& value, const char* name, const char* label)
|
||||
{
|
||||
const QString valueString = value.get();
|
||||
VarUtil::AddChildVariable< QString >(m_pVariable, valueString, name, label);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()([[maybe_unused]] Serialization::IWString& value, [[maybe_unused]] const char* name, [[maybe_unused]] const char* label)
|
||||
{
|
||||
CryFatalError("CVarBlockOArchive::operator() with IWString is not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(float& value, const char* name, const char* label)
|
||||
{
|
||||
VarUtil::AddChildVariable< float >(m_pVariable, value, name, label);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(double& value, const char* name, const char* label)
|
||||
{
|
||||
VarUtil::AddChildVariable< float >(m_pVariable, value, name, label);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(int16& value, const char* name, const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, value, name, label);
|
||||
VarUtil::SetLimits(pVariable, SHRT_MIN, SHRT_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(uint16& value, const char* name, const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, value, name, label);
|
||||
VarUtil::SetLimits(pVariable, 0, USHRT_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(int32& value, const char* name, const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, value, name, label);
|
||||
VarUtil::SetLimits(pVariable, INT_MIN, INT_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(uint32& value, const char* name, const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, value, name, label);
|
||||
VarUtil::SetLimits(pVariable, 0, INT_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(int64& value, const char* name, const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, value, name, label);
|
||||
VarUtil::SetLimits(pVariable, INT_MIN, INT_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(uint64& value, const char* name, const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, value, name, label);
|
||||
VarUtil::SetLimits(pVariable, 0, INT_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(int8& value, const char* name, const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, value, name, label);
|
||||
VarUtil::SetLimits(pVariable, SCHAR_MIN, SCHAR_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(uint8& value, const char* name, const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, value, name, label);
|
||||
VarUtil::SetLimits(pVariable, 0, UCHAR_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(char& value, const char* name, const char* label)
|
||||
{
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, value, name, label);
|
||||
VarUtil::SetLimits(pVariable, CHAR_MIN, CHAR_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::operator()(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
const char* const typeName = ser.type().name();
|
||||
HandlersMap::const_iterator it = m_structHandlers.find(typeName);
|
||||
const bool handlerFound = (it != m_structHandlers.end());
|
||||
if (handlerFound)
|
||||
{
|
||||
StructHandlerFunctionPtr pHandler = it->second;
|
||||
return (this->*pHandler)(ser, name, label);
|
||||
}
|
||||
|
||||
return SerializeStruct(ser, name, label);
|
||||
}
|
||||
|
||||
static const char* gVec4Names[] = { "X", "Y", "Z", "W" };
|
||||
static const char* gEmptyNames[] = { "" };
|
||||
|
||||
bool CVariableOArchive::operator()(Serialization::IContainer& ser, const char* name, const char* label)
|
||||
{
|
||||
CVariableOArchive childArchive;
|
||||
childArchive.SetFilter(GetFilter());
|
||||
childArchive.SetInnerContext(GetInnerContext());
|
||||
|
||||
_smart_ptr< IVariable > pChildVariable = childArchive.GetIVariable();
|
||||
pChildVariable->SetName(name);
|
||||
pChildVariable->SetHumanName(label);
|
||||
|
||||
m_pVariable->AddVariable(pChildVariable);
|
||||
|
||||
const size_t containerSize = ser.size();
|
||||
|
||||
const char** nameArray = gEmptyNames;
|
||||
size_t nameArraySize = 1;
|
||||
if (containerSize >= 2 && containerSize <= 4)
|
||||
{
|
||||
nameArray = gVec4Names;
|
||||
nameArraySize = containerSize;
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
if (0 < containerSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
ser(childArchive, nameArray[index % nameArraySize], nameArray[index % nameArraySize]);
|
||||
++index;
|
||||
} while (ser.next());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::SerializeStruct(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
CVariableOArchive childArchive;
|
||||
childArchive.SetFilter(GetFilter());
|
||||
childArchive.SetInnerContext(GetInnerContext());
|
||||
|
||||
_smart_ptr< IVariable > pChildVariable = childArchive.GetIVariable();
|
||||
pChildVariable->SetName(name);
|
||||
pChildVariable->SetHumanName(label);
|
||||
|
||||
m_pVariable->AddVariable(pChildVariable);
|
||||
|
||||
const bool serializeSuccess = ser(childArchive);
|
||||
|
||||
return serializeSuccess;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::SerializeAnimationName(const Serialization::IResourceSelector* pSelector, const char* name, const char* label)
|
||||
{
|
||||
const QString valueString = pSelector->GetValue();
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< QString >(m_pVariable, valueString, name, label);
|
||||
pVariable->SetDataType(IVariable::DT_ANIMATION);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::SerializeSoundName(const Serialization::IResourceSelector* pSelector, const char* name, const char* label)
|
||||
{
|
||||
const QString valueString = pSelector->GetValue();
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< QString >(m_pVariable, valueString, name, label);
|
||||
pVariable->SetDataType(IVariable::DT_AUDIO_TRIGGER);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CVariableOArchive::CreateChildEnumVariable(const QStringList& enumValues, const QString& value, const char* name, const char* label)
|
||||
{
|
||||
if (enumValues.empty())
|
||||
{
|
||||
VarUtil::AddChildVariable< QString >(m_pVariable, value, name, label);
|
||||
}
|
||||
else
|
||||
{
|
||||
_smart_ptr< CVariableEnum< QString > > pVariable = new CVariableEnum< QString >();
|
||||
pVariable->SetName(name);
|
||||
pVariable->SetHumanName(label);
|
||||
|
||||
pVariable->AddEnumItem("", "");
|
||||
|
||||
const size_t enumValuesCount = enumValues.size();
|
||||
for (size_t i = 0; i < enumValuesCount; ++i)
|
||||
{
|
||||
pVariable->AddEnumItem(enumValues[ i ], enumValues[ i ]);
|
||||
}
|
||||
|
||||
pVariable->Set(value);
|
||||
|
||||
m_pVariable->AddVariable(pVariable);
|
||||
}
|
||||
}
|
||||
|
||||
bool CVariableOArchive::SerializeObjectFilename(const Serialization::IResourceSelector* pSelector, const char* name, const char* label)
|
||||
{
|
||||
const QString valueString = pSelector->GetValue();
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< QString >(m_pVariable, valueString, name, label);
|
||||
pVariable->SetDataType(IVariable::DT_OBJECT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CVariableOArchive::SerializeStringListStaticValue(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
const StringListStaticValue* const pStringListStaticValue = reinterpret_cast< StringListStaticValue* >(ser.pointer());
|
||||
const StringListStatic& stringListStatic = pStringListStaticValue->stringList();
|
||||
const int index = pStringListStaticValue->index();
|
||||
|
||||
_smart_ptr< CVariableEnum< int > > pVariable = new CVariableEnum< int >();
|
||||
pVariable->SetName(name);
|
||||
pVariable->SetHumanName(label);
|
||||
|
||||
const size_t stringListStaticSize = stringListStatic.size();
|
||||
for (size_t i = 0; i < stringListStaticSize; ++i)
|
||||
{
|
||||
pVariable->AddEnumItem(stringListStatic[ i ], static_cast< int >(i));
|
||||
}
|
||||
|
||||
if (0 <= index)
|
||||
{
|
||||
CRY_ASSERT(index < stringListStaticSize);
|
||||
pVariable->Set(static_cast< int >(index));
|
||||
}
|
||||
|
||||
m_pVariable->AddVariable(pVariable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVariableOArchive::SerializeIResourceSelector(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
const Serialization::IResourceSelector* pSelector = reinterpret_cast< Serialization::IResourceSelector* >(ser.pointer());
|
||||
|
||||
ResourceHandlersMap::iterator it = m_resourceHandlers.find(pSelector->resourceType);
|
||||
if (it != m_resourceHandlers.end())
|
||||
{
|
||||
return (this->*(it->second))(pSelector, name, label);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void SetLimits(IVariable* pVariable, const Serialization::RangeDecorator<T>* pRange, float stepValue)
|
||||
{
|
||||
if (pRange->softMin != std::numeric_limits<T>::lowest() || pRange->softMax != std::numeric_limits<T>::max())
|
||||
{
|
||||
float minimal = (float)pRange->softMin;
|
||||
float maximal = (float)pRange->softMax;
|
||||
bool hardMin = false;
|
||||
bool hardMax = false;
|
||||
if (pRange->hardMin != std::numeric_limits<T>::lowest())
|
||||
{
|
||||
minimal = pRange->hardMin;
|
||||
hardMin = true;
|
||||
}
|
||||
if (pRange->hardMax != std::numeric_limits<T>::max())
|
||||
{
|
||||
maximal = pRange->hardMax;
|
||||
hardMax = true;
|
||||
}
|
||||
pVariable->SetLimits(minimal, maximal, stepValue, hardMin, hardMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
float minimal = 0.0f;
|
||||
float maximal = 0.0f;
|
||||
float oldStep = 0.0f;
|
||||
bool hardMin = false;
|
||||
bool hardMax = false;
|
||||
pVariable->GetLimits(minimal, maximal, oldStep, hardMin, hardMax);
|
||||
pVariable->SetLimits(minimal, maximal, stepValue, hardMin, hardMax);
|
||||
}
|
||||
}
|
||||
|
||||
bool CVariableOArchive::SerializeRangeFloat(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
const Serialization::RangeDecorator< float >* const pRange = reinterpret_cast< Serialization::RangeDecorator< float >* >(ser.pointer());
|
||||
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< float >(m_pVariable, *pRange->value, name, label);
|
||||
|
||||
SetLimits(pVariable.get(), pRange, 0.01f);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVariableOArchive::SerializeRangeInt(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
const Serialization::RangeDecorator< int >* const pRange = reinterpret_cast< Serialization::RangeDecorator< int >* >(ser.pointer());
|
||||
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, *pRange->value, name, label);
|
||||
SetLimits(pVariable.get(), pRange, 1.0f);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVariableOArchive::SerializeRangeUInt(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
const Serialization::RangeDecorator< unsigned int >* const pRange = reinterpret_cast< Serialization::RangeDecorator< unsigned int >* >(ser.pointer());
|
||||
|
||||
_smart_ptr< IVariable > pVariable = VarUtil::AddChildVariable< int >(m_pVariable, *pRange->value, name, label);
|
||||
SetLimits(pVariable, pRange, 1.0f);
|
||||
return true;
|
||||
}
|
||||
@@ -1,83 +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 "Util/Variable.h"
|
||||
#include "Serialization.h"
|
||||
|
||||
|
||||
namespace Serialization
|
||||
{
|
||||
struct IResourceSelector;
|
||||
|
||||
class CVariableOArchive
|
||||
: public IArchive
|
||||
{
|
||||
public:
|
||||
CVariableOArchive();
|
||||
virtual ~CVariableOArchive();
|
||||
|
||||
_smart_ptr< IVariable > GetIVariable() const;
|
||||
CVarBlockPtr GetVarBlock() const;
|
||||
|
||||
// IArchive
|
||||
virtual bool operator()(bool& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(IString& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(IWString& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(float& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(double& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(int16& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(uint16& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(int32& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(uint32& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(int64& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(uint64& value, const char* name = "", const char* label = 0) override;
|
||||
|
||||
virtual bool operator()(int8& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(uint8& value, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(char& value, const char* name = "", const char* label = 0);
|
||||
|
||||
virtual bool operator()(const SStruct& ser, const char* name = "", const char* label = 0) override;
|
||||
virtual bool operator()(IContainer& ser, const char* name = "", const char* label = 0) override;
|
||||
//virtual bool operator()( IPointer& ptr, const char* name = "", const char* label = 0 ) override;
|
||||
// ~IArchive
|
||||
|
||||
using IArchive::operator();
|
||||
|
||||
private:
|
||||
bool SerializeStruct(const SStruct& ser, const char* name, const char* label);
|
||||
bool SerializeStringListStaticValue(const SStruct& ser, const char* name, const char* label);
|
||||
bool SerializeRangeFloat(const SStruct& ser, const char* name, const char* label);
|
||||
bool SerializeRangeInt(const SStruct& ser, const char* name, const char* label);
|
||||
bool SerializeRangeUInt(const SStruct& ser, const char* name, const char* label);
|
||||
bool SerializeIResourceSelector(const SStruct& ser, const char* name, const char* label);
|
||||
|
||||
bool SerializeAnimationName(const IResourceSelector* pSelector, const char* name, const char* label);
|
||||
bool SerializeSoundName(const IResourceSelector* pSelector, const char* name, const char* label);
|
||||
bool SerializeObjectFilename(const IResourceSelector* pSelector, const char* name, const char* label);
|
||||
|
||||
void CreateChildEnumVariable(const QStringList& enumValues, const QString& value, const char* name, const char* label);
|
||||
|
||||
private:
|
||||
_smart_ptr< IVariable > m_pVariable;
|
||||
|
||||
typedef bool ( CVariableOArchive::* StructHandlerFunctionPtr )(const SStruct&, const char*, const char*);
|
||||
typedef std::map< string, StructHandlerFunctionPtr > HandlersMap;
|
||||
HandlersMap m_structHandlers; // TODO: have only one of these.
|
||||
|
||||
typedef bool ( CVariableOArchive::* ResourceHandlerFunctionPtr )(const IResourceSelector*, const char*, const char*);
|
||||
typedef std::map< string, ResourceHandlerFunctionPtr > ResourceHandlersMap;
|
||||
ResourceHandlersMap m_resourceHandlers;
|
||||
};
|
||||
}
|
||||
@@ -1,177 +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 "SettingsBlock.h"
|
||||
|
||||
// CryCommon
|
||||
#include <CryCommon/Serialization/ITextInputArchive.h>
|
||||
#include <CryCommon/Serialization/ITextOutputArchive.h>
|
||||
|
||||
// Editor
|
||||
#include "Serialization.h"
|
||||
|
||||
using std::vector;
|
||||
|
||||
SProjectSettingsBlock* SProjectSettingsBlock::s_pLastBlock;
|
||||
|
||||
SProjectSettingsBlock::SProjectSettingsBlock(const char* name, const char* label)
|
||||
: m_name(name)
|
||||
, m_label(label)
|
||||
{
|
||||
m_pPrevious = s_pLastBlock;
|
||||
s_pLastBlock = this;
|
||||
}
|
||||
|
||||
|
||||
struct SAllSettingsSerializer
|
||||
{
|
||||
void Serialize(Serialization::IArchive& ar)
|
||||
{
|
||||
SProjectSettingsBlock* pCurrent = SProjectSettingsBlock::s_pLastBlock;
|
||||
while (pCurrent != 0)
|
||||
{
|
||||
ar(*pCurrent, pCurrent->GetName(), pCurrent->GetLabel());
|
||||
pCurrent = pCurrent->m_pPrevious;
|
||||
}
|
||||
}
|
||||
} static gAllSettingsSerializer;
|
||||
|
||||
void SProjectSettingsBlock::GetAllSettingsSerializer(Serialization::SStruct* pSerializer)
|
||||
{
|
||||
*pSerializer = Serialization::SStruct(gAllSettingsSerializer);
|
||||
}
|
||||
|
||||
SProjectSettingsBlock* SProjectSettingsBlock::Find(const char* blockName)
|
||||
{
|
||||
SProjectSettingsBlock* pCurrent = SProjectSettingsBlock::s_pLastBlock;
|
||||
while (pCurrent != 0)
|
||||
{
|
||||
if (_stricmp(pCurrent->GetName(), blockName) == 0)
|
||||
{
|
||||
return pCurrent;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool ReadFileContent(vector<char>* pBuffer, const char* filename)
|
||||
{
|
||||
AZ::IO::HandleType fileHandle = gEnv->pCryPak->FOpen(filename, "rb");
|
||||
if (fileHandle == AZ::IO::InvalidHandle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size = gEnv->pCryPak->FGetSize(fileHandle);
|
||||
pBuffer->resize(size);
|
||||
|
||||
bool result = true;
|
||||
if (gEnv->pCryPak->FRead(&(*pBuffer)[0], size, fileHandle) != size)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
gEnv->pCryPak->FClose(fileHandle);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool SaveFileContent(const char* filename, const char* pBuffer, size_t length)
|
||||
{
|
||||
string fullpath = Path::GamePathToFullPath(filename).toUtf8().data();
|
||||
|
||||
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
|
||||
if (!gEnv->pFileIO->Open(fullpath.c_str(), AZ::IO::GetOpenModeFromStringMode("wb"), fileHandle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
if (!gEnv->pFileIO->Write(fileHandle, pBuffer, length))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
gEnv->pFileIO->Close(fileHandle);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool SaveFileContentIfDiffers(const char* filename, const char* pBuffer, size_t length)
|
||||
{
|
||||
vector<char> content;
|
||||
ReadFileContent(&content, filename);
|
||||
|
||||
bool needToWrite = true;
|
||||
if (!content.empty() && content.size() == length)
|
||||
{
|
||||
needToWrite = memcmp(&content[0], pBuffer, length) != 0;
|
||||
}
|
||||
|
||||
if (needToWrite)
|
||||
{
|
||||
return SaveFileContent(filename, pBuffer, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SProjectSettingsBlock::Load()
|
||||
{
|
||||
const char* filename = GetFilename();
|
||||
|
||||
vector<char> content;
|
||||
if (!ReadFileContent(&content, filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto pArchive(Serialization::CreateTextInputArchive());
|
||||
if (!pArchive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pArchive->AttachMemory(&content[0], content.size()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Serialization::SStruct serializer;
|
||||
GetAllSettingsSerializer(&serializer);
|
||||
serializer(*pArchive);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SProjectSettingsBlock::Save()
|
||||
{
|
||||
const char* filename = GetFilename();
|
||||
auto pArchive(Serialization::CreateTextOutputArchive());
|
||||
if (!pArchive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Serialization::SStruct serializer;
|
||||
GetAllSettingsSerializer(&serializer);
|
||||
serializer(*pArchive);
|
||||
|
||||
return SaveFileContentIfDiffers(filename, pArchive->GetBuffer(), pArchive->GetBufferLength());
|
||||
}
|
||||
|
||||
const char* SProjectSettingsBlock::GetFilename()
|
||||
{
|
||||
return "SandboxSettings.json";
|
||||
}
|
||||
|
||||
@@ -1,76 +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
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Following utility can be used to add blocks of per-project settings.
|
||||
// Example:
|
||||
//
|
||||
// MyComponent.cpp:
|
||||
//
|
||||
// struct SProjectSettingsMy : SProjectSettingsBlock
|
||||
// {
|
||||
// bool bMyOption;
|
||||
//
|
||||
// SProjectSettingsMy()
|
||||
// : SProjectSettingsBlock("my", "My")
|
||||
// , bMyOption(false)
|
||||
// {}
|
||||
//
|
||||
// void Serialize(Serialization::IArchive& ar)
|
||||
// {
|
||||
// ar(bMyOption, "myOption", "My Option");
|
||||
// }
|
||||
//
|
||||
// } static gMySettings;
|
||||
//
|
||||
//
|
||||
// Now gMySettings will be loaded and saved automatically and available for
|
||||
// editing through:
|
||||
//
|
||||
// GetIEditor()->OpenProjectSettings("my");
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
#ifndef CRYINCLUDE_EDITOR_SETTINGSBLOCK_H
|
||||
#define CRYINCLUDE_EDITOR_SETTINGSBLOCK_H
|
||||
|
||||
namespace Serialization
|
||||
{
|
||||
class IArchive;
|
||||
struct SStruct;
|
||||
};
|
||||
|
||||
struct SProjectSettingsBlock
|
||||
{
|
||||
SProjectSettingsBlock(const char* name, const char* label);
|
||||
|
||||
virtual void Serialize(Serialization::IArchive& ar) = 0;
|
||||
|
||||
const char* GetName() const{ return m_name; }
|
||||
const char* GetLabel() const{ return m_label; }
|
||||
|
||||
static void GetAllSettingsSerializer(Serialization::SStruct* serializer);
|
||||
static SProjectSettingsBlock* Find(const char* name);
|
||||
static bool Load();
|
||||
static bool Save();
|
||||
static const char* GetFilename();
|
||||
private:
|
||||
const char* m_name;
|
||||
const char* m_label;
|
||||
SProjectSettingsBlock* m_pPrevious;
|
||||
static SProjectSettingsBlock* s_pLastBlock;
|
||||
friend struct SAllSettingsSerializer;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_SETTINGSBLOCK_H
|
||||
@@ -595,10 +595,6 @@ AmazonToolbar ToolbarManager::GetEditModeToolbar() const
|
||||
t.AddAction(ID_TOOLBAR_WIDGET_SNAP_GRID, ORIGINAL_TOOLBAR_VERSION);
|
||||
t.AddAction(ID_TOOLBAR_WIDGET_SNAP_ANGLE, ORIGINAL_TOOLBAR_VERSION);
|
||||
|
||||
t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION);
|
||||
t.AddAction(ID_TOOLBAR_WIDGET_ENVIRONMENT_MODE, ORIGINAL_TOOLBAR_VERSION);
|
||||
t.AddAction(ID_TOOLBAR_WIDGET_DEBUG_MODE, ORIGINAL_TOOLBAR_VERSION);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,38 +27,3 @@ void CUsedResources::Add(const char* pResourceFileName)
|
||||
files.insert(pResourceFileName);
|
||||
}
|
||||
}
|
||||
|
||||
void CUsedResources::Validate(IErrorReport* pReport)
|
||||
{
|
||||
auto pPak = gEnv->pCryPak;
|
||||
|
||||
for (TResourceFiles::iterator it = files.begin(); it != files.end(); ++it)
|
||||
{
|
||||
const QString& filename = *it;
|
||||
|
||||
bool fileExists = pPak->IsFileExist(filename.toUtf8().data());
|
||||
|
||||
if (!fileExists)
|
||||
{
|
||||
for (int i = 0; !fileExists && i < IResourceCompilerHelper::GetNumEngineImageFormats(); ++i)
|
||||
{
|
||||
fileExists = gEnv->pCryPak->IsFileExist(PathUtil::ReplaceExtension(filename.toUtf8().data(), IResourceCompilerHelper::GetEngineImageFormat(i, true)).c_str());
|
||||
}
|
||||
for (int i = 0; !fileExists && i < IResourceCompilerHelper::GetNumSourceImageFormats(); ++i)
|
||||
{
|
||||
fileExists = gEnv->pCryPak->IsFileExist(PathUtil::ReplaceExtension(filename.toUtf8().data(), IResourceCompilerHelper::GetSourceImageFormat(i, true)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!fileExists)
|
||||
{
|
||||
CErrorRecord err;
|
||||
|
||||
err.error = QObject::tr("Resource File %1 not found,").arg(filename);
|
||||
err.severity = CErrorRecord::ESEVERITY_ERROR;
|
||||
err.flags |= CErrorRecord::FLAG_NOFILE;
|
||||
pReport->ReportError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ public:
|
||||
|
||||
CUsedResources();
|
||||
void Add(const char* pResourceFileName);
|
||||
//! validate gathered resources, reports warning if resource is not found
|
||||
void Validate(struct IErrorReport* pReport);
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
TResourceFiles files;
|
||||
|
||||
@@ -21,206 +21,228 @@
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
static const auto ManipulatorPriority = AzFramework::ViewportControllerPriority::High;
|
||||
static const auto InteractionPriority = AzFramework::ViewportControllerPriority::Low;
|
||||
static const auto ManipulatorPriority = AzFramework::ViewportControllerPriority::Highest;
|
||||
static const auto InteractionPriority = AzFramework::ViewportControllerPriority::High;
|
||||
|
||||
namespace SandboxEditor
|
||||
{
|
||||
|
||||
ViewportManipulatorControllerInstance::ViewportManipulatorControllerInstance(AzFramework::ViewportId viewport, ViewportManipulatorController* controller)
|
||||
: AzFramework::MultiViewportControllerInstanceInterface<ViewportManipulatorController>(viewport, controller)
|
||||
{
|
||||
}
|
||||
|
||||
AzToolsFramework::ViewportInteraction::MouseButton ViewportManipulatorControllerInstance::GetMouseButton(
|
||||
const AzFramework::InputChannel& inputChannel)
|
||||
{
|
||||
using AzToolsFramework::ViewportInteraction::MouseButton;
|
||||
using InputButton = AzFramework::InputDeviceMouse::Button;
|
||||
const auto& id = inputChannel.GetInputChannelId();
|
||||
if (id == InputButton::Left)
|
||||
ViewportManipulatorControllerInstance::ViewportManipulatorControllerInstance(
|
||||
AzFramework::ViewportId viewport, ViewportManipulatorController* controller)
|
||||
: AzFramework::MultiViewportControllerInstanceInterface<ViewportManipulatorController>(viewport, controller)
|
||||
{
|
||||
return MouseButton::Left;
|
||||
}
|
||||
if (id == InputButton::Middle)
|
||||
{
|
||||
return MouseButton::Middle;
|
||||
}
|
||||
if (id == InputButton::Right)
|
||||
{
|
||||
return MouseButton::Right;
|
||||
}
|
||||
return MouseButton::None;
|
||||
}
|
||||
|
||||
bool ViewportManipulatorControllerInstance::IsMouseMove(const AzFramework::InputChannel& inputChannel)
|
||||
{
|
||||
return inputChannel.GetInputChannelId() == AzFramework::InputDeviceMouse::SystemCursorPosition;
|
||||
}
|
||||
|
||||
AzToolsFramework::ViewportInteraction::KeyboardModifier ViewportManipulatorControllerInstance::GetKeyboardModifier(
|
||||
const AzFramework::InputChannel& inputChannel)
|
||||
{
|
||||
using AzToolsFramework::ViewportInteraction::KeyboardModifier;
|
||||
using Key = AzFramework::InputDeviceKeyboard::Key;
|
||||
const auto& id = inputChannel.GetInputChannelId();
|
||||
if (id == Key::ModifierAltL || id == Key::ModifierAltR)
|
||||
{
|
||||
return KeyboardModifier::Alt;
|
||||
}
|
||||
if (id == Key::ModifierCtrlL || id == Key::ModifierCtrlR)
|
||||
{
|
||||
return KeyboardModifier::Ctrl;
|
||||
}
|
||||
if (id == Key::ModifierShiftL || id == Key::ModifierShiftR)
|
||||
{
|
||||
return KeyboardModifier::Shift;
|
||||
}
|
||||
return KeyboardModifier::None;
|
||||
}
|
||||
|
||||
bool ViewportManipulatorControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
|
||||
{
|
||||
// We only care about manipulator and viewport interaction events
|
||||
if (event.m_priority != ManipulatorPriority && event.m_priority != InteractionPriority)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using InteractionBus = AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
|
||||
using namespace AzToolsFramework::ViewportInteraction;
|
||||
using AzFramework::InputChannel;
|
||||
|
||||
bool interactionHandled = false;
|
||||
AZStd::optional<MouseButton> overrideButton;
|
||||
AZStd::optional<MouseEvent> eventType;
|
||||
|
||||
// Because we receive events multiple times at separate priorities for manipulator events and
|
||||
// viewport interaction events, we want to avoid updating our "last tick state" until we're on our last event,
|
||||
// which currently is the low priority Interaction processor.
|
||||
const bool finishedProcessingEvents = event.m_priority == InteractionPriority;
|
||||
|
||||
if (IsMouseMove(event.m_inputChannel))
|
||||
AzToolsFramework::ViewportInteraction::MouseButton ViewportManipulatorControllerInstance::GetMouseButton(
|
||||
const AzFramework::InputChannel& inputChannel)
|
||||
{
|
||||
// Cache the ray trace results when doing manipulator interaction checks, no need to recalculate after
|
||||
if (event.m_priority == ManipulatorPriority)
|
||||
using AzToolsFramework::ViewportInteraction::MouseButton;
|
||||
using InputButton = AzFramework::InputDeviceMouse::Button;
|
||||
const auto& id = inputChannel.GetInputChannelId();
|
||||
if (id == InputButton::Left)
|
||||
{
|
||||
AzFramework::ScreenPoint screenPosition = AzFramework::ScreenPoint(0, 0);
|
||||
ViewportMouseCursorRequestBus::EventResult(
|
||||
screenPosition, GetViewportId(), &ViewportMouseCursorRequestBus::Events::ViewportCursorScreenPosition);
|
||||
|
||||
m_state.m_mousePick.m_screenCoordinates = screenPosition;
|
||||
AZStd::optional<ProjectedViewportRay> ray;
|
||||
ViewportInteractionRequestBus::EventResult(
|
||||
ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPosition);
|
||||
|
||||
if (ray.has_value())
|
||||
{
|
||||
m_state.m_mousePick.m_rayOrigin = ray.value().origin;
|
||||
m_state.m_mousePick.m_rayDirection = ray.value().direction;
|
||||
}
|
||||
return MouseButton::Left;
|
||||
}
|
||||
eventType = MouseEvent::Move;
|
||||
}
|
||||
else if (auto mouseButton = GetMouseButton(event.m_inputChannel); mouseButton != MouseButton::None)
|
||||
{
|
||||
const AZ::u32 mouseButtonValue = static_cast<AZ::u32>(mouseButton);
|
||||
overrideButton = mouseButton;
|
||||
if (event.m_inputChannel.GetState() == InputChannel::State::Began)
|
||||
if (id == InputButton::Middle)
|
||||
{
|
||||
m_state.m_mouseButtons.m_mouseButtons |= mouseButtonValue;
|
||||
if (IsDoubleClick(mouseButton))
|
||||
return MouseButton::Middle;
|
||||
}
|
||||
if (id == InputButton::Right)
|
||||
{
|
||||
return MouseButton::Right;
|
||||
}
|
||||
return MouseButton::None;
|
||||
}
|
||||
|
||||
bool ViewportManipulatorControllerInstance::IsMouseMove(const AzFramework::InputChannel& inputChannel)
|
||||
{
|
||||
return inputChannel.GetInputChannelId() == AzFramework::InputDeviceMouse::SystemCursorPosition;
|
||||
}
|
||||
|
||||
AzToolsFramework::ViewportInteraction::KeyboardModifier ViewportManipulatorControllerInstance::GetKeyboardModifier(
|
||||
const AzFramework::InputChannel& inputChannel)
|
||||
{
|
||||
using AzToolsFramework::ViewportInteraction::KeyboardModifier;
|
||||
using Key = AzFramework::InputDeviceKeyboard::Key;
|
||||
const auto& id = inputChannel.GetInputChannelId();
|
||||
if (id == Key::ModifierAltL || id == Key::ModifierAltR)
|
||||
{
|
||||
return KeyboardModifier::Alt;
|
||||
}
|
||||
if (id == Key::ModifierCtrlL || id == Key::ModifierCtrlR)
|
||||
{
|
||||
return KeyboardModifier::Ctrl;
|
||||
}
|
||||
if (id == Key::ModifierShiftL || id == Key::ModifierShiftR)
|
||||
{
|
||||
return KeyboardModifier::Shift;
|
||||
}
|
||||
return KeyboardModifier::None;
|
||||
}
|
||||
|
||||
bool ViewportManipulatorControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
|
||||
{
|
||||
// We only care about manipulator and viewport interaction events
|
||||
if (event.m_priority != ManipulatorPriority && event.m_priority != InteractionPriority)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using InteractionBus = AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
|
||||
using namespace AzToolsFramework::ViewportInteraction;
|
||||
using AzFramework::InputChannel;
|
||||
|
||||
bool interactionHandled = false;
|
||||
float wheelDelta = 0.0f;
|
||||
AZStd::optional<MouseButton> overrideButton;
|
||||
AZStd::optional<MouseEvent> eventType;
|
||||
|
||||
// Because we receive events multiple times at separate priorities for manipulator events and
|
||||
// viewport interaction events, we want to avoid updating our "last tick state" until we're on our last event,
|
||||
// which currently is the low priority Interaction processor.
|
||||
const bool finishedProcessingEvents = event.m_priority == InteractionPriority;
|
||||
|
||||
const auto state = event.m_inputChannel.GetState();
|
||||
if (IsMouseMove(event.m_inputChannel))
|
||||
{
|
||||
// Cache the ray trace results when doing manipulator interaction checks, no need to recalculate after
|
||||
if (event.m_priority == ManipulatorPriority)
|
||||
{
|
||||
// Only remove the double click flag once we're done processing both Manipulator and Interaction events
|
||||
if (event.m_priority == InteractionPriority)
|
||||
AzFramework::ScreenPoint screenPosition = AzFramework::ScreenPoint(0, 0);
|
||||
ViewportMouseCursorRequestBus::EventResult(
|
||||
screenPosition, GetViewportId(), &ViewportMouseCursorRequestBus::Events::ViewportCursorScreenPosition);
|
||||
|
||||
m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPosition;
|
||||
AZStd::optional<ProjectedViewportRay> ray;
|
||||
ViewportInteractionRequestBus::EventResult(
|
||||
ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPosition);
|
||||
|
||||
if (ray.has_value())
|
||||
{
|
||||
m_pendingDoubleClicks.erase(mouseButton);
|
||||
m_mouseInteraction.m_mousePick.m_rayOrigin = ray.value().origin;
|
||||
m_mouseInteraction.m_mousePick.m_rayDirection = ray.value().direction;
|
||||
}
|
||||
eventType = MouseEvent::DoubleClick;
|
||||
}
|
||||
else
|
||||
eventType = MouseEvent::Move;
|
||||
}
|
||||
else if (auto mouseButton = GetMouseButton(event.m_inputChannel); mouseButton != MouseButton::None)
|
||||
{
|
||||
const AZ::u32 mouseButtonValue = static_cast<AZ::u32>(mouseButton);
|
||||
overrideButton = mouseButton;
|
||||
if (state == InputChannel::State::Began)
|
||||
{
|
||||
// Only insert the double click timing once we're done processing events, to avoid a false IsDoubleClick positive
|
||||
if (finishedProcessingEvents)
|
||||
m_mouseInteraction.m_mouseButtons.m_mouseButtons |= mouseButtonValue;
|
||||
if (IsDoubleClick(mouseButton))
|
||||
{
|
||||
m_pendingDoubleClicks[mouseButton] = m_curTime;
|
||||
// Only remove the double click flag once we're done processing both Manipulator and Interaction events
|
||||
if (event.m_priority == InteractionPriority)
|
||||
{
|
||||
m_pendingDoubleClicks.erase(mouseButton);
|
||||
}
|
||||
eventType = MouseEvent::DoubleClick;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only insert the double click timing once we're done processing events, to avoid a false IsDoubleClick positive
|
||||
if (finishedProcessingEvents)
|
||||
{
|
||||
m_pendingDoubleClicks[mouseButton] = m_curTime;
|
||||
}
|
||||
eventType = MouseEvent::Down;
|
||||
}
|
||||
eventType = MouseEvent::Down;
|
||||
}
|
||||
}
|
||||
else if (event.m_inputChannel.GetState() == InputChannel::State::Ended)
|
||||
{
|
||||
// If we've actually logged a mouse down event, forward a mouse up event.
|
||||
// This prevents corner cases like the context menu thinking it should be opened even though no one clicked in this viewport,
|
||||
// due to RenderViewportWidget ensuring all controllers get InputChannel::State::Ended events.
|
||||
if (m_state.m_mouseButtons.m_mouseButtons & mouseButtonValue)
|
||||
else if (state == InputChannel::State::Ended)
|
||||
{
|
||||
// Erase the button from our state if we're done processing events.
|
||||
if (event.m_priority == InteractionPriority)
|
||||
// If we've actually logged a mouse down event, forward a mouse up event.
|
||||
// This prevents corner cases like the context menu thinking it should be opened even though no one clicked in this viewport,
|
||||
// due to RenderViewportWidget ensuring all controllers get InputChannel::State::Ended events.
|
||||
if (m_mouseInteraction.m_mouseButtons.m_mouseButtons & mouseButtonValue)
|
||||
{
|
||||
m_state.m_mouseButtons.m_mouseButtons &= ~mouseButtonValue;
|
||||
// Erase the button from our state if we're done processing events.
|
||||
if (event.m_priority == InteractionPriority)
|
||||
{
|
||||
m_mouseInteraction.m_mouseButtons.m_mouseButtons &= ~mouseButtonValue;
|
||||
}
|
||||
eventType = MouseEvent::Up;
|
||||
}
|
||||
eventType = MouseEvent::Up;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (auto keyboardModifier = GetKeyboardModifier(event.m_inputChannel); keyboardModifier != KeyboardModifier::None)
|
||||
{
|
||||
if (event.m_inputChannel.GetState() == InputChannel::State::Began || event.m_inputChannel.GetState() == InputChannel::State::Updated)
|
||||
else if (auto keyboardModifier = GetKeyboardModifier(event.m_inputChannel); keyboardModifier != KeyboardModifier::None)
|
||||
{
|
||||
m_state.m_keyboardModifiers.m_keyModifiers |= static_cast<AZ::u32>(keyboardModifier);
|
||||
if (state == InputChannel::State::Began || state == InputChannel::State::Updated)
|
||||
{
|
||||
m_mouseInteraction.m_keyboardModifiers.m_keyModifiers |= static_cast<AZ::u32>(keyboardModifier);
|
||||
}
|
||||
else if (state == InputChannel::State::Ended)
|
||||
{
|
||||
m_mouseInteraction.m_keyboardModifiers.m_keyModifiers &= ~static_cast<AZ::u32>(keyboardModifier);
|
||||
}
|
||||
}
|
||||
else if (event.m_inputChannel.GetState() == InputChannel::State::Ended)
|
||||
else if (event.m_inputChannel.GetInputChannelId() == AzFramework::InputDeviceMouse::Movement::Z)
|
||||
{
|
||||
m_state.m_keyboardModifiers.m_keyModifiers &= ~static_cast<AZ::u32>(keyboardModifier);
|
||||
if (state == InputChannel::State::Began || state == InputChannel::State::Updated)
|
||||
{
|
||||
eventType = MouseEvent::Wheel;
|
||||
wheelDelta = event.m_inputChannel.GetValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eventType)
|
||||
{
|
||||
MouseInteraction mouseInteraction = m_state;
|
||||
if (overrideButton)
|
||||
if (eventType)
|
||||
{
|
||||
mouseInteraction.m_mouseButtons.m_mouseButtons = static_cast<AZ::u32>(overrideButton.value());
|
||||
MouseInteraction mouseInteraction = m_mouseInteraction;
|
||||
if (overrideButton)
|
||||
{
|
||||
mouseInteraction.m_mouseButtons.m_mouseButtons = static_cast<AZ::u32>(overrideButton.value());
|
||||
}
|
||||
|
||||
mouseInteraction.m_interactionId.m_viewportId = GetViewportId();
|
||||
|
||||
// Depending on priority, we dispatch to either the manipulator or viewport interaction event
|
||||
const auto& targetInteractionEvent = event.m_priority == ManipulatorPriority
|
||||
? &InteractionBus::Events::InternalHandleMouseManipulatorInteraction
|
||||
: &InteractionBus::Events::InternalHandleMouseViewportInteraction;
|
||||
|
||||
const auto mouseInteractionEvent = [mouseInteraction, event = eventType.value(), wheelDelta] {
|
||||
switch (event)
|
||||
{
|
||||
case MouseEvent::Up:
|
||||
case MouseEvent::Down:
|
||||
case MouseEvent::Move:
|
||||
case MouseEvent::DoubleClick:
|
||||
return MouseInteractionEvent(AZStd::move(mouseInteraction), event);
|
||||
case MouseEvent::Wheel:
|
||||
return MouseInteractionEvent(AZStd::move(mouseInteraction), wheelDelta);
|
||||
}
|
||||
|
||||
AZ_Assert(false, "Unhandled MouseEvent");
|
||||
return MouseInteractionEvent(MouseInteraction{}, MouseEvent::Up);
|
||||
}();
|
||||
|
||||
InteractionBus::EventResult(
|
||||
interactionHandled, AzToolsFramework::GetEntityContextId(), targetInteractionEvent, mouseInteractionEvent);
|
||||
}
|
||||
mouseInteraction.m_interactionId.m_viewportId = GetViewportId();
|
||||
|
||||
// Depending on priority, we dispatch to either the manipulator or viewport interaction event
|
||||
const auto& targetInteractionEvent =
|
||||
event.m_priority == ManipulatorPriority
|
||||
? &InteractionBus::Events::InternalHandleMouseManipulatorInteraction
|
||||
: &InteractionBus::Events::InternalHandleMouseViewportInteraction;
|
||||
|
||||
InteractionBus::EventResult(
|
||||
interactionHandled,
|
||||
AzToolsFramework::GetEntityContextId(),
|
||||
targetInteractionEvent,
|
||||
MouseInteractionEvent(AZStd::move(mouseInteraction), eventType.value()));
|
||||
return interactionHandled;
|
||||
}
|
||||
|
||||
return interactionHandled;
|
||||
}
|
||||
|
||||
void ViewportManipulatorControllerInstance::ResetInputChannels()
|
||||
{
|
||||
m_pendingDoubleClicks.clear();
|
||||
m_state = AzToolsFramework::ViewportInteraction::MouseInteraction();
|
||||
}
|
||||
|
||||
void ViewportManipulatorControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
|
||||
{
|
||||
m_curTime = event.m_time;
|
||||
}
|
||||
|
||||
bool ViewportManipulatorControllerInstance::IsDoubleClick(AzToolsFramework::ViewportInteraction::MouseButton button) const
|
||||
{
|
||||
auto clickIt = m_pendingDoubleClicks.find(button);
|
||||
if (clickIt == m_pendingDoubleClicks.end())
|
||||
void ViewportManipulatorControllerInstance::ResetInputChannels()
|
||||
{
|
||||
return false;
|
||||
m_pendingDoubleClicks.clear();
|
||||
m_mouseInteraction = AzToolsFramework::ViewportInteraction::MouseInteraction();
|
||||
}
|
||||
const double doubleClickThresholdMilliseconds = qApp->doubleClickInterval();
|
||||
return (m_curTime.GetMilliseconds() - clickIt->second.GetMilliseconds()) < doubleClickThresholdMilliseconds;
|
||||
}
|
||||
|
||||
void ViewportManipulatorControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
|
||||
{
|
||||
m_curTime = event.m_time;
|
||||
}
|
||||
|
||||
bool ViewportManipulatorControllerInstance::IsDoubleClick(AzToolsFramework::ViewportInteraction::MouseButton button) const
|
||||
{
|
||||
auto clickIt = m_pendingDoubleClicks.find(button);
|
||||
if (clickIt == m_pendingDoubleClicks.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const double doubleClickThresholdMilliseconds = qApp->doubleClickInterval();
|
||||
return (m_curTime.GetMilliseconds() - clickIt->second.GetMilliseconds()) < doubleClickThresholdMilliseconds;
|
||||
}
|
||||
} //namespace SandboxEditor
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace SandboxEditor
|
||||
static bool IsMouseMove(const AzFramework::InputChannel& inputChannel);
|
||||
static AzToolsFramework::ViewportInteraction::KeyboardModifier GetKeyboardModifier(const AzFramework::InputChannel& inputChannel);
|
||||
|
||||
AzToolsFramework::ViewportInteraction::MouseInteraction m_state;
|
||||
AzToolsFramework::ViewportInteraction::MouseInteraction m_mouseInteraction;
|
||||
AZStd::unordered_map<AzToolsFramework::ViewportInteraction::MouseButton, AZ::ScriptTimePoint> m_pendingDoubleClicks;
|
||||
AZ::ScriptTimePoint m_curTime;
|
||||
};
|
||||
|
||||
@@ -280,8 +280,6 @@ set(FILES
|
||||
Include/IAnimationCompressionManager.h
|
||||
Include/IAssetItem.h
|
||||
Include/IAssetItemDatabase.h
|
||||
Include/IBackgroundScheduleManager.h
|
||||
Include/IBackgroundTaskManager.h
|
||||
Include/ICommandManager.h
|
||||
Include/IConsoleConnectivity.h
|
||||
Include/IDataBaseItem.h
|
||||
@@ -343,10 +341,6 @@ set(FILES
|
||||
AssetEditor/AssetEditorWindow.cpp
|
||||
AssetEditor/AssetEditorWindow.h
|
||||
AssetEditor/AssetEditorWindow.ui
|
||||
BackgroundTaskManager.cpp
|
||||
BackgroundScheduleManager.cpp
|
||||
BackgroundTaskManager.h
|
||||
BackgroundScheduleManager.h
|
||||
Commands/CommandManager.cpp
|
||||
Commands/CommandManager.h
|
||||
Controls/BitmapToolTip.cpp
|
||||
@@ -357,8 +351,6 @@ set(FILES
|
||||
Controls/ConsoleSCB.h
|
||||
Controls/ConsoleSCB.ui
|
||||
Controls/ConsoleSCB.qrc
|
||||
Controls/CurveEditorCtrl.cpp
|
||||
Controls/CurveEditorCtrl.h
|
||||
Controls/FolderTreeCtrl.cpp
|
||||
Controls/FolderTreeCtrl.h
|
||||
Controls/HotTrackingTreeCtrl.cpp
|
||||
@@ -575,11 +567,6 @@ set(FILES
|
||||
QtUI/WaitCursor.cpp
|
||||
RenderHelpers/AxisHelper.cpp
|
||||
RenderHelpers/AxisHelper.h
|
||||
Serialization.h
|
||||
Serialization/VariableOArchive.cpp
|
||||
Serialization/VariableOArchive.h
|
||||
Serialization/VariableIArchive.cpp
|
||||
Serialization/VariableIArchive.h
|
||||
CustomizeKeyboardDialog.h
|
||||
CustomizeKeyboardDialog.cpp
|
||||
CustomizeKeyboardDialog.ui
|
||||
@@ -738,8 +725,6 @@ set(FILES
|
||||
TrackView/TrackViewEventNode.h
|
||||
ConfigGroup.cpp
|
||||
ConfigGroup.h
|
||||
SettingsBlock.cpp
|
||||
SettingsBlock.h
|
||||
Util/AffineParts.h
|
||||
Util/AutoLogTime.cpp
|
||||
Util/AutoLogTime.h
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <LyViewPaneNames.h>
|
||||
#include "IResourceSelectorHost.h"
|
||||
#include "CryExtension/ICryFactoryRegistry.h"
|
||||
|
||||
#include "UI/QComponentEntityEditorMainWindow.h"
|
||||
#include "UI/QComponentEntityEditorOutlinerWindow.h"
|
||||
|
||||
@@ -160,7 +160,6 @@ void SandboxIntegrationManager::Setup()
|
||||
AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect();
|
||||
|
||||
AzFramework::DisplayContextRequestBus::Handler::BusConnect();
|
||||
SetupFileExtensionMap();
|
||||
|
||||
MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_FILE_SAVE_SLICE_TO_ROOT, [this]() {
|
||||
SaveSlice(false);
|
||||
@@ -1926,30 +1925,6 @@ void SandboxIntegrationManager::MakeSliceFromEntities(const AzToolsFramework::En
|
||||
AzToolsFramework::SliceUtilities::MakeNewSlice(entitiesAndDescendants, path, inheritSlices, setAsDynamic);
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::SetupFileExtensionMap()
|
||||
{
|
||||
// There's no central registry for geometry file types.
|
||||
const char* geometryFileExtensions[] =
|
||||
{
|
||||
CRY_GEOMETRY_FILE_EXT, // .cgf
|
||||
CRY_SKEL_FILE_EXT, // .chr
|
||||
CRY_CHARACTER_DEFINITION_FILE_EXT, // .cdf
|
||||
};
|
||||
|
||||
// Cry geometry file extensions.
|
||||
for (const char* extension : geometryFileExtensions)
|
||||
{
|
||||
m_extensionToFileType[AZ::Crc32(extension)] = IFileUtil::EFILE_TYPE_GEOMETRY;
|
||||
}
|
||||
|
||||
// Cry image file extensions.
|
||||
for (size_t i = 0; i < IResourceCompilerHelper::GetNumSourceImageFormats(); ++i)
|
||||
{
|
||||
const char* extension = IResourceCompilerHelper::GetSourceImageFormat(i, false);
|
||||
m_extensionToFileType[AZ::Crc32(extension)] = IFileUtil::EFILE_TYPE_TEXTURE;
|
||||
}
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::RegisterViewPane(const char* name, const char* category, const AzToolsFramework::ViewPaneOptions& viewOptions, const WidgetCreationFunc& widgetCreationFunc)
|
||||
{
|
||||
QtViewPaneManager::instance()->RegisterPane(name, category, widgetCreationFunc, viewOptions);
|
||||
|
||||
@@ -319,12 +319,10 @@ private:
|
||||
void OnLayerComponentDeactivated(AZ::EntityId entityId) override;
|
||||
|
||||
private:
|
||||
void SetupFileExtensionMap();
|
||||
// Right click context menu when a layer is included in the selection.
|
||||
void SetupLayerContextMenu(QMenu* menu);
|
||||
void SetupSliceContextMenu(QMenu* menu);
|
||||
void SetupSliceContextMenu_Modify(QMenu* menu, const AzToolsFramework::EntityIdList& selectedEntities, const AZ::u32 numEntitiesInSlices);
|
||||
void SetupScriptCanvasContextMenu(QMenu* menu);
|
||||
void SaveSlice(const bool& QuickPushToFirstLevel);
|
||||
void GetEntitiesInSlices(const AzToolsFramework::EntityIdList& selectedEntities, AZ::u32& entitiesInSlices, AZStd::vector<AZ::SliceComponent::SliceInstanceAddress>& sliceInstances);
|
||||
|
||||
@@ -348,9 +346,6 @@ private:
|
||||
};
|
||||
|
||||
private:
|
||||
typedef AZStd::unordered_map<AZ::u32, IFileUtil::ECustomFileType> ExtensionMap;
|
||||
ExtensionMap m_extensionToFileType;
|
||||
|
||||
AZ::Vector2 m_contextMenuViewPoint;
|
||||
AZ::Vector3 m_sliceWorldPos;
|
||||
|
||||
|
||||
@@ -1,357 +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 "EditorCommon_precompiled.h"
|
||||
#include "BatchFileDialog.h"
|
||||
#include "QPropertyTree/QPropertyDialog.h"
|
||||
#include "Serialization/StringList.h"
|
||||
#include "Serialization/STL.h"
|
||||
#include "Serialization/IArchive.h"
|
||||
#include "Serialization/STLImpl.h"
|
||||
#include "IEditor.h"
|
||||
#include "Pak/CryPakUtils.h"
|
||||
#include <vector>
|
||||
#include <AzFramework/Archive/IArchive.h>
|
||||
#include <StringUtils.h>
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <Util/PathUtil.h>
|
||||
#include <QDirIterator>
|
||||
|
||||
struct SBatchFileItem
|
||||
{
|
||||
bool selected;
|
||||
string path;
|
||||
bool checkable = false;
|
||||
|
||||
bool operator<(const SBatchFileItem& rhs) const { return path < rhs.path; }
|
||||
|
||||
void Serialize(Serialization::IArchive& ar)
|
||||
{
|
||||
// -------------------------------------------------------------------
|
||||
// Note: The property tree label modifiers used below indicate...
|
||||
// ! - Readonly, you can't modify the path
|
||||
// ^ - Raise location to the parent (the index indicator)
|
||||
// < - Take up the rest of the space
|
||||
// -------------------------------------------------------------------
|
||||
if (!checkable)
|
||||
{
|
||||
ar(selected, "selected", "^");
|
||||
}
|
||||
|
||||
auto gamePath = PathUtil::MakeGamePath(path);
|
||||
ar(gamePath, "path", "!^<");
|
||||
}
|
||||
};
|
||||
typedef std::vector<SBatchFileItem> SBatchFileItems;
|
||||
|
||||
struct CBatchFileDialog::SContent
|
||||
{
|
||||
SBatchFileItems items;
|
||||
string listLabel;
|
||||
|
||||
SContent(const char* itemsLabelText, bool readonlyList)
|
||||
{
|
||||
// Respect the readonly settings
|
||||
if (readonlyList)
|
||||
{
|
||||
listLabel += "!";
|
||||
}
|
||||
|
||||
// Label Size (5px per character)
|
||||
auto labelSize = static_cast<int>(strlen(itemsLabelText)) * 5;
|
||||
{
|
||||
// Format is: >#>+ where the >#> indicates the label size, and the + indicates end of all row formatting
|
||||
char buffer[16];
|
||||
sprintf_s(buffer, sizeof(buffer), ">%i>+", labelSize);
|
||||
listLabel += buffer;
|
||||
}
|
||||
|
||||
// Add the actual label text (the text that is seen)
|
||||
listLabel += itemsLabelText;
|
||||
}
|
||||
|
||||
void Serialize(Serialization::IArchive& ar)
|
||||
{
|
||||
ar(items, "items", listLabel.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
static bool ReadFile(std::vector<char>* buffer, const char* path)
|
||||
{
|
||||
FILE* f = nullptr;
|
||||
azfopen(&f, path, "rb");
|
||||
if (!f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = (size_t)ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
buffer->resize(len);
|
||||
bool result = true;
|
||||
if (len)
|
||||
{
|
||||
result = fread(&(*buffer)[0], 1, len, f) == len;
|
||||
}
|
||||
fclose(f);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void SplitLines(std::vector<string>* lines, const char* start, const char* end)
|
||||
{
|
||||
const char* p = start;
|
||||
const char* lineStart = start;
|
||||
while (true)
|
||||
{
|
||||
if (p == end || *p == '\r' || *p == '\n')
|
||||
{
|
||||
if (p != lineStart)
|
||||
{
|
||||
string line(lineStart, p);
|
||||
bool hasPrintableChars = false;
|
||||
for (size_t i = 0; i < line.size(); ++i)
|
||||
{
|
||||
if (!isspace(line[i]))
|
||||
{
|
||||
hasPrintableChars = true;
|
||||
}
|
||||
}
|
||||
if (hasPrintableChars)
|
||||
{
|
||||
lines->push_back(line);
|
||||
}
|
||||
}
|
||||
lineStart = p + 1;
|
||||
if (p == end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
static string NormalizePath(const char* path)
|
||||
{
|
||||
string result = path;
|
||||
result.replace('\\', '/');
|
||||
result.MakeLower();
|
||||
|
||||
// strip .phys extensions in case list of .cdf is provided
|
||||
string::size_type dotPos = result.rfind('.');
|
||||
if (dotPos != string::npos)
|
||||
{
|
||||
if (_stricmp(result.c_str() + dotPos, ".phys"))
|
||||
{
|
||||
result.erase(dotPos, 5);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool IsEquivalentPath(const char* pathA, const char* pathB)
|
||||
{
|
||||
string normalizedA = NormalizePath(pathA);
|
||||
string normalizedB = NormalizePath(pathB);
|
||||
return normalizedA == normalizedB;
|
||||
}
|
||||
|
||||
void CBatchFileDialog::OnLoadList()
|
||||
{
|
||||
QString existingFile = QFileDialog::getOpenFileName(m_dialog, "Load file list...", QString(), QString("Text Files (*.txt)"));
|
||||
if (existingFile.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string path = existingFile.toLocal8Bit().data();
|
||||
std::vector<char> content;
|
||||
ReadFile(&content, path.c_str());
|
||||
|
||||
std::vector<string> lines;
|
||||
SplitLines(&lines, &content[0], &content[0] + content.size());
|
||||
|
||||
for (size_t i = 0; i < m_content->items.size(); ++i)
|
||||
{
|
||||
m_content->items[i].selected = false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lines.size(); ++i)
|
||||
{
|
||||
const char* line = lines[i].c_str();
|
||||
for (size_t j = 0; j < m_content->items.size(); ++j)
|
||||
{
|
||||
const char* itemPath = m_content->items[j].path.c_str();
|
||||
if (IsEquivalentPath(line, itemPath))
|
||||
{
|
||||
m_content->items[j].selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_dialog->revert();
|
||||
}
|
||||
|
||||
void CBatchFileDialog::OnSelectAll()
|
||||
{
|
||||
for (size_t i = 0; i < m_content->items.size(); ++i)
|
||||
{
|
||||
m_content->items[i].selected = true;
|
||||
}
|
||||
|
||||
m_dialog->revert();
|
||||
}
|
||||
|
||||
void CBatchFileDialog::OnSelectNone()
|
||||
{
|
||||
for (size_t i = 0; i < m_content->items.size(); ++i)
|
||||
{
|
||||
m_content->items[i].selected = false;
|
||||
}
|
||||
|
||||
m_dialog->revert();
|
||||
}
|
||||
|
||||
bool EDITOR_COMMON_API ShowBatchFileDialog(Serialization::StringList* result, const SBatchFileSettings& settings, QWidget* parent)
|
||||
{
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
|
||||
CBatchFileDialog::SContent content(settings.listLabel, settings.readonlyList);
|
||||
if (settings.scanExtension[0] != '\0')
|
||||
{
|
||||
if (settings.useCryPak)
|
||||
{
|
||||
AZStd::vector<AZStd::string> files;
|
||||
|
||||
string mask = "*.";
|
||||
mask += settings.scanExtension;
|
||||
SDirectoryEnumeratorHelper helper;
|
||||
helper.ScanDirectoryRecursive(gEnv->pCryPak, Path::GetEditingGameDataFolder().c_str(), "", mask.c_str(), files);
|
||||
|
||||
for (int k = 0; k < files.size(); ++k)
|
||||
{
|
||||
SBatchFileItem item;
|
||||
item.checkable = settings.filesAreCheckable;
|
||||
item.selected = true;
|
||||
item.path = { files[k].data(), files[k].size() };
|
||||
content.items.push_back(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string gameFolder = Path::GetEditingGameDataFolder().c_str();
|
||||
string gamePrefix = GetIEditor()->GetPrimaryCDFolder().toUtf8().data();
|
||||
if (!gamePrefix.empty() && gamePrefix[gamePrefix.size() - 1] != '\\')
|
||||
{
|
||||
gamePrefix += "\\";
|
||||
}
|
||||
gamePrefix += gameFolder;
|
||||
if (!gamePrefix.empty() && gamePrefix[gamePrefix.size() - 1] != '\\')
|
||||
{
|
||||
gamePrefix += "\\";
|
||||
}
|
||||
gamePrefix.replace('/', '\\');
|
||||
|
||||
QString mask = "*." + QString(settings.scanExtension);
|
||||
QDirIterator dirIterator(QString(gamePrefix), QStringList() << mask, QDir::Files, QDirIterator::Subdirectories);
|
||||
while (dirIterator.hasNext())
|
||||
{
|
||||
SBatchFileItem item;
|
||||
item.selected = true;
|
||||
QByteArray array = dirIterator.next().toUtf8();
|
||||
item.path = string(array);
|
||||
item.path.replace('/', '\\');
|
||||
content.items.push_back(item);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
content.items.reserve(content.items.size() + settings.explicitFileList.size());
|
||||
for (size_t i = 0; i < settings.explicitFileList.size(); ++i)
|
||||
{
|
||||
SBatchFileItem item;
|
||||
item.path = settings.explicitFileList[i].c_str();
|
||||
item.selected = true;
|
||||
content.items.push_back(item);
|
||||
}
|
||||
|
||||
|
||||
std::sort(content.items.begin(), content.items.end());
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
QPropertyDialog dialog(parent);
|
||||
dialog.setSerializer(Serialization::SStruct(content));
|
||||
dialog.setWindowTitle(settings.title);
|
||||
dialog.setWindowStateFilename(settings.stateFilename);
|
||||
dialog.setSizeHint(QSize(settings.defaultWidth, settings.defaultHeight));
|
||||
dialog.setMinimumSize(QSize(540, 250));
|
||||
|
||||
CBatchFileDialog handler;
|
||||
handler.m_dialog = &dialog;
|
||||
handler.m_content = &content;
|
||||
|
||||
QBoxLayout* topRow = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
QLabel* label = new QLabel(settings.descriptionText);
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
label->setFont(font);
|
||||
topRow->addWidget(label, 1);
|
||||
{
|
||||
if (settings.allowListLoading && !settings.readonlyList)
|
||||
{
|
||||
QPushButton* loadListButton = new QPushButton("Load List...");
|
||||
QObject::connect(loadListButton, SIGNAL(pressed()), &handler, SLOT(OnLoadList()));
|
||||
topRow->addWidget(loadListButton);
|
||||
}
|
||||
QPushButton* selectAllButton = new QPushButton("Select All");
|
||||
QObject::connect(selectAllButton, SIGNAL(pressed()), &handler, SLOT(OnSelectAll()));
|
||||
topRow->addWidget(selectAllButton);
|
||||
QPushButton* selectNoneButton = new QPushButton("Select None");
|
||||
QObject::connect(selectNoneButton, SIGNAL(pressed()), &handler, SLOT(OnSelectNone()));
|
||||
topRow->addWidget(selectNoneButton);
|
||||
}
|
||||
dialog.layout()->insertLayout(0, topRow);
|
||||
|
||||
if (parent)
|
||||
{
|
||||
QPoint center = parent->rect().center();
|
||||
dialog.window()->move(max(0, center.x() - dialog.width() / 2),
|
||||
max(0, center.y() - dialog.height() / 2));
|
||||
}
|
||||
|
||||
std::vector<string> failedFiles;
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
result->clear();
|
||||
for (size_t i = 0; i < content.items.size(); ++i)
|
||||
{
|
||||
if (content.items[i].selected)
|
||||
{
|
||||
const char* path = content.items[i].path.c_str();
|
||||
result->push_back(path);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <moc_BatchFileDialog.cpp>
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_BATCHFILEDIALOG_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_BATCHFILEDIALOG_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "EditorCommonAPI.h"
|
||||
#include <QObject>
|
||||
#include <Serialization/StringList.h>
|
||||
#endif
|
||||
|
||||
// Private class, should not be used directly
|
||||
class QWidget;
|
||||
class QPropertyDialog;
|
||||
class CBatchFileDialog
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
void OnSelectAll();
|
||||
void OnSelectNone();
|
||||
void OnLoadList();
|
||||
|
||||
public:
|
||||
QPropertyDialog* m_dialog;
|
||||
struct SContent;
|
||||
SContent* m_content;
|
||||
};
|
||||
// ^^^
|
||||
|
||||
struct SBatchFileSettings
|
||||
{
|
||||
const char* scanExtension;
|
||||
const char* scanFolder;
|
||||
const char* title;
|
||||
const char* descriptionText;
|
||||
const char* listLabel;
|
||||
const char* stateFilename;
|
||||
bool useCryPak;
|
||||
bool allowListLoading;
|
||||
bool readonlyList;
|
||||
bool filesAreCheckable;
|
||||
Serialization::StringList explicitFileList;
|
||||
int defaultWidth;
|
||||
int defaultHeight;
|
||||
|
||||
SBatchFileSettings()
|
||||
: useCryPak(true)
|
||||
, readonlyList(true)
|
||||
, filesAreCheckable(false)
|
||||
, allowListLoading(true)
|
||||
, descriptionText("Batch Selected Files")
|
||||
, listLabel("Files")
|
||||
, stateFilename("batchFileDialog.state")
|
||||
, title("Batch Files")
|
||||
, scanFolder("")
|
||||
, scanExtension("*")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
bool EDITOR_COMMON_API ShowBatchFileDialog(Serialization::StringList* filenames, const SBatchFileSettings& settings, QWidget* parent);
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_BATCHFILEDIALOG_H
|
||||
@@ -13,8 +13,6 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
|
||||
|
||||
# Header only target to prevent linkage against editor libraries when it is not needed. Eventually the targets that depend
|
||||
# on editor headers should cleanup dependencies and interact with the editor through buses or other mechanisms
|
||||
ly_add_target(
|
||||
@@ -34,7 +32,6 @@ ly_add_target(
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
editorcommon_files.cmake
|
||||
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,233 +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 "CurveEditorContent.h"
|
||||
#include <QWidget>
|
||||
#include <Range.h>
|
||||
|
||||
class QMenu;
|
||||
class CCurveEditorControl;
|
||||
class CCurveEditorTangentControl;
|
||||
struct ISplineInterpolator;
|
||||
|
||||
enum ETangent
|
||||
{
|
||||
ETangent_In,
|
||||
ETangent_Out
|
||||
};
|
||||
|
||||
enum ECurveEditorCurveType
|
||||
{
|
||||
eCECT_Bezier,
|
||||
// 2D Bezier curves are used for better curve control, the editor
|
||||
// will enforce that the resulting curve is always 1D.
|
||||
eCECT_2DBezier,
|
||||
};
|
||||
|
||||
namespace CurveEditorHelpers
|
||||
{
|
||||
// Picks a nice color value for a curve. Wraps around after 4.
|
||||
EDITOR_COMMON_API ColorB GetCurveColor(const uint n);
|
||||
EDITOR_COMMON_API QColor LerpColor(const QColor& a, const QColor& b, float k);
|
||||
}
|
||||
|
||||
class EDITOR_COMMON_API CCurveEditor
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum EOptOutFlags
|
||||
{
|
||||
EOptOutFree = 1 << 0,
|
||||
EOptOutFlat = 1 << 1,
|
||||
EOptOutLinear = 1 << 2,
|
||||
EOptOutStep = 1 << 3,
|
||||
EOptOutBezier = 1 << 4,
|
||||
EOptOutSelectionKey = 1 << 5,
|
||||
EOptOutSelectionInOutTangent = 1 << 6,
|
||||
//steven@conffx added some optout options to allow easier graphical customization
|
||||
EOptOutKeyIcon = 1 << 7,
|
||||
EOptOutRuler = 1 << 8,
|
||||
EOptOutTimeSlider = 1 << 9,
|
||||
EOptOutBackground = 1 << 10,
|
||||
EOptOutCustomPenColor = 1 << 11,
|
||||
EOptOutControls = 1 << 12,
|
||||
eOptOutDashedPath = 1 << 13,
|
||||
EOptOutDefaultTooltip = 1 << 14,
|
||||
EOptOutFitCurvesContextMenuOptions = 1 << 15,
|
||||
EOptOutZoomingAndPanning = 1 << 16
|
||||
};
|
||||
|
||||
CCurveEditor(QWidget* parent);
|
||||
~CCurveEditor();
|
||||
|
||||
void SetContent(SCurveEditorContent* pContent);
|
||||
SCurveEditorContent* Content() const { return m_pContent; }
|
||||
|
||||
void SetTime(const float time);
|
||||
|
||||
// The background in the time and value range will be drawn a bit brighter to indicate where keys
|
||||
// should be placed. The curve editor does not enforce that the curves actually stay in those ranges.
|
||||
void SetTimeRange(const float start, const float end);
|
||||
void SetValueRange(const float min, const float max);
|
||||
|
||||
// Points cannot be added outside of the time range and the view will not move horizontally...zooming will only be done on the vertical axis
|
||||
void EnforceTimeRange(const float start, const float end);
|
||||
bool IsTimeRangeEnforced() const;
|
||||
|
||||
void ZoomToTimeRange(const float start, const float end);
|
||||
void ZoomToValueRange(const float min, const float max);
|
||||
|
||||
void SetCurveType(ECurveEditorCurveType curveType);
|
||||
void SetWeighted(bool bWeighted);
|
||||
void SetHandlesVisible(bool bVisible);
|
||||
void SetRulerVisible(bool bVisible);
|
||||
void SetTimeSliderVisible(bool bVisible);
|
||||
|
||||
Vec2 TransformToScreenCoordinates(Vec2 graphPoint);
|
||||
Vec2 TransformFromScreenCoordinates(Vec2 screenPoint);
|
||||
|
||||
// Removes parts of the popup-menu, use CCurveEditor::EMenuOptOutFlags
|
||||
void SetOptOutFlags(int flags);
|
||||
|
||||
// Tools added to tool bar depend on options above
|
||||
void PopulateControlContextMenu(QMenu* pToolBar);
|
||||
|
||||
virtual void paintEvent(QPaintEvent* pEvent) override;
|
||||
void mousePressEvent(QMouseEvent* pEvent) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent* pEvent) override;
|
||||
void mouseMoveEvent(QMouseEvent* pEvent) override;
|
||||
void mouseReleaseEvent(QMouseEvent* pEvent) override;
|
||||
void focusOutEvent(QFocusEvent* pEvent) override;
|
||||
void wheelEvent(QWheelEvent* pEvent) override;
|
||||
void keyPressEvent(QKeyEvent* pEvent) override;
|
||||
|
||||
QString static TangentTypeToString(SCurveEditorKey::ETangentType type);
|
||||
|
||||
void updateCurveKeyShapeColor(); // loop through curve keys and set shape color for them
|
||||
void SetIconShapeColor(unsigned int key, QColor color);
|
||||
void SetIconFillColor(unsigned int key, QColor color);
|
||||
void SetIconImage(QString str);
|
||||
void SetIconShapeMask(QColor color);
|
||||
void SetIconFillMask(QColor color);
|
||||
void SetIconToolTip(unsigned int key, QString str);
|
||||
void SetIconSize(unsigned int key, unsigned int size);
|
||||
|
||||
void setPenColor(QColor color);
|
||||
void ContentChanged();
|
||||
void SortKeys(SCurveEditorCurve& curve);
|
||||
|
||||
std::pair<SCurveEditorCurve*, Vec2> HitDetectCurve(const QPoint point);
|
||||
CCurveEditorControl* HitDetectKey(const QPoint point);
|
||||
CCurveEditorTangentControl* HitDetectTangent(const QPoint point);
|
||||
|
||||
CCurveEditorControl* GetSelectedCurveKey();
|
||||
QRectF GetBackgroundRect();
|
||||
|
||||
void SelectKey(CCurveEditorControl* pKeyToSelect, bool addToExistingSelection);
|
||||
void SelectTangent(CCurveEditorTangentControl* pTangentToSelect);
|
||||
void SelectInRect(const QRect& rect);
|
||||
|
||||
signals:
|
||||
void SignalContentChanged();
|
||||
void SignalScrub();
|
||||
void SignalKeyMoved();
|
||||
void SignalKeyMoveStarted();
|
||||
void SignalKeySelected(CCurveEditorControl* selectedKey);
|
||||
|
||||
public slots:
|
||||
void OnDeleteSelectedKeys();
|
||||
void OnSetSelectedKeysTangentStandard();
|
||||
void OnSetSelectedKeysTangentSmooth();
|
||||
void OnSetSelectedKeysTangentFree();
|
||||
void OnSetSelectedKeysTangentBezier();
|
||||
void OnSetSelectedKeysTangentFlat();
|
||||
void OnSetSelectedKeysTangentLinear();
|
||||
|
||||
void OnSetSelectedKeysInTangentFree();
|
||||
void OnSetSelectedKeysInTangentFlat();
|
||||
void OnSetSelectedKeysInTangentLinear();
|
||||
void OnSetSelectedKeysInTangentStep();
|
||||
void OnSetSelectedKeysInTangentBezier();
|
||||
|
||||
void OnSetSelectedKeysOutTangentFree();
|
||||
void OnSetSelectedKeysOutTangentFlat();
|
||||
void OnSetSelectedKeysOutTangentLinear();
|
||||
void OnSetSelectedKeysOutTangentStep();
|
||||
void OnSetSelectedKeysOutTangentBezier();
|
||||
|
||||
void OnFitCurvesHorizontally();
|
||||
void OnFitCurvesVertically();
|
||||
|
||||
protected:
|
||||
struct SMouseHandler
|
||||
{
|
||||
virtual ~SMouseHandler() = default;
|
||||
virtual void mousePressEvent([[maybe_unused]] QMouseEvent* pEvent) {}
|
||||
virtual void mouseDoubleClickEvent([[maybe_unused]] QMouseEvent* pEvent) {}
|
||||
virtual void mouseMoveEvent([[maybe_unused]] QMouseEvent* pEvent) {}
|
||||
virtual void mouseReleaseEvent([[maybe_unused]] QMouseEvent* pEvent) {}
|
||||
virtual void focusOutEvent([[maybe_unused]] QFocusEvent* pEvent) {}
|
||||
virtual void paintOver([[maybe_unused]] QPainter& painter) {}
|
||||
};
|
||||
struct SSelectionHandler;
|
||||
struct SPanHandler;
|
||||
struct SZoomHandler;
|
||||
struct SMoveKeyHandler;
|
||||
struct SRotateTangentHandler;
|
||||
struct SScrubHandler;
|
||||
QColor m_penColor;
|
||||
|
||||
void LeftButtonMousePressEvent(QMouseEvent* pEvent);
|
||||
void MiddleButtonMousePressEvent(QMouseEvent* pEvent);
|
||||
void RightButtonMousePressEvent(QMouseEvent* pEvent);
|
||||
|
||||
void DeleteMarkedKeys();
|
||||
|
||||
void SetTimeRange(const float start, const float end, bool enforce);
|
||||
|
||||
Vec2 ClosestPointOnCurve(const Vec2 point, const SCurveEditorCurve& curve, const ECurveEditorCurveType curveType);
|
||||
|
||||
bool AddPointToCurve(Vec2 point, SCurveEditorCurve* pCurve);
|
||||
|
||||
QRect GetCurveArea();
|
||||
|
||||
void SetSelectedKeysTangentType(const ETangent tangent, const SCurveEditorKey::ETangentType type);
|
||||
void SmoothSelectedKeys();
|
||||
|
||||
void UpdateTangents();
|
||||
SCurveEditorContent* m_pContent;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
std::unique_ptr<SMouseHandler> m_pMouseHandler;
|
||||
|
||||
ECurveEditorCurveType m_curveType;
|
||||
bool m_bWeighted;
|
||||
bool m_bHandlesVisible;
|
||||
bool m_bRulerVisible;
|
||||
bool m_bTimeSliderVisible;
|
||||
|
||||
float m_time;
|
||||
Vec2 m_zoom;
|
||||
Vec2 m_translation;
|
||||
Range m_timeRange;
|
||||
bool m_timeRangeEnforced;
|
||||
Range m_valueRange;
|
||||
|
||||
int m_optOutFlags;
|
||||
public:
|
||||
QList<CCurveEditorControl*> m_pControlKeys;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
@@ -1,155 +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 <Cry_Math.h>
|
||||
#include <Cry_Color.h>
|
||||
|
||||
#include "Serialization/Strings.h"
|
||||
#include "Serialization/SmartPtr.h"
|
||||
#include "Serialization/Color.h"
|
||||
#include "Serialization.h"
|
||||
|
||||
struct ISplineInterpolator;
|
||||
|
||||
struct SCurveEditorKey
|
||||
{
|
||||
SCurveEditorKey()
|
||||
: m_bSelected(false)
|
||||
, m_bModified(false)
|
||||
, m_bAdded(false)
|
||||
, m_bDeleted(false)
|
||||
, m_time(0.0f)
|
||||
, m_value(0.0f)
|
||||
, m_inTangentType(eTangentType_Standard)
|
||||
, m_outTangentType(eTangentType_Standard)
|
||||
, m_inTangent(ZERO)
|
||||
, m_outTangent(ZERO)
|
||||
{
|
||||
}
|
||||
|
||||
enum ETangentType
|
||||
{
|
||||
eTangentType_Standard, // Tangent freely rotates but will stay in sync with its pair if its pair is also standard
|
||||
eTangentType_Free, // Tangent is completely free moving (does not sync with its pair)
|
||||
eTangentType_Step, // Step immediately to value of next control point in tangent direction
|
||||
eTangentType_Linear, // Tangent always points to next control point
|
||||
eTangentType_Bezier, // Tangent is free moving and can be justified by user
|
||||
eTangentType_Smooth, // Tangent is smoothed automatically based on direction/distance to neighboring controls
|
||||
eTangentType_Flat, // Tangent is flattened (y = 0) - will still sync with its pair if both are flat
|
||||
};
|
||||
|
||||
void Serialize(IArchive& ar)
|
||||
{
|
||||
ar(m_inTangentType, "inTangentType");
|
||||
ar(m_outTangentType, "outTangentType");
|
||||
ar(m_time, "time");
|
||||
ar(m_value, "value");
|
||||
ar(m_inTangent, "inTangent");
|
||||
ar(m_outTangent, "outTangent");
|
||||
}
|
||||
|
||||
bool m_bSelected : 1;
|
||||
bool m_bModified : 1;
|
||||
bool m_bAdded : 1;
|
||||
bool m_bDeleted : 1;
|
||||
|
||||
ETangentType m_inTangentType : 4;
|
||||
ETangentType m_outTangentType : 4;
|
||||
|
||||
float m_time;
|
||||
float m_value;
|
||||
|
||||
// For 1D Bezier only the Y component is used
|
||||
Vec2 m_inTangent;
|
||||
Vec2 m_outTangent;
|
||||
|
||||
|
||||
bool operator==(const SCurveEditorKey& rhs) const
|
||||
{
|
||||
return (m_inTangentType == rhs.m_inTangentType
|
||||
&& m_outTangentType == rhs.m_outTangentType
|
||||
&& m_time == rhs.m_time
|
||||
&& m_value == rhs.m_value
|
||||
&& m_inTangent == rhs.m_inTangent
|
||||
&& m_outTangent == rhs.m_outTangent);
|
||||
}
|
||||
|
||||
bool operator!=(const SCurveEditorKey& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct SCurveEditorCurve
|
||||
{
|
||||
SCurveEditorCurve()
|
||||
: m_bModified(false)
|
||||
, m_defaultValue(0.0f)
|
||||
, m_color(255, 255, 255)
|
||||
, m_customInterpolator(nullptr)
|
||||
{}
|
||||
|
||||
void Serialize(IArchive& ar)
|
||||
{
|
||||
ar(m_keys, "keys");
|
||||
ar(m_defaultValue, "defaultValue");
|
||||
ar(m_color, "color");
|
||||
}
|
||||
|
||||
bool m_bModified : 1;
|
||||
float m_defaultValue;
|
||||
ColorB m_color;
|
||||
|
||||
// Setting m_customInterpolator will override spline-draw code.
|
||||
// When used, its up to developer to fill and update all necessary keys.
|
||||
ISplineInterpolator* m_customInterpolator;
|
||||
|
||||
std::vector<SCurveEditorKey> m_keys;
|
||||
|
||||
bool operator==(const SCurveEditorCurve& rhs) const
|
||||
{
|
||||
if (m_defaultValue != rhs.m_defaultValue
|
||||
|| m_color != rhs.m_color
|
||||
|| m_keys.size() != rhs.m_keys.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_keys.size(); i++)
|
||||
{
|
||||
if (m_keys[i] != rhs.m_keys[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const SCurveEditorCurve& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<SCurveEditorCurve> TCurveEditorCurves;
|
||||
|
||||
struct SCurveEditorContent
|
||||
{
|
||||
void Serialize(IArchive& ar)
|
||||
{
|
||||
ar(m_curves, "curves");
|
||||
}
|
||||
|
||||
TCurveEditorCurves m_curves;
|
||||
};
|
||||
@@ -1,84 +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 <Cry_Math.h>
|
||||
#include <Cry_Color.h>
|
||||
#include <Bezier.h>
|
||||
#include <AnimTime.h>
|
||||
|
||||
#include "Serialization/Strings.h"
|
||||
#include "Serialization/SmartPtr.h"
|
||||
#include "Serialization/Color.h"
|
||||
#include "Serialization.h"
|
||||
|
||||
struct SCurveEditorKey
|
||||
{
|
||||
SCurveEditorKey()
|
||||
: m_time(0)
|
||||
, m_bSelected(false)
|
||||
, m_bModified(false)
|
||||
, m_bAdded(false)
|
||||
, m_bDeleted(false)
|
||||
{
|
||||
}
|
||||
|
||||
void Serialize(IArchive& ar)
|
||||
{
|
||||
ar(m_time);
|
||||
ar(m_controlPoint);
|
||||
}
|
||||
|
||||
SAnimTime m_time;
|
||||
SBezierControlPoint m_controlPoint;
|
||||
|
||||
bool m_bSelected : 1;
|
||||
bool m_bModified : 1;
|
||||
bool m_bAdded : 1;
|
||||
bool m_bDeleted : 1;
|
||||
};
|
||||
|
||||
struct SCurveEditorCurve
|
||||
{
|
||||
SCurveEditorCurve()
|
||||
: m_bModified(false)
|
||||
, m_defaultValue(0.0f)
|
||||
, m_color(255, 255, 255)
|
||||
{}
|
||||
|
||||
void Serialize(IArchive& ar)
|
||||
{
|
||||
ar(m_keys, "keys");
|
||||
ar(m_defaultValue, "defaultValue");
|
||||
ar(m_color, "color");
|
||||
}
|
||||
|
||||
bool m_bModified : 1;
|
||||
float m_defaultValue;
|
||||
ColorB m_color;
|
||||
|
||||
DynArray<char> userSideLoad;
|
||||
|
||||
std::vector<SCurveEditorKey> m_keys;
|
||||
};
|
||||
|
||||
typedef std::vector<SCurveEditorCurve> TCurveEditorCurves;
|
||||
|
||||
struct SCurveEditorContent
|
||||
{
|
||||
void Serialize(IArchive& ar)
|
||||
{
|
||||
ar(m_curves, "curves");
|
||||
}
|
||||
|
||||
TCurveEditorCurves m_curves;
|
||||
};
|
||||
@@ -1,20 +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 "CurveEditorContent.h"
|
||||
|
||||
SERIALIZATION_ENUM_BEGIN_NESTED(SCurveEditorKey, ETangentType, "TangentType")
|
||||
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Custom, "Custom")
|
||||
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Auto, "Smooth")
|
||||
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Zero, "Zero")
|
||||
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Step, "Step")
|
||||
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Linear, "Linear")
|
||||
SERIALIZATION_ENUM_END()
|
||||
@@ -1,352 +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 "EditorCommon_precompiled.h"
|
||||
#include "CurveEditorControl.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QBitmap>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "CurveEditor.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const int kDefaultControlVisualSize = 8;
|
||||
const int kDefaultControlClickableSize = 10;
|
||||
const int kDefaultTangentControlVisualSize = 6;
|
||||
const int kDefaultTangentControlClickableSize = 8;
|
||||
const int kDefaultTangentControlDistanceFromControl = 30;
|
||||
|
||||
void DrawPointRect(QPainter& painter, QPointF point, const QColor& color, int size)
|
||||
{
|
||||
painter.setBrush(QBrush(color));
|
||||
painter.setPen(QColor(0, 0, 0));
|
||||
float halfSize = size / 2.0f;
|
||||
QPointF extents = QPointF(halfSize, halfSize);
|
||||
painter.drawRect(QRectF(point - extents, point + extents));
|
||||
}
|
||||
}
|
||||
|
||||
CCurveEditorControl::CCurveEditorControl(CCurveEditor& curveEditor, SCurveEditorCurve& curve, SCurveEditorKey& key)
|
||||
: m_CurveEditor(curveEditor)
|
||||
, m_Curve(curve)
|
||||
, m_Key(key)
|
||||
, m_VisualSize(kDefaultControlVisualSize)
|
||||
, m_ClickableSize(kDefaultControlClickableSize)
|
||||
, m_pInTangent(new CCurveEditorTangentControl(*this, ETangent_In))
|
||||
, m_pOutTangent(new CCurveEditorTangentControl(*this, ETangent_Out))
|
||||
, m_filledPxr(kDefaultControlVisualSize, kDefaultControlVisualSize)
|
||||
, m_shapePxr(kDefaultControlVisualSize, kDefaultControlVisualSize)
|
||||
, m_icon(kDefaultControlVisualSize, kDefaultControlVisualSize)
|
||||
, m_originalPxr(kDefaultControlVisualSize, kDefaultControlVisualSize)
|
||||
, m_tip("")
|
||||
, m_iconsize(16)
|
||||
{
|
||||
}
|
||||
|
||||
CCurveEditorControl::~CCurveEditorControl()
|
||||
{
|
||||
delete m_pInTangent;
|
||||
delete m_pOutTangent;
|
||||
}
|
||||
|
||||
CCurveEditor& CCurveEditorControl::GetCurveEditor() const
|
||||
{
|
||||
return m_CurveEditor;
|
||||
}
|
||||
|
||||
SCurveEditorCurve& CCurveEditorControl::GetCurve() const
|
||||
{
|
||||
return m_Curve;
|
||||
}
|
||||
|
||||
SCurveEditorKey& CCurveEditorControl::GetKey() const
|
||||
{
|
||||
return m_Key;
|
||||
}
|
||||
|
||||
CCurveEditorTangentControl& CCurveEditorControl::GetInTangent()
|
||||
{
|
||||
return *m_pInTangent;
|
||||
}
|
||||
|
||||
CCurveEditorTangentControl& CCurveEditorControl::GetOutTangent()
|
||||
{
|
||||
return *m_pOutTangent;
|
||||
}
|
||||
|
||||
bool CCurveEditorControl::IsSelected() const
|
||||
{
|
||||
return m_Key.m_bSelected;
|
||||
}
|
||||
|
||||
void CCurveEditorControl::SetSelected(bool selected)
|
||||
{
|
||||
m_Key.m_bSelected = selected;
|
||||
m_pInTangent->SetVisible(selected);
|
||||
m_pOutTangent->SetVisible(selected);
|
||||
}
|
||||
|
||||
bool CCurveEditorControl::IsKeyMarkedForRemoval() const
|
||||
{
|
||||
return m_Key.m_bDeleted;
|
||||
}
|
||||
|
||||
void CCurveEditorControl::MarkKeyForRemoval()
|
||||
{
|
||||
m_Key.m_bDeleted = true;
|
||||
}
|
||||
|
||||
void CCurveEditorControl::Paint(QPainter& painter, const QPalette& palette, const bool& paintInOutTangents)
|
||||
{
|
||||
const QColor pointColor = m_Key.m_bSelected ? palette.color(QPalette::Highlight) : QColor(255, 255, 255, 255);
|
||||
|
||||
if (paintInOutTangents)
|
||||
{
|
||||
m_pInTangent->Paint(painter, palette);
|
||||
m_pOutTangent->Paint(painter, palette);
|
||||
}
|
||||
|
||||
DrawPointRect(painter, GetScreenPosition(), pointColor, m_VisualSize);
|
||||
}
|
||||
void CCurveEditorControl::PaintIcon(QPainter& painter, const QPalette& palette, const bool& paintInOutTangents)
|
||||
{
|
||||
if (paintInOutTangents)
|
||||
{
|
||||
m_pInTangent->Paint(painter, palette);
|
||||
m_pOutTangent->Paint(painter, palette);
|
||||
}
|
||||
|
||||
QPointF pos = GetScreenPosition();
|
||||
float halfSize = m_iconsize / 2.0f;
|
||||
QPointF extents = QPointF(halfSize, halfSize);
|
||||
painter.drawPixmap(QRectF(GetScreenPosition() - extents, GetScreenPosition() + extents), m_icon, QRectF(0, 0, m_iconsize, m_iconsize));
|
||||
}
|
||||
|
||||
bool CCurveEditorControl::IsMouseWithinControl(QPointF screenPos) const
|
||||
{
|
||||
QPointF keyPosition = GetScreenPosition();
|
||||
QPointF deltaPos = screenPos - keyPosition;
|
||||
|
||||
float halfClickSize = m_ClickableSize / 2.0f;
|
||||
|
||||
return abs(deltaPos.x()) <= halfClickSize && abs(deltaPos.y()) <= halfClickSize;
|
||||
}
|
||||
|
||||
QPointF CCurveEditorControl::GetScreenPosition() const
|
||||
{
|
||||
Vec2 screenPosition = m_CurveEditor.TransformToScreenCoordinates(Vec2(m_Key.m_time, m_Key.m_value));
|
||||
return QPointF(screenPosition.x, screenPosition.y);
|
||||
}
|
||||
|
||||
void CCurveEditorControl::BuildIcon()
|
||||
{
|
||||
m_filledPxr = QPixmap(m_originalPxr.size());
|
||||
m_shapePxr = QPixmap(m_originalPxr.size());
|
||||
m_shapePxr.fill(m_shapeColor);
|
||||
m_filledPxr.fill(m_fillColor);
|
||||
m_shapePxr.setMask(m_originalPxr.createMaskFromColor(m_shapeMask).createMaskFromColor(m_fillMask));
|
||||
m_filledPxr.setMask(m_originalPxr.createMaskFromColor(m_fillMask, Qt::MaskOutColor));
|
||||
QPainter painter(&m_shapePxr);
|
||||
painter.drawPixmap(0, 0, m_filledPxr);
|
||||
m_icon = m_shapePxr.scaled(m_iconsize, m_iconsize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
void CCurveEditorControl::SetIconFillMask(QColor color)
|
||||
{
|
||||
m_fillMask = color;
|
||||
BuildIcon();
|
||||
}
|
||||
|
||||
void CCurveEditorControl::SetIconShapeMask(QColor color)
|
||||
{
|
||||
m_shapeMask = color;
|
||||
BuildIcon();
|
||||
}
|
||||
|
||||
void CCurveEditorControl::SetIconImage(QString str)
|
||||
{
|
||||
m_originalPxr.load(str);
|
||||
BuildIcon();
|
||||
}
|
||||
|
||||
void CCurveEditorControl::SetIconFillColor(QColor color)
|
||||
{
|
||||
m_fillColor = color;
|
||||
BuildIcon();
|
||||
}
|
||||
|
||||
void CCurveEditorControl::SetIconShapeColor(QColor color)
|
||||
{
|
||||
m_shapeColor = color;
|
||||
BuildIcon();
|
||||
}
|
||||
|
||||
|
||||
CCurveEditorTangentControl::CCurveEditorTangentControl(CCurveEditorControl& control, ETangent tangentDirection)
|
||||
: m_Control(control)
|
||||
, m_TangentDirection(tangentDirection)
|
||||
, m_Visible(false)
|
||||
, m_Selected(false)
|
||||
, m_VisualSize(kDefaultTangentControlVisualSize)
|
||||
, m_ClickableSize(kDefaultTangentControlClickableSize)
|
||||
, m_DistanceFromControl(kDefaultTangentControlDistanceFromControl)
|
||||
{
|
||||
}
|
||||
|
||||
CCurveEditorTangentControl::~CCurveEditorTangentControl()
|
||||
{
|
||||
}
|
||||
|
||||
CCurveEditorControl& CCurveEditorTangentControl::GetControl()
|
||||
{
|
||||
return m_Control;
|
||||
}
|
||||
|
||||
ETangent CCurveEditorTangentControl::GetTangentDirection() const
|
||||
{
|
||||
return m_TangentDirection;
|
||||
}
|
||||
|
||||
bool CCurveEditorTangentControl::IsVisible() const
|
||||
{
|
||||
if (!m_Visible)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SCurveEditorKey::ETangentType tangentType;
|
||||
|
||||
if (m_TangentDirection == ETangent_In)
|
||||
{
|
||||
tangentType = m_Control.GetKey().m_inTangentType;
|
||||
}
|
||||
else
|
||||
{
|
||||
tangentType = m_Control.GetKey().m_outTangentType;
|
||||
}
|
||||
|
||||
if (tangentType == SCurveEditorKey::eTangentType_Step)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// first in
|
||||
if ((*m_Control.GetCurve().m_keys.begin()).m_time == m_Control.GetKey().m_time && m_TangentDirection == ETangent_In)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// last out
|
||||
if ((*(m_Control.GetCurve().m_keys.end() - 1)).m_time == m_Control.GetKey().m_time && m_TangentDirection == ETangent_Out)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCurveEditorTangentControl::SetVisible(bool visible)
|
||||
{
|
||||
m_Visible = visible;
|
||||
}
|
||||
|
||||
bool CCurveEditorTangentControl::IsSelected() const
|
||||
{
|
||||
return m_Selected;
|
||||
}
|
||||
|
||||
void CCurveEditorTangentControl::SetSelected(bool selected)
|
||||
{
|
||||
m_Selected = selected;
|
||||
}
|
||||
|
||||
void CCurveEditorTangentControl::SetVisualSize(int visualSize)
|
||||
{
|
||||
m_VisualSize = visualSize;
|
||||
}
|
||||
|
||||
void CCurveEditorTangentControl::SetClickableSize(int clickableSize)
|
||||
{
|
||||
m_ClickableSize = clickableSize;
|
||||
}
|
||||
|
||||
void CCurveEditorTangentControl::SetDistanceFromControl(int distanceFromControl)
|
||||
{
|
||||
m_DistanceFromControl = distanceFromControl;
|
||||
}
|
||||
|
||||
void CCurveEditorTangentControl::Paint(QPainter& painter, const QPalette& palette)
|
||||
{
|
||||
if (!IsVisible())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QPointF controlPosition = m_Control.GetScreenPosition();
|
||||
QPointF tangentPosition = GetScreenPosition();
|
||||
|
||||
float highlightPercent;
|
||||
if (m_Selected)
|
||||
{
|
||||
highlightPercent = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
highlightPercent = 0.5f;
|
||||
}
|
||||
const QColor tangentColor = CurveEditorHelpers::LerpColor(palette.color(QPalette::Highlight), palette.color(QPalette::Window), highlightPercent);
|
||||
const QPen tangentPen = QPen(tangentColor);
|
||||
|
||||
painter.setPen(tangentPen);
|
||||
painter.drawLine(controlPosition, tangentPosition);
|
||||
|
||||
const QColor tangentControlColor = m_Selected ? palette.color(QPalette::Highlight) : palette.color(QPalette::Dark);
|
||||
DrawPointRect(painter, tangentPosition, tangentControlColor, m_VisualSize);
|
||||
}
|
||||
|
||||
bool CCurveEditorTangentControl::IsMouseWithinControl(QPointF screenPos) const
|
||||
{
|
||||
if (!IsVisible())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QPointF keyPosition = GetScreenPosition();
|
||||
QPointF deltaPos = screenPos - keyPosition;
|
||||
|
||||
float halfClickSize = m_ClickableSize / 2.0f;
|
||||
|
||||
return abs(deltaPos.x()) <= halfClickSize && abs(deltaPos.y()) <= halfClickSize;
|
||||
}
|
||||
|
||||
QPointF CCurveEditorTangentControl::GetScreenPosition() const
|
||||
{
|
||||
QPointF controlPosition = m_Control.GetScreenPosition();
|
||||
|
||||
Vec2 tangent;
|
||||
if (m_TangentDirection == ETangent_In)
|
||||
{
|
||||
tangent = m_Control.GetKey().m_inTangent;
|
||||
}
|
||||
else
|
||||
{
|
||||
tangent = m_Control.GetKey().m_outTangent;
|
||||
}
|
||||
|
||||
Vec2 tangentScreenPosition = m_Control.GetCurveEditor().TransformToScreenCoordinates(Vec2(m_Control.GetKey().m_time + tangent.x, m_Control.GetKey().m_value + tangent.y));
|
||||
Vec2 transformedTangentDelta = (tangentScreenPosition - Vec2(aznumeric_cast<float>(controlPosition.x()), aznumeric_cast<float>(controlPosition.y()))).Normalize() * aznumeric_cast<float>(m_DistanceFromControl);
|
||||
|
||||
return controlPosition + QPointF(transformedTangentDelta.x, transformedTangentDelta.y);
|
||||
}
|
||||
@@ -1,150 +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 "CurveEditor.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class CCurveEditor;
|
||||
class CCurveEditorTangentControl;
|
||||
class QMouseEvent;
|
||||
|
||||
class QPainter;
|
||||
|
||||
class EDITOR_COMMON_API CCurveEditorControl
|
||||
{
|
||||
public:
|
||||
CCurveEditorControl(CCurveEditor& curveEditor, SCurveEditorCurve& curve, SCurveEditorKey& key);
|
||||
~CCurveEditorControl();
|
||||
|
||||
CCurveEditor& GetCurveEditor() const;
|
||||
SCurveEditorCurve& GetCurve() const;
|
||||
SCurveEditorKey& GetKey() const;
|
||||
|
||||
CCurveEditorTangentControl& GetInTangent();
|
||||
CCurveEditorTangentControl& GetOutTangent();
|
||||
|
||||
void SetVisualSize(int visualSize)
|
||||
{
|
||||
m_VisualSize = visualSize;
|
||||
}
|
||||
void SetClickableSize(int clickableSize)
|
||||
{
|
||||
m_ClickableSize = clickableSize;
|
||||
}
|
||||
|
||||
bool IsSelected() const;
|
||||
void SetSelected(bool selected);
|
||||
|
||||
bool IsKeyMarkedForRemoval() const;
|
||||
void MarkKeyForRemoval();
|
||||
|
||||
void Paint(QPainter& painter, const QPalette& palette, const bool& paintInOutTangents);
|
||||
void PaintIcon(QPainter& painter, const QPalette& palette, const bool& paintInOutTangents);
|
||||
|
||||
bool IsMouseWithinControl(QPointF screenPos) const;
|
||||
|
||||
QPointF GetScreenPosition() const;
|
||||
|
||||
QRect GetRect() const
|
||||
{
|
||||
return QRect(aznumeric_cast<int>(GetScreenPosition().x() - (m_VisualSize / 2)), aznumeric_cast<int>(GetScreenPosition().y() - (m_VisualSize / 2)), m_VisualSize, m_VisualSize);
|
||||
}
|
||||
|
||||
void SetIconShapeColor(QColor color);
|
||||
|
||||
void SetIconFillColor(QColor color);
|
||||
|
||||
void SetIconImage(QString str);
|
||||
|
||||
void SetIconShapeMask(QColor color);
|
||||
|
||||
void SetIconFillMask(QColor color);
|
||||
|
||||
void SetIconToolTip(QString str)
|
||||
{
|
||||
m_tip = str;
|
||||
}
|
||||
|
||||
void SetIconSize(int size)
|
||||
{
|
||||
m_iconsize = size;
|
||||
BuildIcon();
|
||||
}
|
||||
|
||||
QString GetToolTip() const { return m_tip; }
|
||||
|
||||
protected:
|
||||
void BuildIcon();
|
||||
|
||||
private:
|
||||
QPixmap m_icon;
|
||||
QPixmap m_filledPxr;
|
||||
QPixmap m_shapePxr;
|
||||
QPixmap m_originalPxr;
|
||||
QColor m_fillColor;
|
||||
QColor m_shapeColor;
|
||||
QColor m_fillMask;
|
||||
QColor m_shapeMask;
|
||||
QString m_tip;
|
||||
int m_iconsize;
|
||||
|
||||
CCurveEditor& m_CurveEditor;
|
||||
SCurveEditorCurve& m_Curve;
|
||||
SCurveEditorKey& m_Key;
|
||||
|
||||
int m_VisualSize;
|
||||
int m_ClickableSize;
|
||||
|
||||
CCurveEditorTangentControl* m_pInTangent;
|
||||
CCurveEditorTangentControl* m_pOutTangent;
|
||||
};
|
||||
|
||||
class EDITOR_COMMON_API CCurveEditorTangentControl
|
||||
{
|
||||
public:
|
||||
CCurveEditorTangentControl(CCurveEditorControl& curveControl, ETangent tangentDirection);
|
||||
~CCurveEditorTangentControl();
|
||||
|
||||
CCurveEditorControl& GetControl();
|
||||
ETangent GetTangentDirection() const;
|
||||
|
||||
bool IsVisible() const;
|
||||
void SetVisible(bool visible);
|
||||
|
||||
bool IsSelected() const;
|
||||
void SetSelected(bool selected);
|
||||
|
||||
void SetVisualSize(int visualSize);
|
||||
void SetClickableSize(int clickableSize);
|
||||
void SetDistanceFromControl(int distanceFromControl);
|
||||
|
||||
void Paint(QPainter& painter, const QPalette& palette);
|
||||
|
||||
bool IsMouseWithinControl(QPointF screenPos) const;
|
||||
|
||||
private:
|
||||
|
||||
QPointF GetScreenPosition() const;
|
||||
|
||||
CCurveEditorControl& m_Control;
|
||||
ETangent m_TangentDirection;
|
||||
|
||||
bool m_Selected;
|
||||
|
||||
int m_VisualSize;
|
||||
int m_ClickableSize;
|
||||
int m_DistanceFromControl;
|
||||
|
||||
bool m_Visible;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,154 +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 "CurveEditorContent.h"
|
||||
#include <QWidget>
|
||||
#include <Range.h>
|
||||
#include <AnimTime.h>
|
||||
|
||||
class QToolBar;
|
||||
|
||||
enum ECurveEditorCurveType
|
||||
{
|
||||
eCECT_Bezier,
|
||||
// 2D Bezier curves are used for better curve control, the editor
|
||||
// will enforce that the resulting curve is always 1D.
|
||||
eCECT_2DBezier,
|
||||
};
|
||||
|
||||
namespace CurveEditorHelpers
|
||||
{
|
||||
// Picks a nice color value for a curve. Wraps around after 4.
|
||||
EDITOR_COMMON_API ColorB GetCurveColor(const uint n);
|
||||
}
|
||||
|
||||
class EDITOR_COMMON_API CCurveEditor
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CCurveEditor(QWidget* parent);
|
||||
~CCurveEditor();
|
||||
|
||||
void SetContent(SCurveEditorContent* pContent);
|
||||
SCurveEditorContent* Content() const { return m_pContent; }
|
||||
|
||||
SAnimTime Time() const { return m_time; }
|
||||
void SetTime(const SAnimTime time);
|
||||
|
||||
// The background in the time and value range will be drawn a bit brighter to indicate where keys
|
||||
// should be placed. The curve editor does not enforce that the curves actually stay in those ranges.
|
||||
void SetTimeRange(const SAnimTime start, const SAnimTime end);
|
||||
void SetValueRange(const float min, const float max);
|
||||
|
||||
void ZoomToTimeRange(const float start, const float end);
|
||||
void ZoomToValueRange(const float min, const float max);
|
||||
|
||||
void SetCurveType(ECurveEditorCurveType curveType);
|
||||
void SetWeighted(bool bWeighted);
|
||||
void SetHandlesVisible(bool bVisible);
|
||||
void SetRulerVisible(bool bVisible);
|
||||
void SetTimeSliderVisible(bool bVisible);
|
||||
void SetGridVisible(bool bVisible);
|
||||
void SetFrameRate(SAnimTime::EFrameRate frameRate) { m_frameRate = frameRate; }
|
||||
void SetTimeSnapping(bool snapTime) { m_bSnapTime = snapTime; }
|
||||
void SetKeySnapping(bool snapKeys) { m_bSnapKeys = snapKeys; }
|
||||
|
||||
// Tools added to tool bar depend on options above
|
||||
void FillWithCurveToolsAndConnect(QToolBar* pToolBar);
|
||||
|
||||
void paintEvent(QPaintEvent* pEvent) override;
|
||||
void mousePressEvent(QMouseEvent* pEvent) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent* pEvent) override;
|
||||
void mouseMoveEvent(QMouseEvent* pEvent) override;
|
||||
void mouseReleaseEvent(QMouseEvent* pEvent) override;
|
||||
void focusOutEvent(QFocusEvent* pEvent) override;
|
||||
void wheelEvent(QWheelEvent* pEvent) override;
|
||||
void keyPressEvent(QKeyEvent* pEvent) override;
|
||||
|
||||
signals:
|
||||
void SignalContentChanged();
|
||||
void SignalScrub();
|
||||
|
||||
public slots:
|
||||
void OnDeleteSelectedKeys();
|
||||
void OnSetSelectedKeysTangentAuto();
|
||||
void OnSetSelectedKeysInTangentZero();
|
||||
void OnSetSelectedKeysInTangentStep();
|
||||
void OnSetSelectedKeysInTangentLinear();
|
||||
void OnSetSelectedKeysOutTangentZero();
|
||||
void OnSetSelectedKeysOutTangentStep();
|
||||
void OnSetSelectedKeysOutTangentLinear();
|
||||
void OnFitCurvesHorizontally();
|
||||
void OnFitCurvesVertically();
|
||||
void OnBreakTangents();
|
||||
void OnUnifyTangents();
|
||||
|
||||
private:
|
||||
struct SMouseHandler;
|
||||
struct SSelectionHandler;
|
||||
struct SPanHandler;
|
||||
struct SZoomHandler;
|
||||
struct SMoveHandler;
|
||||
struct SHandleMoveHandler;
|
||||
struct SScrubHandler;
|
||||
enum ETangent;
|
||||
|
||||
void DrawGrid(QPainter& painter, const QPalette& palette);
|
||||
|
||||
void LeftButtonMousePressEvent(QMouseEvent* pEvent);
|
||||
void MiddleButtonMousePressEvent(QMouseEvent* pEvent);
|
||||
void RightButtonMousePressEvent(QMouseEvent* pEvent);
|
||||
|
||||
void SelectInRect(const QRect& rect);
|
||||
|
||||
void ContentChanged();
|
||||
void DeleteMarkedKeys();
|
||||
|
||||
std::pair<SCurveEditorCurve*, Vec2> HitDetectCurve(const QPoint point);
|
||||
std::pair<SCurveEditorCurve*, SCurveEditorKey*> HitDetectKey(const QPoint point);
|
||||
std::tuple<SCurveEditorCurve*, SCurveEditorKey, SCurveEditorKey*, ETangent> HitDetectHandle(const QPoint point);
|
||||
Vec2 ClosestPointOnCurve(const Vec2 point, const SCurveEditorCurve& curve, const ECurveEditorCurveType curveType);
|
||||
|
||||
void AddPointToCurve(Vec2 point, SCurveEditorCurve* pCurve);
|
||||
void SortKeys(SCurveEditorCurve& curve);
|
||||
|
||||
QRect GetCurveArea();
|
||||
|
||||
enum ETangent
|
||||
{
|
||||
ETangent_In,
|
||||
ETangent_Out
|
||||
};
|
||||
|
||||
void SetSelectedKeysTangentType(const ETangent tangent, const SBezierControlPoint::ETangentType type);
|
||||
|
||||
SCurveEditorContent* m_pContent;
|
||||
std::unique_ptr<SMouseHandler> m_pMouseHandler;
|
||||
|
||||
ECurveEditorCurveType m_curveType;
|
||||
SAnimTime::EFrameRate m_frameRate;
|
||||
bool m_bWeighted : 1;
|
||||
bool m_bHandlesVisible : 1;
|
||||
bool m_bRulerVisible : 1;
|
||||
bool m_bTimeSliderVisible : 1;
|
||||
bool m_bGridVisible : 1;
|
||||
bool m_bSnapTime : 1;
|
||||
bool m_bSnapKeys : 1;
|
||||
|
||||
SAnimTime m_time;
|
||||
Vec2 m_zoom;
|
||||
Vec2 m_translation;
|
||||
TRange<SAnimTime> m_timeRange;
|
||||
Range m_valueRange;
|
||||
};
|
||||
@@ -1,194 +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 "EditorCommon_precompiled.h"
|
||||
//Cry
|
||||
#include <Cry_Camera.h>
|
||||
|
||||
//Editor
|
||||
#include <Util/EditorUtils.h>
|
||||
#include <Util/Math.h>
|
||||
|
||||
//Local
|
||||
#include "QViewport.h"
|
||||
#include "DisplayViewportAdapter.h"
|
||||
|
||||
CDisplayViewportAdapter::CDisplayViewportAdapter(QViewport* viewport)
|
||||
: m_viewport(viewport)
|
||||
{
|
||||
m_screenMatrix.SetIdentity();
|
||||
}
|
||||
|
||||
void CDisplayViewportAdapter::Update()
|
||||
{
|
||||
}
|
||||
|
||||
const Matrix34& CDisplayViewportAdapter::GetScreenTM() const
|
||||
{
|
||||
return m_screenMatrix;
|
||||
}
|
||||
|
||||
float CDisplayViewportAdapter::GetScreenScaleFactor(const Vec3& position) const
|
||||
{
|
||||
float dist = m_viewport->Camera()->GetPosition().GetDistance(position);
|
||||
if (dist < m_viewport->Camera()->GetNearPlane())
|
||||
{
|
||||
dist = m_viewport->Camera()->GetNearPlane();
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
float CDisplayViewportAdapter::GetScreenScaleFactor([[maybe_unused]] const CCamera& camera, [[maybe_unused]] const Vec3& object_position)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool CDisplayViewportAdapter::HitTestLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& hitpoint, int pixelRadius, float* pToCameraDistance) const
|
||||
{
|
||||
float dist = GetDistanceToLine(lineP1, lineP2, hitpoint);
|
||||
if (dist <= pixelRadius)
|
||||
{
|
||||
if (pToCameraDistance)
|
||||
{
|
||||
Vec3 raySrc, rayDir;
|
||||
ViewToWorldRay(hitpoint, raySrc, rayDir);
|
||||
Vec3 rayTrg = raySrc + rayDir * 10000.0f;
|
||||
|
||||
Vec3 pa, pb;
|
||||
float mua, mub;
|
||||
LineLineIntersect(lineP1, lineP2, raySrc, rayTrg, pa, pb, mua, mub);
|
||||
*pToCameraDistance = mub;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float CDisplayViewportAdapter::GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const
|
||||
{
|
||||
QPoint p1 = WorldToView(lineP1);
|
||||
QPoint p2 = WorldToView(lineP2);
|
||||
|
||||
return PointToLineDistance2D(
|
||||
Vec3(float(p1.x()), float(p1.y()), 0),
|
||||
Vec3(float(p2.x()), float(p2.y()), 0),
|
||||
Vec3(float(point.x()), float(point.y()), 0));
|
||||
}
|
||||
|
||||
CBaseObjectsCache* CDisplayViewportAdapter::GetVisibleObjectsCache()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CDisplayViewportAdapter::IsBoundsVisible([[maybe_unused]] const AABB& box) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CDisplayViewportAdapter::GetPerpendicularAxis(EAxis* axis, bool* is2D) const
|
||||
{
|
||||
*axis = AXIS_NONE;
|
||||
*is2D = false;
|
||||
}
|
||||
|
||||
const Matrix34& CDisplayViewportAdapter::GetViewTM() const
|
||||
{
|
||||
m_viewMatrix = m_viewport->Camera()->GetViewMatrix();
|
||||
return m_viewMatrix;
|
||||
}
|
||||
|
||||
QPoint CDisplayViewportAdapter::WorldToView(const Vec3& worldPoint) const
|
||||
{
|
||||
return m_viewport->ProjectToScreen(worldPoint);
|
||||
}
|
||||
|
||||
QPoint CDisplayViewportAdapter::WorldToViewParticleEditor(const Vec3& worldPoint, [[maybe_unused]] int width, [[maybe_unused]] int height) const
|
||||
{
|
||||
return m_viewport->ProjectToScreen(worldPoint);
|
||||
}
|
||||
|
||||
Vec3 CDisplayViewportAdapter::WorldToView3D([[maybe_unused]] const Vec3& worldPoint, [[maybe_unused]] int flags) const
|
||||
{
|
||||
return Vec3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
Vec3 CDisplayViewportAdapter::ViewToWorld([[maybe_unused]] const QPoint& vp, [[maybe_unused]] bool* collideWithTerrain, [[maybe_unused]] bool onlyTerrain, [[maybe_unused]] bool bSkipVegetation, [[maybe_unused]] bool bTestRenderMesh, [[maybe_unused]] bool* collideWithObject) const
|
||||
{
|
||||
return Vec3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void CDisplayViewportAdapter::ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const
|
||||
{
|
||||
Ray ray;
|
||||
// this can fail for number of reasons
|
||||
if (!m_viewport->ScreenToWorldRay(&ray, vp.x(), vp.y()))
|
||||
{
|
||||
// return some "safe" default that will not cause FPE
|
||||
raySrc = m_viewport->Camera()->GetPosition();
|
||||
rayDir = m_viewport->Camera()->GetViewdir();
|
||||
|
||||
// the interface should be changed to accommodate for error
|
||||
return;
|
||||
}
|
||||
raySrc = ray.origin;
|
||||
rayDir = ray.direction;
|
||||
}
|
||||
|
||||
float CDisplayViewportAdapter::GetGridStep() const
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float CDisplayViewportAdapter::GetAspectRatio() const
|
||||
{
|
||||
int w, h;
|
||||
GetDimensions(&w, &h);
|
||||
if (h != 0)
|
||||
{
|
||||
return float(w) / h;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
const Plane* CDisplayViewportAdapter::GetConstructionPlane() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CDisplayViewportAdapter::ScreenToClient([[maybe_unused]] QPoint& pt) const
|
||||
{
|
||||
}
|
||||
|
||||
void CDisplayViewportAdapter::GetDimensions(int* width, int* height) const
|
||||
{
|
||||
if (width)
|
||||
{
|
||||
*width = m_viewport->Width();
|
||||
}
|
||||
if (height)
|
||||
{
|
||||
*height = m_viewport->Height();
|
||||
}
|
||||
}
|
||||
|
||||
void CDisplayViewportAdapter::setRay([[maybe_unused]] QPoint& vp, [[maybe_unused]] Vec3& raySrc, [[maybe_unused]] Vec3& rayDir)
|
||||
{
|
||||
}
|
||||
|
||||
void CDisplayViewportAdapter::setHitcontext([[maybe_unused]] QPoint& vp, [[maybe_unused]] Vec3& raySrc, [[maybe_unused]] Vec3& rayDir)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
//Cry
|
||||
#include <Cry_Math.h>
|
||||
#include "Cry_Matrix34.h"
|
||||
#include "Cry_Vector3.h"
|
||||
|
||||
//Editor
|
||||
#include "Include/IDisplayViewport.h"
|
||||
|
||||
//Local
|
||||
#include "EditorCommonAPI.h"
|
||||
|
||||
class EDITOR_COMMON_API QViewport;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
class EDITOR_COMMON_API CDisplayViewportAdapter
|
||||
: public ::IDisplayViewport
|
||||
{
|
||||
public:
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
CDisplayViewportAdapter(QViewport* viewport);
|
||||
|
||||
void Update() override;
|
||||
const Matrix34& GetScreenTM() const override;
|
||||
float GetScreenScaleFactor(const Vec3& position) const override;
|
||||
float GetScreenScaleFactor(const CCamera& camera, const Vec3& object_position) override;
|
||||
bool HitTestLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& hitpoint, int pixelRadius, float* pToCameraDistance = 0) const override;
|
||||
float GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const override;
|
||||
CBaseObjectsCache* GetVisibleObjectsCache() override;
|
||||
bool IsBoundsVisible(const AABB& box) const override;
|
||||
void GetPerpendicularAxis(EAxis* axis, bool* is2D) const override;
|
||||
const Matrix34& GetViewTM() const override;
|
||||
QPoint WorldToView(const Vec3& worldPoint) const override;
|
||||
QPoint WorldToViewParticleEditor(const Vec3& worldPoint, int width, int height) const override;
|
||||
Vec3 WorldToView3D(const Vec3& worldPoint, int flags = 0) const override;
|
||||
Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override;
|
||||
void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const override;
|
||||
float GetGridStep() const override;
|
||||
float GetAspectRatio() const override;
|
||||
const Plane* GetConstructionPlane() const override;
|
||||
void ScreenToClient(QPoint& pt) const override;
|
||||
void GetDimensions(int* width, int* height) const override;
|
||||
void setRay(QPoint& vp, Vec3& raySrc, Vec3& rayDir) override;
|
||||
void setHitcontext(QPoint& vp, Vec3& raySrc, Vec3& rayDir) override;
|
||||
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
mutable Matrix34 m_viewMatrix;
|
||||
Matrix34 m_screenMatrix;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QViewport* m_viewport;
|
||||
};
|
||||
@@ -16,13 +16,16 @@
|
||||
#include <QStyleOptionToolButton>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
|
||||
static QColor Interpolate(const QColor& a, const QColor& b, float k)
|
||||
namespace DockTitleBarInterpolate
|
||||
{
|
||||
float mk = 1.0f - k;
|
||||
return QColor(aznumeric_cast<int>(a.red() * mk + b.red() * k),
|
||||
aznumeric_cast<int>(a.green() * mk + b.green() * k),
|
||||
aznumeric_cast<int>(a.blue() * mk + b.blue() * k),
|
||||
aznumeric_cast<int>(a.alpha() * mk + b.alpha() * k));
|
||||
static QColor Interpolate(const QColor& a, const QColor& b, float k)
|
||||
{
|
||||
float mk = 1.0f - k;
|
||||
return QColor(aznumeric_cast<int>(a.red() * mk + b.red() * k),
|
||||
aznumeric_cast<int>(a.green() * mk + b.green() * k),
|
||||
aznumeric_cast<int>(a.blue() * mk + b.blue() * k),
|
||||
aznumeric_cast<int>(a.alpha() * mk + b.alpha() * k));
|
||||
}
|
||||
}
|
||||
|
||||
class CDockWidgetTitleButton
|
||||
@@ -60,7 +63,7 @@ public:
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
QRect r = rect().adjusted(2, 2, -3, -3);
|
||||
p.translate(0.5f, 0.5f);
|
||||
QColor color = Interpolate(palette().color(QPalette::Window), palette().color(QPalette::Shadow), 0.2f);
|
||||
QColor color = DockTitleBarInterpolate::Interpolate(palette().color(QPalette::Window), palette().color(QPalette::Shadow), 0.2f);
|
||||
p.setBrush(QBrush(color));
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawRoundedRect(r, 4, 4, Qt::AbsoluteSize);
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace DrawingPrimitives
|
||||
|
||||
void DrawTicks(const std::vector<STick>& ticks, QPainter& painter, const QPalette& palette, const STickOptions& options)
|
||||
{
|
||||
QColor midDark = Interpolate(palette.color(QPalette::Dark), palette.color(QPalette::Button), 0.5f);
|
||||
QColor midDark = DrawingPrimitives::Interpolate(palette.color(QPalette::Dark), palette.color(QPalette::Button), 0.5f);
|
||||
painter.setPen(QPen(midDark));
|
||||
|
||||
const int height = options.m_rect.height();
|
||||
@@ -149,13 +149,13 @@ namespace DrawingPrimitives
|
||||
painter.fillRect(shadowRect, upperBrush);
|
||||
}
|
||||
|
||||
painter.fillRect(options.m_rect, Interpolate(palette.color(QPalette::Button), palette.color(QPalette::Midlight), 0.25f));
|
||||
painter.fillRect(options.m_rect, DrawingPrimitives::Interpolate(palette.color(QPalette::Button), palette.color(QPalette::Midlight), 0.25f));
|
||||
if (options.m_drawBackgroundCallback)
|
||||
{
|
||||
options.m_drawBackgroundCallback();
|
||||
}
|
||||
|
||||
QColor midDark = Interpolate(palette.color(QPalette::Dark), palette.color(QPalette::Button), 0.5f);
|
||||
QColor midDark = DrawingPrimitives::Interpolate(palette.color(QPalette::Dark), palette.color(QPalette::Button), 0.5f);
|
||||
painter.setPen(QPen(midDark));
|
||||
|
||||
QFont font;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>Icons/CurveEditor/auto.png</file>
|
||||
<file>Icons/CurveEditor/fit_horizontal.png</file>
|
||||
<file>Icons/CurveEditor/fit_vertical.png</file>
|
||||
<file>Icons/CurveEditor/linear_in.png</file>
|
||||
<file>Icons/CurveEditor/linear_out.png</file>
|
||||
<file>Icons/CurveEditor/step_in.png</file>
|
||||
<file>Icons/CurveEditor/step_out.png</file>
|
||||
<file>Icons/CurveEditor/zero_in.png</file>
|
||||
<file>Icons/CurveEditor/zero_out.png</file>
|
||||
<file>Icons/CurveEditor/break.png</file>
|
||||
<file>Icons/CurveEditor/unify.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,144 +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 "EditorCommon_precompiled.h"
|
||||
#include "EventManager.h"
|
||||
#include "Serialization/JSONIArchive.h"
|
||||
#include "Serialization/JSONOArchive.h"
|
||||
|
||||
CEventManager* CEventManager::ms_pEventManager;
|
||||
|
||||
CEventManager::CEventManager()
|
||||
: m_nextAddress(0)
|
||||
, m_nextHandlerId(0)
|
||||
{
|
||||
if (ms_pEventManager)
|
||||
{
|
||||
CryFatalError("There should be only one event manager instance");
|
||||
}
|
||||
|
||||
ms_pEventManager = this;
|
||||
}
|
||||
|
||||
void CEventManager::Init([[maybe_unused]] SSystemGlobalEnvironment* env)
|
||||
{
|
||||
}
|
||||
|
||||
CEventManager* CEventManager::GetInstance()
|
||||
{
|
||||
return ms_pEventManager;
|
||||
}
|
||||
|
||||
uint CEventManager::GetAddressId(const char* name)
|
||||
{
|
||||
auto findIter = m_nameToAddressMap.find(name);
|
||||
if (findIter != m_nameToAddressMap.end())
|
||||
{
|
||||
return findIter->second;
|
||||
}
|
||||
|
||||
uint newId = m_nextAddress++;
|
||||
m_nameToAddressMap[name] = newId;
|
||||
return newId;
|
||||
}
|
||||
|
||||
uint CEventManager::GetUniqueAddressId()
|
||||
{
|
||||
return m_nextAddress++;
|
||||
}
|
||||
|
||||
void CEventManager::SendEventRaw(const uint address, const char* eventName, const char* message) const
|
||||
{
|
||||
SendEventImplementation(address, eventName, message, DynArray<uint>());
|
||||
}
|
||||
|
||||
void CEventManager::SendEventRaw(const uint address, const char* eventName, const char* message, const DynArray<uint>& excludedHandlers) const
|
||||
{
|
||||
SendEventImplementation(address, eventName, message, excludedHandlers);
|
||||
}
|
||||
|
||||
void CEventManager::SendEventImplementation(const uint address, const string& eventName, const string& message, const DynArray<uint>& excludedHandlers) const
|
||||
{
|
||||
auto handlerFindIter = m_messageRoutingMap.find(std::make_pair(address, eventName));
|
||||
if (handlerFindIter != m_messageRoutingMap.end())
|
||||
{
|
||||
const std::vector<std::pair<uint, TEventHandlerFunc> >& handlers = handlerFindIter->second;
|
||||
|
||||
for (uint i = 0; i < handlers.size(); ++i)
|
||||
{
|
||||
if (!stl::find(excludedHandlers, handlers[i].first))
|
||||
{
|
||||
handlers[i].second(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CEventManager::CanDeliverRaw(const uint address, const char* eventName) const
|
||||
{
|
||||
auto handlerFindIter = m_messageRoutingMap.find(std::make_pair(address, eventName));
|
||||
if (handlerFindIter != m_messageRoutingMap.end())
|
||||
{
|
||||
const std::vector<std::pair<uint, TEventHandlerFunc> >& handlers = handlerFindIter->second;
|
||||
return !handlers.empty();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CEventConnection CEventManager::AddEventCallbackRaw(const uint address, const char* eventName, TEventHandlerFunc callback)
|
||||
{
|
||||
const uint handlerId = m_nextHandlerId++;
|
||||
m_messageRoutingMap[std::make_pair(address, eventName)].push_back(std::make_pair(handlerId, callback));
|
||||
return CEventConnection(address, eventName, handlerId);
|
||||
}
|
||||
|
||||
string CEventManager::SerializeMessageToJSON(const Serialization::SStruct& ref) const
|
||||
{
|
||||
Serialization::JSONOArchive oArchive;
|
||||
oArchive(ref);
|
||||
return oArchive.buffer();
|
||||
}
|
||||
|
||||
void CEventManager::DeserializeFromJSON(const Serialization::SStruct& ref, const string& json)
|
||||
{
|
||||
Serialization::JSONIArchive iArchive;
|
||||
if (iArchive.open(json.data(), json.size()))
|
||||
{
|
||||
iArchive(ref);
|
||||
}
|
||||
}
|
||||
|
||||
void CEventConnection::Disconnect()
|
||||
{
|
||||
if (m_bConnected)
|
||||
{
|
||||
auto& messageMap = CEventManager::GetInstance()->m_messageRoutingMap;
|
||||
auto findIter = messageMap.find(std::make_pair(m_address, m_eventName));
|
||||
|
||||
if (findIter != messageMap.end())
|
||||
{
|
||||
stl::find_and_erase_if(findIter->second, [=](const std::pair<uint, CEventManager::TEventHandlerFunc>& h)
|
||||
{
|
||||
return h.first == m_handlerId;
|
||||
});
|
||||
}
|
||||
|
||||
if (findIter->second.empty())
|
||||
{
|
||||
messageMap.erase(findIter);
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
@@ -1,204 +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_EDITORCOMMON_EVENTS_EVENTMANAGER_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_EVENTS_EVENTMANAGER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include "EditorCommonAPI.h"
|
||||
#include "IEditor.h"
|
||||
|
||||
#include "Serialization/IArchive.h"
|
||||
|
||||
struct SSystemGlobalEnvironment;
|
||||
|
||||
class CEventConnection
|
||||
{
|
||||
friend class CEventManager;
|
||||
friend class CScopedEventConnection;
|
||||
|
||||
public:
|
||||
CEventConnection()
|
||||
: m_bConnected(false) {}
|
||||
|
||||
EDITOR_COMMON_API void Disconnect();
|
||||
|
||||
uint GetHandlerId() const { return m_handlerId; }
|
||||
|
||||
private:
|
||||
CEventConnection(const uint address, const string& eventName, const uint handlerId)
|
||||
: m_address(address)
|
||||
, m_eventName(eventName)
|
||||
, m_handlerId(handlerId)
|
||||
, m_bConnected(true) {}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_bConnected = false;
|
||||
m_address = 0;
|
||||
m_handlerId = 0;
|
||||
m_eventName.clear();
|
||||
}
|
||||
|
||||
void Move(CEventConnection& other)
|
||||
{
|
||||
m_bConnected = other.m_bConnected;
|
||||
m_address = other.m_address;
|
||||
m_handlerId = other.m_handlerId;
|
||||
m_eventName.swap(other.m_eventName);
|
||||
other.Reset();
|
||||
}
|
||||
|
||||
bool m_bConnected;
|
||||
uint m_address;
|
||||
uint m_handlerId;
|
||||
string m_eventName;
|
||||
};
|
||||
|
||||
class CScopedEventConnection
|
||||
: public CEventConnection
|
||||
{
|
||||
public:
|
||||
CScopedEventConnection()
|
||||
: CEventConnection() {}
|
||||
|
||||
CScopedEventConnection(CScopedEventConnection&& connection)
|
||||
{
|
||||
Move(connection);
|
||||
}
|
||||
|
||||
CScopedEventConnection(CEventConnection&& connection)
|
||||
{
|
||||
Move(connection);
|
||||
}
|
||||
|
||||
CScopedEventConnection& operator =(CEventConnection&& connection)
|
||||
{
|
||||
if (&connection != this)
|
||||
{
|
||||
Disconnect();
|
||||
Move(connection);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~CScopedEventConnection() { Disconnect(); }
|
||||
|
||||
private:
|
||||
CScopedEventConnection(const CScopedEventConnection&); // no implementation
|
||||
CScopedEventConnection& operator =(const CScopedEventConnection&); // no implementation
|
||||
};
|
||||
|
||||
class EDITOR_COMMON_API CEventManager
|
||||
{
|
||||
friend class CEventConnection;
|
||||
|
||||
public:
|
||||
CEventManager();
|
||||
|
||||
static CEventManager* GetInstance();
|
||||
|
||||
void Init(SSystemGlobalEnvironment* pEnv);
|
||||
|
||||
// Registers an address and returns its ID. Multiple event handlers can listen to the same address, allowing broadcasts.
|
||||
uint GetAddressId(const char* name);
|
||||
|
||||
// Registers a new unique address
|
||||
uint GetUniqueAddressId();
|
||||
|
||||
public:
|
||||
|
||||
// Sends an event to an address
|
||||
//
|
||||
// TMessageType must be a serializable struct
|
||||
//
|
||||
template <class TMessageType>
|
||||
void SendEvent(const uint address, const TMessageType& message)
|
||||
{
|
||||
const string json = SerializeMessageToJSON(Serialization::SStruct(message));
|
||||
SendEventRaw(address, TMessageType::GetName(), json);
|
||||
}
|
||||
|
||||
template <class TMessageType>
|
||||
void SendEvent(const uint address, const TMessageType& message, const DynArray<uint>& excludedHandlers) const
|
||||
{
|
||||
const string json = SerializeMessageToJSON(Serialization::SStruct(message));
|
||||
SendEventRaw(address, TMessageType::GetName(), json, excludedHandlers);
|
||||
}
|
||||
|
||||
// For sending a raw JSON message.
|
||||
void SendEventRaw(const uint address, const char* eventName, const char* message) const;
|
||||
void SendEventRaw(const uint address, const char* eventName, const char* message, const DynArray<uint>& excludedHandlers) const;
|
||||
|
||||
// Tests if a call to SendEvent would actually send a message (there is someone listening to this message)
|
||||
bool CanDeliverRaw(const uint address, const char* eventName) const;
|
||||
template<class TMessageType>
|
||||
bool CanDeliver(const uint address) const
|
||||
{
|
||||
const char* pEventName = TMessageType::GetName();
|
||||
return CanDeliverRaw(address, pEventName);
|
||||
}
|
||||
|
||||
// This should be the most common way to add an event callback
|
||||
//
|
||||
// This example will install an event handler for OnEvent(const SMessageType &message) that is sent to a specific address:
|
||||
// CEventManager::GetInstance()->AddEventCallback(componentId, this, &CEventHandler::OnEvent);
|
||||
//
|
||||
// TMessageType must be a serializable struct
|
||||
//
|
||||
// Returns a CEventConnection. The callback is removed when this object is destroyed.
|
||||
//
|
||||
template <class TClassType, class TMessageType>
|
||||
CEventConnection AddEventCallback(const uint address, TClassType* pThis, void (TClassType::* pMethod)(const TMessageType&))
|
||||
{
|
||||
return AddEventCallback<TMessageType>(address, std::bind(pMethod, pThis, std::placeholders::_1));
|
||||
}
|
||||
|
||||
// Same as above, but you can pass in any function object that takes TMessageType& as an argument directly.
|
||||
//
|
||||
template <class TMessageType>
|
||||
CEventConnection AddEventCallback(const uint address, std::function<void (const TMessageType&)> callback)
|
||||
{
|
||||
return AddEventCallbackRaw(address, TMessageType::GetName(), [=](const string& json)
|
||||
{
|
||||
TMessageType message;
|
||||
DeserializeFromJSON(Serialization::SStruct(message), json);
|
||||
callback(message);
|
||||
});
|
||||
}
|
||||
|
||||
// This can be used if raw parsing of JSON is preferred.
|
||||
typedef std::function<void (const char*)> TEventHandlerFunc;
|
||||
CEventConnection AddEventCallbackRaw(const uint componentId, const char* eventName, TEventHandlerFunc callback);
|
||||
|
||||
private:
|
||||
void SendEventImplementation(const uint address, const string& eventName, const string& message, const DynArray<uint>& excludedHandlers) const;
|
||||
|
||||
string SerializeMessageToJSON(const Serialization::SStruct& ref) const;
|
||||
void DeserializeFromJSON(const Serialization::SStruct& ref, const string& json);
|
||||
|
||||
uint m_nextAddress;
|
||||
uint m_nextHandlerId;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
std::map<string, uint, stl::less_stricmp<string> > m_nameToAddressMap;
|
||||
std::map<std::pair<uint, string>, std::vector<std::pair<uint, TEventHandlerFunc> > > m_messageRoutingMap;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
static CEventManager* ms_pEventManager;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_EVENTS_EVENTMANAGER_H
|
||||
@@ -1,224 +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 "EditorCommon_precompiled.h"
|
||||
#include "Serialization/ClassFactory.h"
|
||||
#include "Serialization/Pointers.h"
|
||||
#include "Serialization/IArchive.h"
|
||||
#include "ListSelectionDialog.h"
|
||||
#include <IEditor.h>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QBoxLayout>
|
||||
#include <QTreeView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QIcon>
|
||||
#include <QMenu>
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QCoreApplication>
|
||||
#include <QByteArray>
|
||||
#include "IResourceSelectorHost.h"
|
||||
|
||||
#include "DeepFilterProxyModel.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
ListSelectionDialog::ListSelectionDialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_currentColumn(0)
|
||||
{
|
||||
setWindowTitle("Choose...");
|
||||
setWindowModality(Qt::ApplicationModal);
|
||||
|
||||
QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
setLayout(layout);
|
||||
|
||||
QBoxLayout* filterBox = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
layout->addLayout(filterBox);
|
||||
{
|
||||
filterBox->addWidget(new QLabel("Filter:", this), 0);
|
||||
filterBox->addWidget(m_filterEdit = new QLineEdit(this), 1);
|
||||
connect(m_filterEdit, SIGNAL(textChanged(const QString&)), this, SLOT(onFilterChanged(const QString&)));
|
||||
m_filterEdit->installEventFilter(this);
|
||||
}
|
||||
|
||||
QBoxLayout* infoBox = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
layout->addLayout(infoBox);
|
||||
|
||||
m_model = new QStandardItemModel();
|
||||
m_model->setColumnCount(1);
|
||||
m_model->setHeaderData(0, Qt::Horizontal, "Name", Qt::DisplayRole);
|
||||
|
||||
m_filterModel = new DeepFilterProxyModel(this);
|
||||
m_filterModel->setSourceModel(m_model);
|
||||
m_filterModel->setDynamicSortFilter(true);
|
||||
|
||||
m_tree = new QTreeView(this);
|
||||
//m_tree->setColumnCount(3);
|
||||
m_tree->setModel(m_filterModel);
|
||||
|
||||
m_tree->header()->setStretchLastSection(false);
|
||||
#if QT_VERSION >= 0x50000
|
||||
m_tree->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
#else
|
||||
m_tree->header()->setResizeMode(0, QHeaderView::Stretch);
|
||||
#endif
|
||||
//m_tree->header()->resizeSection(0, 80);
|
||||
connect(m_tree, SIGNAL(activated(const QModelIndex&)), this, SLOT(onActivated(const QModelIndex&)));
|
||||
|
||||
layout->addWidget(m_tree, 1);
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(this);
|
||||
buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
layout->addWidget(buttons, 0);
|
||||
}
|
||||
|
||||
bool ListSelectionDialog::eventFilter(QObject* obj, QEvent* event)
|
||||
{
|
||||
if (obj == m_filterEdit && event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent* keyEvent = (QKeyEvent*)event;
|
||||
if (keyEvent->key() == Qt::Key_Down ||
|
||||
keyEvent->key() == Qt::Key_Up ||
|
||||
keyEvent->key() == Qt::Key_PageDown ||
|
||||
keyEvent->key() == Qt::Key_PageUp)
|
||||
{
|
||||
QCoreApplication::sendEvent(m_tree, event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QDialog::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void ListSelectionDialog::onFilterChanged(const QString& str)
|
||||
{
|
||||
m_filterModel->setFilterString(str);
|
||||
m_filterModel->invalidate();
|
||||
m_tree->expandAll();
|
||||
|
||||
QModelIndex currentSource = m_filterModel->mapToSource(m_tree->selectionModel()->currentIndex());
|
||||
if (!currentSource.isValid() || !m_filterModel->matchFilter(currentSource.row(), currentSource.parent()))
|
||||
{
|
||||
QModelIndex firstMatchingIndex = m_filterModel->findFirstMatchingIndex(QModelIndex());
|
||||
if (firstMatchingIndex.isValid())
|
||||
{
|
||||
m_tree->selectionModel()->setCurrentIndex(firstMatchingIndex, QItemSelectionModel::SelectCurrent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListSelectionDialog::onActivated(const QModelIndex& index)
|
||||
{
|
||||
m_tree->setCurrentIndex(index);
|
||||
accept();
|
||||
}
|
||||
|
||||
QSize ListSelectionDialog::sizeHint() const
|
||||
{
|
||||
return QSize(600, 900);
|
||||
}
|
||||
|
||||
void ListSelectionDialog::SetColumnText(int column, const char* text)
|
||||
{
|
||||
if (column >= m_model->columnCount())
|
||||
{
|
||||
int oldColumnCount = m_model->columnCount();
|
||||
m_model->setColumnCount(column + 1);
|
||||
for (int i = oldColumnCount; i <= column; ++i)
|
||||
{
|
||||
#if QT_VERSION >= 0x50000
|
||||
m_tree->header()->setSectionResizeMode(i, QHeaderView::Interactive);
|
||||
#else
|
||||
m_tree->header()->setResizeMode(i, QHeaderView::Interactive);
|
||||
#endif
|
||||
m_tree->header()->resizeSection(i, 40);
|
||||
}
|
||||
}
|
||||
m_model->setHeaderData(column, Qt::Horizontal, text, Qt::DisplayRole);
|
||||
}
|
||||
|
||||
void ListSelectionDialog::SetColumnWidth(int column, int width)
|
||||
{
|
||||
if (column >= m_model->columnCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_tree->header()->resizeSection(column, width);
|
||||
}
|
||||
|
||||
|
||||
void ListSelectionDialog::AddRow(const char* name)
|
||||
{
|
||||
AddRow(name, QIcon());
|
||||
}
|
||||
|
||||
void ListSelectionDialog::AddRow(const char* name, const QIcon& icon)
|
||||
{
|
||||
QStandardItem* item = new QStandardItem(name);
|
||||
item->setEditable(false);
|
||||
item->setData(name);
|
||||
item->setIcon(icon);
|
||||
|
||||
QList<QStandardItem*> items;
|
||||
items.append(item);
|
||||
|
||||
m_model->appendRow(items);
|
||||
m_currentColumn = 1;
|
||||
m_firstColumnToItem[name] = item;
|
||||
}
|
||||
|
||||
void ListSelectionDialog::AddRowColumn(const char* text)
|
||||
{
|
||||
int itemCount = m_model->rowCount(QModelIndex());
|
||||
if (itemCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QStandardItem* item = new QStandardItem();
|
||||
item->setText(QString::fromLocal8Bit(text));
|
||||
if (QStandardItem* lastItem = m_model->item(itemCount - 1, 0))
|
||||
{
|
||||
item->setData(lastItem->data());
|
||||
}
|
||||
item->setEditable(false);
|
||||
m_model->setItem(itemCount - 1, m_currentColumn, item);
|
||||
++m_currentColumn;
|
||||
}
|
||||
|
||||
QString ListSelectionDialog::ChooseItem(const QString& currentValue)
|
||||
{
|
||||
m_tree->expandAll();
|
||||
|
||||
if (exec() == QDialog::Accepted && m_tree->selectionModel()->currentIndex().isValid())
|
||||
{
|
||||
QModelIndex currentIndex = m_tree->selectionModel()->currentIndex();
|
||||
QModelIndex sourceCurrentIndex = m_filterModel->mapToSource(currentIndex);
|
||||
QStandardItem* item = m_model->itemFromIndex(sourceCurrentIndex);
|
||||
if (item)
|
||||
{
|
||||
m_chosenItem = item->data().toString().toUtf8();
|
||||
return m_chosenItem.constData();
|
||||
}
|
||||
}
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#include <moc_ListSelectionDialog.cpp>
|
||||
@@ -1,73 +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_EDITORCOMMON_LISTSELECTIONDIALOG_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_LISTSELECTIONDIALOG_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "EditorCommonAPI.h"
|
||||
#include <QDialog>
|
||||
#include <QMap>
|
||||
#endif
|
||||
|
||||
class DeepFilterProxyModel;
|
||||
class QLineEdit;
|
||||
class QModelIndex;
|
||||
class QStandardItemModel;
|
||||
class QStandardItem;
|
||||
class QString;
|
||||
class QTreeView;
|
||||
class QWidget;
|
||||
class QByteArray;
|
||||
|
||||
class EDITOR_COMMON_API ListSelectionDialog
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ListSelectionDialog(QWidget* parent);
|
||||
void SetColumnText(int column, const char* text);
|
||||
void SetColumnWidth(int column, int width);
|
||||
|
||||
void AddRow(const char* firstColumnValue);
|
||||
void AddRow(const char* firstColumnValue, const QIcon& icon);
|
||||
void AddRowColumn(const char* value);
|
||||
|
||||
QString ChooseItem(const QString& currentValue);
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
protected slots:
|
||||
void onActivated(const QModelIndex& index);
|
||||
void onFilterChanged(const QString&);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* obj, QEvent* event);
|
||||
|
||||
private:
|
||||
QTreeView* m_tree;
|
||||
QStandardItemModel* m_model;
|
||||
DeepFilterProxyModel* m_filterModel;
|
||||
typedef QMap<QString, QStandardItem*> StringToItem;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
StringToItem m_firstColumnToItem;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QLineEdit* m_filterEdit;
|
||||
QByteArray m_chosenItem;
|
||||
int m_currentColumn;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_LISTSELECTIONDIALOG_H
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates
|
||||
|
||||
#include <QPropertyTree/Unicode.h>
|
||||
|
||||
#include <vector>
|
||||
#include <QtCore/QString>
|
||||
|
||||
string fromWideChar(const wchar_t* wstr)
|
||||
{
|
||||
return QString::fromWCharArray(wstr).toUtf8().data();
|
||||
}
|
||||
|
||||
wstring toWideChar(const char* str)
|
||||
{
|
||||
QString s = QString::fromUtf8(str);
|
||||
|
||||
std::vector<wchar_t> result(s.size()+1);
|
||||
s.toWCharArray(&result[0]);
|
||||
return &result[0];
|
||||
}
|
||||
|
||||
@@ -1,14 +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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../Common/UnixLike/QPropertyTree/Unicode_UnixLike.cpp
|
||||
)
|
||||
@@ -1,14 +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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../Common/UnixLike/QPropertyTree/Unicode_UnixLike.cpp
|
||||
)
|
||||
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates
|
||||
|
||||
#include <QPropertyTree/Unicode.h>
|
||||
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
|
||||
string fromWideChar(const wchar_t* wstr)
|
||||
{
|
||||
// We have different implementation for windows as Qt for windows
|
||||
// is built with wchar_t of diferent size (4 bytes, as on linux).
|
||||
// Therefore we avoid calling any wchar_t functions in Qt.
|
||||
const unsigned int codepage = CP_UTF8;
|
||||
int len = WideCharToMultiByte(codepage, 0, wstr, -1, NULL, 0, 0, 0);
|
||||
char* buf = (char*)alloca(len);
|
||||
if (len > 1) {
|
||||
WideCharToMultiByte(codepage, 0, wstr, -1, buf, len, 0, 0);
|
||||
return string(buf, len - 1);
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
wstring toWideChar(const char* str)
|
||||
{
|
||||
const unsigned int codepage = CP_UTF8;
|
||||
int len = MultiByteToWideChar(codepage, 0, str, -1, NULL, 0);
|
||||
wchar_t* buf = (wchar_t*)alloca(len * sizeof(wchar_t));
|
||||
if (len > 1) {
|
||||
MultiByteToWideChar(codepage, 0, str, -1, buf, len);
|
||||
return wstring(buf, len - 1);
|
||||
}
|
||||
return wstring();
|
||||
}
|
||||
|
||||
@@ -1,14 +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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
QPropertyTree/Unicode_Windows.cpp
|
||||
)
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
#include <QAbstractQVariantTreeDataModel.h>
|
||||
|
||||
|
||||
QAbstractQVariantTreeDataModel::Item* QAbstractQVariantTreeDataModel::itemFromIndex(const QModelIndex& index) const
|
||||
{
|
||||
if (index.isValid())
|
||||
{
|
||||
return (Item*)index.internalPointer();
|
||||
}
|
||||
return m_root.get();
|
||||
}
|
||||
|
||||
QModelIndex QAbstractQVariantTreeDataModel::indexFromItem(QAbstractQVariantTreeDataModel::Item* item, int col /*= 0*/) const
|
||||
{
|
||||
if (0 == item)
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
if (!item->m_parent || !item->m_parent->asFolder())
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
int row = item->m_parent->asFolder()->row(item);
|
||||
return createIndex(row, col, item);
|
||||
}
|
||||
|
||||
QModelIndex QAbstractQVariantTreeDataModel::index(int row, int column, const QModelIndex& parent /*= QModelIndex()*/) const
|
||||
{
|
||||
Item* parentItem = itemFromIndex(parent);
|
||||
if (parentItem && parentItem->asFolder() && row < parentItem->asFolder()->m_children.size())
|
||||
{
|
||||
Item* item = parentItem->asFolder()->m_children[row].get();
|
||||
return createIndex(row, column, item);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex QAbstractQVariantTreeDataModel::parent(const QModelIndex& child) const
|
||||
{
|
||||
Item* item = itemFromIndex(child);
|
||||
return item && item->m_parent && item->m_parent->asFolder() ? indexFromItem(item->m_parent) : QModelIndex();
|
||||
}
|
||||
|
||||
bool QAbstractQVariantTreeDataModel::hasChildren(const QModelIndex& parent /* = QModelIndex() */) const
|
||||
{
|
||||
Item* item = itemFromIndex(parent);
|
||||
return item && item->asFolder() && item->asFolder()->m_children.size();
|
||||
}
|
||||
|
||||
int QAbstractQVariantTreeDataModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const
|
||||
{
|
||||
Item* item = itemFromIndex(parent);
|
||||
int res = 0;
|
||||
if (item && item->asFolder())
|
||||
{
|
||||
res = (int) item->asFolder()->m_children.size();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int QAbstractQVariantTreeDataModel::columnCount([[maybe_unused]] const QModelIndex& parent /*= QModelIndex()*/) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -1,87 +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.
|
||||
*
|
||||
*/
|
||||
#ifndef QABSTRACTQVARIANTTREEDATAMODEL_H
|
||||
#define QABSTRACTQVARIANTTREEDATAMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "EditorCommonAPI.h"
|
||||
|
||||
|
||||
class EDITOR_COMMON_API QAbstractQVariantTreeDataModel
|
||||
: public QAbstractItemModel
|
||||
{
|
||||
public:
|
||||
QAbstractQVariantTreeDataModel(QObject* parent)
|
||||
: QAbstractItemModel(parent) { }
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex& child) const override;
|
||||
bool hasChildren(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
||||
protected:
|
||||
struct Folder;
|
||||
|
||||
struct Item
|
||||
{
|
||||
Item()
|
||||
: m_parent(0) { }
|
||||
|
||||
QMap<int, QVariant> m_data;
|
||||
Folder* m_parent;
|
||||
|
||||
virtual ~Item() = default;
|
||||
virtual const Folder* asFolder() const { return 0; } // need this as we don't have RTTI
|
||||
};
|
||||
|
||||
struct Folder
|
||||
: public Item
|
||||
{
|
||||
Folder(const QString& name)
|
||||
{
|
||||
m_data.insert(Qt::DisplayRole, name);
|
||||
}
|
||||
std::vector < std::shared_ptr<Item> > m_children;
|
||||
const Folder* asFolder() const override { return this; } // need this as we don't have RTTI
|
||||
|
||||
int row(Item* item) const
|
||||
{
|
||||
for (int i = 0; i < m_children.size(); ++i)
|
||||
{
|
||||
if (m_children[i].get() == item)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void addChild(std::shared_ptr<Item> item)
|
||||
{
|
||||
item->m_parent = this;
|
||||
m_children.push_back(item);
|
||||
}
|
||||
};
|
||||
|
||||
Item* itemFromIndex(const QModelIndex& index) const;
|
||||
QModelIndex indexFromItem(Item* item, int col = 0) const;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
std::shared_ptr<Folder> m_root;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
#endif // QABSTRACTQVARIANTTREEDATAMODEL_H
|
||||
@@ -1,309 +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 "QParentWndWidget.h"
|
||||
#include <QEvent>
|
||||
#include <QGuiApplication>
|
||||
#include <QApplication>
|
||||
#include <QFocusEvent>
|
||||
|
||||
#include "QParentWndWidget.h"
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QWindow>
|
||||
#endif
|
||||
static HWND FindTopmostWindow(HWND child, bool considerWsChild)
|
||||
{
|
||||
if (child == GetDesktopWindow())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
HWND current = child;
|
||||
while (GetParent(current) != 0)
|
||||
{
|
||||
if (considerWsChild && (GetWindowLongW(current, GWL_STYLE) & WS_CHILD) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
current = GetParent(current);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
QParentWndWidget::QParentWndWidget(HWND parent)
|
||||
: m_parent(parent)
|
||||
, m_previousFocus(0)
|
||||
, m_modalityRoot(0)
|
||||
, m_parentToCenterOn(0)
|
||||
{
|
||||
if (m_parent)
|
||||
{
|
||||
SetWindowLongA((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP);
|
||||
|
||||
#if QT_VERSION >= 0x50000
|
||||
QWindow* window = windowHandle();
|
||||
window->setProperty("_q_embedded_native_parent_handle", (WId)m_parent);
|
||||
SetParent((HWND)winId(), m_parent);
|
||||
window->setFlags(Qt::FramelessWindowHint);
|
||||
#else
|
||||
SetParent((HWND)winId(), m_parent);
|
||||
#endif
|
||||
QEvent e(QEvent::EmbeddingControl);
|
||||
QApplication::sendEvent(this, &e);
|
||||
}
|
||||
|
||||
m_parentToCenterOn = FindTopmostWindow(m_parent, true);
|
||||
m_modalityRoot = FindTopmostWindow(m_parent, false);
|
||||
}
|
||||
|
||||
void QParentWndWidget::childEvent(QChildEvent* ev)
|
||||
{
|
||||
QObject* child = ev->child();
|
||||
if (child->isWidgetType())
|
||||
{
|
||||
if (ev->added())
|
||||
{
|
||||
if (child->isWidgetType())
|
||||
{
|
||||
child->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
else if (ev->removed() && m_parentWasDisabled)
|
||||
{
|
||||
m_parentWasDisabled = false;
|
||||
EnableWindow(m_modalityRoot, true);
|
||||
child->removeEventFilter(this);
|
||||
}
|
||||
}
|
||||
QWidget::childEvent(ev);
|
||||
}
|
||||
|
||||
void QParentWndWidget::show()
|
||||
{
|
||||
if (!m_previousFocus)
|
||||
{
|
||||
m_previousFocus = ::GetFocus();
|
||||
}
|
||||
if (!m_previousFocus)
|
||||
{
|
||||
m_previousFocus = parentWindow();
|
||||
}
|
||||
|
||||
QWidget::show();
|
||||
}
|
||||
void QParentWndWidget::hide()
|
||||
{
|
||||
QWidget::hide();
|
||||
}
|
||||
|
||||
void QParentWndWidget::center()
|
||||
{
|
||||
const QWidget* child = findChild<QWidget*>();
|
||||
|
||||
RECT rect;
|
||||
GetWindowRect(m_parentToCenterOn, &rect);
|
||||
setGeometry((rect.right - rect.left) / 2 + rect.left,
|
||||
(rect.bottom - rect.top) / 2 + rect.top, 0, 0);
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x50000
|
||||
bool QParentWndWidget::nativeEvent(const QByteArray&, void* message, long* result)
|
||||
#else
|
||||
bool QParentWndWidget::winEvent(MSG* msg, long* result)
|
||||
#endif
|
||||
{
|
||||
#if QT_VERSION >= 0x50000
|
||||
MSG* msg = (MSG*)message;
|
||||
#endif
|
||||
if (msg->message == WM_SETFOCUS)
|
||||
{
|
||||
Qt::FocusReason reason;
|
||||
if (::GetKeyState(VK_LBUTTON) < 0 ||
|
||||
::GetKeyState(VK_RBUTTON) < 0)
|
||||
{
|
||||
reason = Qt::MouseFocusReason;
|
||||
}
|
||||
else if (::GetKeyState(VK_SHIFT) < 0)
|
||||
{
|
||||
reason = Qt::BacktabFocusReason;
|
||||
}
|
||||
else
|
||||
{
|
||||
reason = Qt::TabFocusReason;
|
||||
}
|
||||
QFocusEvent ev(QEvent::FocusIn, reason);
|
||||
QApplication::sendEvent(this, &ev);
|
||||
}
|
||||
if (msg->message == WM_GETDLGCODE)
|
||||
{
|
||||
*result = DLGC_WANTARROWS | DLGC_WANTTAB;
|
||||
return(true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QParentWndWidget::eventFilter(QObject* obj, QEvent* ev)
|
||||
{
|
||||
QWidget* widget = (QWidget*)obj;
|
||||
switch (ev->type())
|
||||
{
|
||||
case QEvent::WindowDeactivate:
|
||||
{
|
||||
if (widget->isModal() && isHidden())
|
||||
{
|
||||
BringWindowToTop(m_parent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::Show:
|
||||
{
|
||||
if (widget->isWindow())
|
||||
{
|
||||
if (!m_previousFocus)
|
||||
{
|
||||
m_previousFocus = ::GetFocus();
|
||||
}
|
||||
if (!m_previousFocus)
|
||||
{
|
||||
m_previousFocus = parentWindow();
|
||||
}
|
||||
hide();
|
||||
if (widget->isModal() && !m_parentWasDisabled)
|
||||
{
|
||||
EnableWindow(m_modalityRoot, false);
|
||||
m_parentWasDisabled = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::Hide:
|
||||
{
|
||||
if (m_parentWasDisabled)
|
||||
{
|
||||
EnableWindow(m_modalityRoot, true);
|
||||
m_parentWasDisabled = false;
|
||||
}
|
||||
if (m_previousFocus)
|
||||
{
|
||||
::SetFocus(m_previousFocus);
|
||||
}
|
||||
else
|
||||
{
|
||||
::SetFocus(parentWindow());
|
||||
}
|
||||
if (widget->testAttribute(Qt::WA_DeleteOnClose) && widget->isWindow())
|
||||
{
|
||||
deleteLater();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::Close:
|
||||
{
|
||||
::SetActiveWindow(m_parent);
|
||||
if (widget->testAttribute(Qt::WA_DeleteOnClose))
|
||||
{
|
||||
deleteLater();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
;
|
||||
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
void QParentWndWidget::focusInEvent(QFocusEvent* ev)
|
||||
{
|
||||
QWidget* candidate = this;
|
||||
|
||||
if (ev->reason() == Qt::TabFocusReason || ev->reason() == Qt::BacktabFocusReason)
|
||||
{
|
||||
while (candidate && (candidate->focusPolicy() & Qt::TabFocus) == 0)
|
||||
{
|
||||
candidate = candidate->nextInFocusChain();
|
||||
if (candidate == this)
|
||||
{
|
||||
candidate = 0;
|
||||
}
|
||||
}
|
||||
if (candidate)
|
||||
{
|
||||
candidate->setFocus(ev->reason());
|
||||
candidate->setAttribute(Qt::WA_KeyboardFocusChange);
|
||||
candidate->window()->setAttribute(Qt::WA_KeyboardFocusChange);
|
||||
if (ev->reason() == Qt::BacktabFocusReason)
|
||||
{
|
||||
QWidget::focusNextPrevChild(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QParentWndWidget::focusNextPrevChild(bool next)
|
||||
{
|
||||
QWidget* current = focusWidget();
|
||||
if (next)
|
||||
{
|
||||
QWidget* nextFocus = current;
|
||||
while (true)
|
||||
{
|
||||
nextFocus = nextFocus->nextInFocusChain();
|
||||
if (nextFocus->isWindow())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (nextFocus->focusPolicy() & Qt::TabFocus)
|
||||
{
|
||||
return QWidget::focusNextPrevChild(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!current->isWindow())
|
||||
{
|
||||
QWidget* nextFocus = current->nextInFocusChain();
|
||||
QWidget* prevFocus = 0;
|
||||
QWidget* topLevel = 0;
|
||||
while (nextFocus != current)
|
||||
{
|
||||
if ((nextFocus->focusPolicy() & Qt::TabFocus) != 0)
|
||||
{
|
||||
prevFocus = nextFocus;
|
||||
topLevel = 0;
|
||||
}
|
||||
else if (nextFocus->isWindow())
|
||||
{
|
||||
topLevel = nextFocus;
|
||||
}
|
||||
nextFocus = nextFocus->nextInFocusChain();
|
||||
}
|
||||
|
||||
if (!topLevel)
|
||||
{
|
||||
return QWidget::focusNextPrevChild(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::SetFocus(m_parent);
|
||||
return true;
|
||||
}
|
||||
|
||||
#include <moc_QParentWndWidget.cpp>
|
||||
@@ -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
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPARENTWNDWIDGET_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPARENTWNDWIDGET_H
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
|
||||
#include "EditorCommonAPI.h"
|
||||
#endif
|
||||
|
||||
// QParentWndWidget can be used to show Qt popup windows/dialogs on top on
|
||||
// Win32/MFC windows.
|
||||
//
|
||||
// Example of usage:
|
||||
// QParentWndWidget parent(parentHwnd);
|
||||
//
|
||||
// QDialog dialog(parent);
|
||||
// dialog.exec(...);
|
||||
class EDITOR_COMMON_API QParentWndWidget
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QParentWndWidget(HWND parent);
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
void center();
|
||||
|
||||
HWND parentWindow() const { return m_parent; }
|
||||
|
||||
protected:
|
||||
void childEvent(QChildEvent* e) override;
|
||||
void focusInEvent(QFocusEvent* ev) override;
|
||||
bool focusNextPrevChild(bool next) override;
|
||||
|
||||
bool eventFilter(QObject* o, QEvent* e) override;
|
||||
#if QT_VERSION >= 0x50000
|
||||
bool nativeEvent(const QByteArray&, void* message, long*);
|
||||
#else
|
||||
bool winEvent(MSG* msg, long*);
|
||||
#endif
|
||||
|
||||
private:
|
||||
HWND m_parent;
|
||||
HWND m_parentToCenterOn;
|
||||
HWND m_modalityRoot;
|
||||
|
||||
HWND m_previousFocus;
|
||||
|
||||
bool m_parentWasDisabled;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPARENTWNDWIDGET_H
|
||||
@@ -1,49 +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 "EditorCommonAPI.h"
|
||||
#include "Controls/PropertyCtrl.h"
|
||||
#include <QtWinMigrate/qwinhost.h>
|
||||
|
||||
template<class T>
|
||||
class TemplatePropertyCtrl
|
||||
: public QWinHost
|
||||
{
|
||||
public:
|
||||
TemplatePropertyCtrl(QWidget* parent)
|
||||
: QWinHost(parent) { }
|
||||
|
||||
T m_props;
|
||||
protected:
|
||||
virtual HWND createWindow(HWND parent, HINSTANCE instance)
|
||||
{
|
||||
CWnd* parentWindow = CWnd::FromHandle(parent);
|
||||
m_props.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 100, 100), parentWindow /*, IDC_GRAPH_PROPERTIES*/);
|
||||
m_props.ModifyStyleEx(0, WS_EX_CLIENTEDGE);
|
||||
m_props.SetParent(parentWindow);
|
||||
return m_props.m_hWnd;
|
||||
}
|
||||
};
|
||||
|
||||
class QPropertyCtrl
|
||||
: public TemplatePropertyCtrl <CPropertyCtrl>
|
||||
{
|
||||
public:
|
||||
QPropertyCtrl(QWidget* parent)
|
||||
: TemplatePropertyCtrl<CPropertyCtrl>(parent)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include "Color.h"
|
||||
#include "Serialization/IArchive.h"
|
||||
#include <math.h>
|
||||
#include "MathUtils.h"
|
||||
|
||||
|
||||
// HSV
|
||||
// h=0..360, s=0..1, v=0..1
|
||||
inline void HSVtoRGB(float h,float s,float v,
|
||||
float& r,float& g,float& b)
|
||||
{
|
||||
const float min=1e-5f;
|
||||
int i;
|
||||
float f,m,n,k;
|
||||
|
||||
if(s<min){
|
||||
r=g=b=v;
|
||||
}
|
||||
else {
|
||||
if(h>=360.0f)
|
||||
h=0;
|
||||
else
|
||||
h=h/60.0f;
|
||||
|
||||
i=xround(floor(h));
|
||||
f=h-i;
|
||||
m=v*(1-s);
|
||||
n=v*(1-s*f);
|
||||
k=v*(1-s*(1-f));
|
||||
|
||||
switch(i){
|
||||
case 0:
|
||||
r=v; g=k; b=m;
|
||||
break;
|
||||
case 1:
|
||||
r=n; g=v; b=m;
|
||||
break;
|
||||
case 2:
|
||||
r=m; g=v; b=k;
|
||||
break;
|
||||
case 3:
|
||||
r=m; g=n; b=v;
|
||||
break;
|
||||
case 4:
|
||||
r=k; g=m; b=v;
|
||||
break;
|
||||
case 5:
|
||||
r=v; g=m; b=n;
|
||||
break;
|
||||
default:
|
||||
YASLI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
YASLI_ASSERT(r>=0 && r<=1);
|
||||
YASLI_ASSERT(g>=0 && g<=1);
|
||||
YASLI_ASSERT(b>=0 && b<=1);
|
||||
}
|
||||
|
||||
void Color::setHSV(float h,float s,float v, unsigned char alpha)
|
||||
{
|
||||
float rf,gf,bf;
|
||||
HSVtoRGB(h,s,v, rf,gf,bf);
|
||||
r = xround(rf*255);
|
||||
g = xround(gf*255);
|
||||
b = xround(bf*255);
|
||||
a = alpha;
|
||||
}
|
||||
|
||||
|
||||
void Color::toHSV(float& h,float& s,float& v)
|
||||
{
|
||||
float rf = r/255.f;
|
||||
float gf = g/255.f;
|
||||
float bf = b/255.f;
|
||||
v = max(max(rf,gf),bf);
|
||||
float temp=min(min(rf,gf),bf);
|
||||
if(v==0)
|
||||
s=0;
|
||||
else
|
||||
s=(v-temp)/v;
|
||||
|
||||
if(s==0)
|
||||
h=0;
|
||||
else {
|
||||
float Cr=(v-rf)/(v-temp);
|
||||
float Cg=(v-gf)/(v-temp);
|
||||
float Cb=(v-bf)/(v-temp);
|
||||
|
||||
if(rf==v) {
|
||||
h=Cb-Cg;
|
||||
}
|
||||
else if(gf==v) {
|
||||
h=2+Cr-Cb;
|
||||
}
|
||||
else if(bf==v) {
|
||||
h=4+Cg-Cr;
|
||||
}
|
||||
|
||||
h=60*h;
|
||||
if(h<0)h+=360;
|
||||
}
|
||||
}
|
||||
|
||||
void Color::Serialize(Serialization::IArchive& ar)
|
||||
{
|
||||
ar(r, "", "^R");
|
||||
ar(g, "", "^G");
|
||||
ar(b, "", "^B");
|
||||
ar(a, "", "^A");
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_COLOR_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_COLOR_H
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace Serialization {
|
||||
class IArchive;
|
||||
}
|
||||
|
||||
struct Color
|
||||
{
|
||||
unsigned char b, g, r, a;
|
||||
|
||||
Color() : r(255), g(255), b(255), a(255) { }
|
||||
Color(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a = 255) { r=_r; g=_g; b=_b; a=_a; }
|
||||
explicit Color(unsigned long _argb) { argb() = _argb; }
|
||||
void set(int rc,int gc,int bc,int ac = 255) { r=rc; g=gc; b=bc; a=ac; }
|
||||
|
||||
Color& setGDI(unsigned long color) {
|
||||
b = (unsigned char)(color >> 16);
|
||||
g = (unsigned char)(color >> 8);
|
||||
r = (unsigned char)(color);
|
||||
a = 255;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void setHSV(float h,float s,float v, unsigned char alpha = 255);
|
||||
void toHSV(float& h,float& s, float& v);
|
||||
|
||||
Color& operator*= (float f) { r=int(r*f); g=int(g*f); b=int(b*f); a=int(a*f); return *this; }
|
||||
Color& operator+= (Color &p) { r+=p.r; g+=p.g; b+=p.b; a+=p.a; return *this; }
|
||||
Color& operator-= (Color &p) { r-=p.r; g-=p.g; b-=p.b; a-=p.a; return *this; }
|
||||
Color operator+ (Color &p) { return Color(r+p.r,g+p.g,b+p.b,a+p.a); }
|
||||
Color operator- (Color &p) { return Color(r-p.r,g-p.g,b-p.b,a-p.a); }
|
||||
Color operator* (float f) const { return Color(int(r*f), int(g*f), int(b*f), int(a*f)); }
|
||||
Color operator* (int f) const { return Color(r*f,g*f,b*f,a*f); }
|
||||
Color operator/ (int f) const { if(f!=0) f=(1<<16)/f; else f=1<<16; return Color((r*f)>>16,(g*f)>>16,(b*f)>>16,(a*f)>>16); }
|
||||
|
||||
bool operator==(const Color& rhs) const { return argb() == rhs.argb(); }
|
||||
bool operator!=(const Color& rhs) const { return argb() != rhs.argb(); }
|
||||
|
||||
unsigned long argb() const { return *reinterpret_cast<const unsigned long*>(this); }
|
||||
unsigned long& argb() { return *reinterpret_cast<unsigned long*>(this); }
|
||||
unsigned long rgb() const { return r | g << 8 | b << 16; }
|
||||
unsigned long rgba() const { return r | g << 8 | b << 16 | a << 24; }
|
||||
unsigned char& operator[](int i) { return ((unsigned char*)this)[i];}
|
||||
Color interpolate(const Color &v, float f) const
|
||||
{
|
||||
return Color(int(r+int(v.r-r)*f),
|
||||
int(g+int(v.g-g)*f),
|
||||
int(b+int(v.b-b)*f),
|
||||
int(a+(v.a-a)*f));
|
||||
}
|
||||
void Serialize(Serialization::IArchive& ar);
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_COLOR_H
|
||||
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include "ConstStringList.h"
|
||||
#include <algorithm>
|
||||
#include "Serialization/STL.h"
|
||||
#include "Serialization/IArchive.h"
|
||||
#include "Serialization/STLImpl.h"
|
||||
|
||||
ConstStringList globalConstStringList;
|
||||
|
||||
const char* ConstStringList::findOrAdd(const char* string)
|
||||
{
|
||||
// TODO: try sorted vector of const char*
|
||||
Strings::iterator it = std::find(strings_.begin(), strings_.end(), string);
|
||||
if (it == strings_.end()) {
|
||||
strings_.push_back(string);
|
||||
return strings_.back().c_str();
|
||||
}
|
||||
else {
|
||||
return it->c_str();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ConstStringWrapper::ConstStringWrapper(ConstStringList* list, const char*& string)
|
||||
: list_(list ? list : &globalConstStringList)
|
||||
, string_(string)
|
||||
{
|
||||
YASLI_ASSERT(string_);
|
||||
}
|
||||
|
||||
using Serialization::string;
|
||||
|
||||
bool Serialize(Serialization::IArchive& ar, ConstStringWrapper& val, const char* name, const char* label)
|
||||
{
|
||||
if (ar.IsOutput()) {
|
||||
YASLI_ASSERT(val.string_);
|
||||
string out = val.string_;
|
||||
return ar(out, name, label);
|
||||
}
|
||||
else {
|
||||
string in;
|
||||
bool result = ar(in, name, label);
|
||||
|
||||
val.string_ = val.list_->findOrAdd(in.c_str());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONSTSTRINGLIST_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONSTSTRINGLIST_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include "EditorCommonAPI.h"
|
||||
|
||||
class ConstStringWrapper;
|
||||
|
||||
namespace Serialization { class IArchive; }
|
||||
|
||||
bool Serialize(Serialization::IArchive& ar, ConstStringWrapper &wrapper, const char* name, const char* label);
|
||||
|
||||
class ConstStringList{
|
||||
public:
|
||||
const char* findOrAdd(const char* string);
|
||||
protected:
|
||||
typedef std::list<std::string> Strings;
|
||||
Strings strings_;
|
||||
};
|
||||
|
||||
class ConstStringWrapper {
|
||||
public:
|
||||
ConstStringWrapper(ConstStringList* list, const char*& string);
|
||||
protected:
|
||||
ConstStringList* list_;
|
||||
const char*& string_;
|
||||
friend bool ::Serialize(Serialization::IArchive& ar, ConstStringWrapper &wrapper, const char* name, const char* label);
|
||||
};
|
||||
|
||||
extern ConstStringList globalConstStringList;
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONSTSTRINGLIST_H
|
||||
@@ -1,76 +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_EDITORCOMMON_QPROPERTYTREE_CONTEXTLIST_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONTEXTLIST_H
|
||||
#pragma once
|
||||
|
||||
#include <Serialization/IArchive.h>
|
||||
|
||||
namespace Serialization
|
||||
{
|
||||
class CContextList
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
void Update(T* contextObject)
|
||||
{
|
||||
for (size_t i = 0; i < links_.size(); ++i)
|
||||
{
|
||||
if (links_[i]->type == TypeID::get<T>())
|
||||
{
|
||||
links_[i]->contextObject = (void*)contextObject;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SContextLink* newLink = new SContextLink;
|
||||
newLink->type = TypeID::get<T>();
|
||||
newLink->outer = links_.empty() ? connectedList_ : links_.back();
|
||||
newLink->contextObject = (void*)contextObject;
|
||||
tail_.outer = newLink;
|
||||
links_.push_back(newLink);
|
||||
}
|
||||
|
||||
CContextList()
|
||||
{
|
||||
tail_.outer = 0;
|
||||
tail_.contextObject = 0;
|
||||
connectedList_ = 0;
|
||||
}
|
||||
|
||||
explicit CContextList(SContextLink* connectedList)
|
||||
{
|
||||
tail_.outer = 0;
|
||||
tail_.contextObject = 0;
|
||||
connectedList_ = connectedList;
|
||||
}
|
||||
|
||||
~CContextList()
|
||||
{
|
||||
for (size_t i = 0; i < links_.size(); ++i)
|
||||
{
|
||||
delete links_[i];
|
||||
}
|
||||
links_.clear();
|
||||
}
|
||||
|
||||
SContextLink* Tail() { return &tail_; }
|
||||
private:
|
||||
SContextLink tail_;
|
||||
std::vector<SContextLink*> links_;
|
||||
SContextLink* connectedList_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONTEXTLIST_H
|
||||
@@ -1,156 +0,0 @@
|
||||
/**
|
||||
* yasli - Serialization Library.
|
||||
* Copyright (C) 2007-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_FACTORY_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_FACTORY_H
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include "Serialization/Assert.h"
|
||||
|
||||
template<class _Key, class _Product, class _KeyPred = std::less<_Key>>
|
||||
class Factory {
|
||||
public:
|
||||
typedef AZStd::map<_Key, AZStd::function<_Product *()>, _KeyPred, AZ::StdLegacyAllocator> Creators;
|
||||
typedef _Product* (*ProductConstructionFunction)(void);
|
||||
|
||||
Factory() {}
|
||||
|
||||
struct Creator
|
||||
{
|
||||
Creator()
|
||||
{
|
||||
if (s_creatorsHead)
|
||||
{
|
||||
m_next = s_creatorsHead;
|
||||
}
|
||||
s_creatorsHead = this;
|
||||
}
|
||||
|
||||
Creator(Factory& factory, _Key key, ProductConstructionFunction construction_function_)
|
||||
: Creator()
|
||||
{
|
||||
// capture key and construction_function_ by value so the lazy load won't try to access possibly deleted data
|
||||
Register = [&, key, construction_function_]()
|
||||
{
|
||||
factory.add(key, construction_function_);
|
||||
};
|
||||
}
|
||||
|
||||
Creator(_Key key, ProductConstructionFunction construction_function_)
|
||||
: Creator()
|
||||
{
|
||||
// capture key and construction_function_ by value so the lazy load won't try to access possibly deleted data
|
||||
Register = [&, key, construction_function_]()
|
||||
{
|
||||
Factory::the().add(key, construction_function_);
|
||||
};
|
||||
}
|
||||
|
||||
AZStd::function<void()> Register;
|
||||
Creator* m_next = nullptr;
|
||||
};
|
||||
|
||||
void add(const _Key& key, AZStd::function<_Product *()> creator) {
|
||||
YASLI_ASSERT(creators_.find(key) == creators_.end());
|
||||
YASLI_ASSERT(creator);
|
||||
creators_[key] = creator;
|
||||
}
|
||||
|
||||
void remove(const _Key& key) {
|
||||
auto& entry = creators_.find(key);
|
||||
if (entry != creators_.end()) {
|
||||
creators_.erase(entry);
|
||||
}
|
||||
}
|
||||
|
||||
_Product* create(const _Key& key) const
|
||||
{
|
||||
lazyRegisterCreators();
|
||||
typename Creators::const_iterator it = creators_.find(key);
|
||||
if (it != creators_.end()) {
|
||||
return it->second();
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
lazyRegisterCreators();
|
||||
return creators_.size();
|
||||
}
|
||||
|
||||
_Product* createByIndex(int index) const
|
||||
{
|
||||
lazyRegisterCreators();
|
||||
YASLI_ASSERT(index >= 0 && index < creators_.size());
|
||||
typename Creators::const_iterator it = creators_.begin();
|
||||
std::advance(it, index);
|
||||
return it->second();
|
||||
}
|
||||
|
||||
|
||||
const Creators& creators() const
|
||||
{
|
||||
lazyRegisterCreators();
|
||||
return creators_;
|
||||
}
|
||||
|
||||
static Factory& the()
|
||||
{
|
||||
static Factory* genericFactory = nullptr;
|
||||
static AZStd::aligned_storage_for_t<Factory> s_storage;
|
||||
if (!genericFactory)
|
||||
{
|
||||
genericFactory = new(&s_storage) Factory();
|
||||
}
|
||||
return *genericFactory;
|
||||
}
|
||||
|
||||
private:
|
||||
void lazyRegisterCreators() const
|
||||
{
|
||||
if (s_creatorsHead)
|
||||
{
|
||||
Creator* creator = s_creatorsHead;
|
||||
while (creator)
|
||||
{
|
||||
creator->Register();
|
||||
creator = creator->m_next;
|
||||
}
|
||||
s_creatorsHead = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Creators creators_;
|
||||
|
||||
static Creator* s_creatorsHead;
|
||||
};
|
||||
|
||||
template <class _Key, class _Product, class _KeyPred>
|
||||
typename Factory<_Key, _Product, _KeyPred>::Creator* Factory<_Key, _Product, _KeyPred>::s_creatorsHead = nullptr;
|
||||
|
||||
#define REGISTER_IN_FACTORY(factory, key, product, construction_function) \
|
||||
static factory::Creator factory##product##Creator(key, construction_function);
|
||||
|
||||
#define REGISTER_IN_FACTORY_INSTANCE(factory, factoryType, key, product) \
|
||||
static factoryType::Creator<product> factoryType##product##Creator(factory, key);
|
||||
|
||||
#define DECLARE_SEGMENT(fileName) int dataSegment##fileName;
|
||||
|
||||
#define FORCE_SEGMENT(fileName) \
|
||||
extern int dataSegment##fileName; \
|
||||
int* dataSegmentPtr##fileName = &dataSegment##fileName;
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_FACTORY_H
|
||||
@@ -1,54 +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_EDITORCOMMON_QPROPERTYTREE_MATHUTILS_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_MATHUTILS_H
|
||||
#pragma once
|
||||
|
||||
inline int xround(float v)
|
||||
{
|
||||
return int(v + 0.5f);
|
||||
}
|
||||
|
||||
inline int min(int a, int b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
inline int max(int a, int b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
inline float min(float a, float b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
inline float max(float a, float b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
inline float clamp(float value, float min, float max)
|
||||
{
|
||||
return ::min(::max(min, value), max);
|
||||
}
|
||||
|
||||
inline int clamp(int value, int min, int max)
|
||||
{
|
||||
return ::min(::max(min, value), max);
|
||||
}
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_MATHUTILS_H
|
||||
@@ -1,466 +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.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include "PropertyDrawContext.h"
|
||||
#include <memory>
|
||||
#include "QPropertyTree.h"
|
||||
#include "Serialization/Decorators/IconXPM.h"
|
||||
#include "Unicode.h"
|
||||
#include <QApplication>
|
||||
#include <QStyleOption>
|
||||
#include <QPainter>
|
||||
#include <QBitmap>
|
||||
|
||||
// required to create context for the draw calls
|
||||
#include <QPushButton>
|
||||
#include <QCheckBox>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# define _stricmp strcasecmp
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
QColor interpolateColor(const QColor& a, const QColor& b, float k);
|
||||
|
||||
IconXPMCache::~IconXPMCache()
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
|
||||
void IconXPMCache::flush()
|
||||
{
|
||||
IconToBitmap::iterator it;
|
||||
for (it = iconToImageMap_.begin(); it != iconToImageMap_.end(); ++it)
|
||||
delete it->second.bitmap;
|
||||
iconToImageMap_.clear();
|
||||
}
|
||||
|
||||
struct RGBAImage
|
||||
{
|
||||
int width_;
|
||||
int height_;
|
||||
std::vector<Color> pixels_;
|
||||
|
||||
RGBAImage() : width_(0), height_(0) {}
|
||||
};
|
||||
|
||||
bool IconXPMCache::parseXPM(RGBAImage* out, const Serialization::IconXPM& icon)
|
||||
{
|
||||
if (icon.lineCount < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse values
|
||||
std::vector<Color> pixels;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int charsPerPixel = 0;
|
||||
int colorCount = 0;
|
||||
int hotSpotX = -1;
|
||||
int hotSpotY = -1;
|
||||
|
||||
int scanResult = azsscanf(icon.source[0], "%d %d %d %d %d %d", &width, &height, &colorCount, &charsPerPixel, &hotSpotX, &hotSpotY);
|
||||
if (scanResult != 4 && scanResult != 6)
|
||||
return false;
|
||||
|
||||
if (charsPerPixel > 4)
|
||||
return false;
|
||||
|
||||
if (icon.lineCount != 1 + colorCount + height) {
|
||||
YASLI_ASSERT(0 && "Wrong line count");
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse colors
|
||||
std::vector<std::pair<int, Color> > colors;
|
||||
colors.resize(colorCount);
|
||||
|
||||
for (int colorIndex = 0; colorIndex < colorCount; ++colorIndex) {
|
||||
const char* p = icon.source[colorIndex + 1];
|
||||
int code = 0;
|
||||
for (int charIndex = 0; charIndex < charsPerPixel; ++charIndex) {
|
||||
if (*p == '\0')
|
||||
return false;
|
||||
code = (code << 8) | *p;
|
||||
++p;
|
||||
}
|
||||
colors[colorIndex].first = code;
|
||||
|
||||
while (*p == '\t' || *p == ' ')
|
||||
++p;
|
||||
|
||||
if (*p == '\0')
|
||||
return false;
|
||||
|
||||
if (*p != 'c' && *p != 'g')
|
||||
return false;
|
||||
++p;
|
||||
|
||||
while (*p == '\t' || *p == ' ')
|
||||
++p;
|
||||
|
||||
if (*p == '\0')
|
||||
return false;
|
||||
|
||||
if (*p == '#') {
|
||||
++p;
|
||||
if (strlen(p) == 6) {
|
||||
int colorCode;
|
||||
if (azsscanf(p, "%x", &colorCode) != 1)
|
||||
return false;
|
||||
Color color((colorCode & 0xff0000) >> 16,
|
||||
(colorCode & 0xff00) >> 8,
|
||||
(colorCode & 0xff),
|
||||
255);
|
||||
colors[colorIndex].second = color;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (_stricmp(p, "None") == 0)
|
||||
colors[colorIndex].second = Color(0, 0, 0, 0);
|
||||
else if (_stricmp(p, "Black") == 0)
|
||||
colors[colorIndex].second = Color(0, 0, 0, 255);
|
||||
else {
|
||||
// unknown color
|
||||
colors[colorIndex].second = Color(255, 0, 0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse pixels
|
||||
pixels.resize(width * height);
|
||||
int pi = 0;
|
||||
for (int y = 0; y < height; ++y) {
|
||||
const char* p = icon.source[1 + colorCount + y];
|
||||
if (strlen(p) != width * charsPerPixel)
|
||||
return false;
|
||||
|
||||
for (int x = 0; x < width; ++x) {
|
||||
int code = 0;
|
||||
for (int i = 0; i < charsPerPixel; ++i) {
|
||||
code = (code << 8) | *p;
|
||||
++p;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size_t(colorCount); ++i)
|
||||
if (colors[i].first == code)
|
||||
pixels[pi] = colors[i].second;
|
||||
++pi;
|
||||
}
|
||||
}
|
||||
|
||||
out->pixels_.swap(pixels);
|
||||
out->width_ = width;
|
||||
out->height_ = height;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QImage* IconXPMCache::getImageForIcon(const Serialization::IconXPM& icon)
|
||||
{
|
||||
IconToBitmap::iterator it = iconToImageMap_.find(icon.source);
|
||||
if (it != iconToImageMap_.end())
|
||||
return it->second.bitmap;
|
||||
|
||||
RGBAImage image;
|
||||
if (!parseXPM(&image, icon))
|
||||
return 0;
|
||||
|
||||
BitmapCache& cache = iconToImageMap_[icon.source];
|
||||
cache.pixels.swap(image.pixels_);
|
||||
cache.bitmap = new QImage((unsigned char*)&cache.pixels[0], image.width_, image.height_, QImage::Format_ARGB32);
|
||||
return cache.bitmap;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void drawRoundRectangle(QPainter& p, const QRect &_r, unsigned int color, int radius, [[maybe_unused]] int width)
|
||||
{
|
||||
QRect r = _r;
|
||||
int dia = 2 * radius;
|
||||
|
||||
p.setPen(QColor(color));
|
||||
p.drawRoundedRect(r, dia, dia);
|
||||
}
|
||||
|
||||
void fillRoundRectangle(QPainter& p, const QBrush& brush, const QRect& _r, const QColor& border, int radius)
|
||||
{
|
||||
bool wasAntialisingSet = p.renderHints().testFlag(QPainter::Antialiasing);
|
||||
p.setRenderHints(QPainter::Antialiasing, true);
|
||||
|
||||
p.setBrush(brush);
|
||||
QPen pen(QBrush(border), 1.0, Qt::SolidLine);
|
||||
p.setPen(pen);
|
||||
QRectF adjustedRect = _r;
|
||||
adjustedRect.adjust(0.5f, 0.5f, -0.5f, -0.5f);
|
||||
p.drawRoundedRect(adjustedRect, radius, radius);
|
||||
|
||||
p.setRenderHints(QPainter::Antialiasing, wasAntialisingSet);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void PropertyDrawContext::drawIcon(const QRect& rect, const Serialization::IconXPM& icon) const
|
||||
{
|
||||
QImage* image = tree->_iconCache()->getImageForIcon(icon);
|
||||
if (!image)
|
||||
return;
|
||||
int x = rect.left() + (rect.width() - image->width()) / 2;
|
||||
int y = rect.top() + (rect.height() - image->height()) / 2;
|
||||
painter->drawImage(x, y, *image);
|
||||
}
|
||||
|
||||
void PropertyDrawContext::drawCheck(const QRect& rect, bool disabled, CheckState checked) const
|
||||
{
|
||||
QStyleOptionButton option;
|
||||
if (!disabled)
|
||||
option.state |= QStyle::State_Enabled;
|
||||
else {
|
||||
option.state |= QStyle::State_ReadOnly;
|
||||
option.palette.setCurrentColorGroup(QPalette::Disabled);
|
||||
}
|
||||
if (checked == CHECK_SET)
|
||||
option.state |= QStyle::State_On;
|
||||
else if (checked == CHECK_IN_BETWEEN)
|
||||
option.state |= QStyle::State_NoChange;
|
||||
else
|
||||
option.state |= QStyle::State_Off;
|
||||
|
||||
// create a widget so that the style sheet has context for its draw calls
|
||||
QCheckBox forContext;
|
||||
QSize checkboxSize = tree->style()->subElementRect(QStyle::SE_CheckBoxIndicator, &option, &forContext).size();
|
||||
option.rect = QRect(rect.left(), rect.center().y() - checkboxSize.height() / 2, checkboxSize.width(), checkboxSize.height());
|
||||
tree->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter, &forContext);
|
||||
if (disabled) {
|
||||
// With Fusion theme difference between disabled and enabled checkbox is very subtle, let's amplify it
|
||||
QColor readOnlyOverlay = tree->backgroundColor();
|
||||
readOnlyOverlay.setAlpha(128);
|
||||
painter->fillRect(option.rect, QBrush(readOnlyOverlay));
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyDrawContext::drawButton(const QRect& rect, const wchar_t* text, int buttonFlags, const QFont* font, const Color* colorOverride) const
|
||||
{
|
||||
QPushButton button;
|
||||
button.ensurePolished();
|
||||
QStyleOptionButton option;
|
||||
option.initFrom(&button);
|
||||
if (buttonFlags & BUTTON_DISABLED) {
|
||||
option.state |= QStyle::State_ReadOnly;
|
||||
option.palette.setCurrentColorGroup(QPalette::Disabled);
|
||||
}
|
||||
else
|
||||
option.state |= QStyle::State_Enabled;
|
||||
if (buttonFlags & BUTTON_PRESSED) {
|
||||
option.state |= QStyle::State_On;
|
||||
option.state |= QStyle::State_Sunken;
|
||||
}
|
||||
else
|
||||
option.state |= QStyle::State_Raised;
|
||||
|
||||
if (buttonFlags & BUTTON_FOCUSED)
|
||||
option.state |= QStyle::State_HasFocus;
|
||||
option.rect = rect.adjusted(0, 0, -1, -1);
|
||||
|
||||
QWidget* pseudoDrawWidget = &button;
|
||||
|
||||
if (colorOverride) {
|
||||
QPalette& palette = option.palette;
|
||||
palette.setCurrentColorGroup(QPalette::Normal);
|
||||
QColor tintTarget(colorOverride->r, colorOverride->g, colorOverride->b, colorOverride->a);
|
||||
|
||||
QPalette::ColorRole groups[] = { QPalette::Button, QPalette::Light, QPalette::Dark, QPalette::Midlight, QPalette::Mid, QPalette::Shadow };
|
||||
for (int i = 0; i < sizeof(groups) / sizeof(groups[0]); ++i)
|
||||
palette.setColor(groups[i], interpolateColor(palette.color(groups[i]), tintTarget, 0.11f));
|
||||
|
||||
tree->style()->drawControl(QStyle::CE_PushButtonBevel, &option, painter, pseudoDrawWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Previously, a temporary QPushButton widget was used as the drawing aid
|
||||
// for this control. However, our stylesheets didn't seem to affect the
|
||||
// QPushButton as intended, which left some of them with incorrect background
|
||||
// colors. It seemed to work to let the tree be the drawing aid, but we should
|
||||
// probably revisit this in the future.
|
||||
tree->style()->drawControl(QStyle::CE_PushButtonBevel, &option, painter, pseudoDrawWidget);
|
||||
}
|
||||
|
||||
QRect textRect;
|
||||
if ((buttonFlags & BUTTON_DISABLED) == 0 && buttonFlags & BUTTON_POPUP_ARROW)
|
||||
{
|
||||
QStyleOption arrowOption;
|
||||
arrowOption.rect = QRect(rect.right() - 11, rect.top(), 8, rect.height());
|
||||
arrowOption.state |= QStyle::State_Enabled;
|
||||
|
||||
// part of the above context change
|
||||
tree->style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &arrowOption, painter, tree);
|
||||
|
||||
textRect = rect.adjusted(0, 0, -8, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
textRect = rect;
|
||||
}
|
||||
|
||||
if (buttonFlags & BUTTON_PRESSED)
|
||||
{
|
||||
textRect = textRect.adjusted(1, 0, 1, 0);
|
||||
}
|
||||
if ((buttonFlags & BUTTON_CENTER) == 0)
|
||||
{
|
||||
textRect.adjust(4, 0, -5, 0);
|
||||
}
|
||||
|
||||
QColor textColor;
|
||||
if (colorOverride && !(buttonFlags & BUTTON_DISABLED))
|
||||
{
|
||||
textColor = interpolateColor(tree->palette().color(QPalette::Normal, QPalette::ButtonText),
|
||||
QColor(colorOverride->r, colorOverride->g, colorOverride->b, colorOverride->a), 0.4f);
|
||||
}
|
||||
else
|
||||
{
|
||||
textColor = tree->palette().color((buttonFlags & BUTTON_DISABLED) ? QPalette::Disabled : QPalette::Normal, QPalette::ButtonText);
|
||||
}
|
||||
tree->_drawRowValue(*painter, text, font, textRect, textColor, false, (buttonFlags & BUTTON_CENTER) != 0);
|
||||
}
|
||||
|
||||
void PropertyDrawContext::drawButtonWithIcon(const QIcon& icon, const QRect& rect, const wchar_t* text, bool selected, bool pressed, bool focused, bool enabled, bool showButtonFrame, const QFont* font) const
|
||||
{
|
||||
QStyleOptionButton option;
|
||||
if (enabled)
|
||||
option.state |= QStyle::State_Enabled;
|
||||
else
|
||||
option.state |= QStyle::State_ReadOnly;
|
||||
if (pressed) {
|
||||
option.state |= QStyle::State_On;
|
||||
option.state |= QStyle::State_Sunken;
|
||||
}
|
||||
else
|
||||
option.state |= QStyle::State_Raised;
|
||||
|
||||
if (focused)
|
||||
option.state |= QStyle::State_HasFocus;
|
||||
option.rect = rect.adjusted(0, 0, -1, -1);
|
||||
|
||||
// See the comment in the drawButton method above for why we don't use the
|
||||
// QPushButton as the drawing aid for this control
|
||||
if (showButtonFrame)
|
||||
tree->style()->drawControl(QStyle::CE_PushButton, &option, painter, tree);
|
||||
|
||||
int iconSize = 16;
|
||||
QRect iconRect(rect.topLeft(), QPoint(rect.left() + iconSize, rect.bottom()));
|
||||
QRect textRect;
|
||||
if (enabled)
|
||||
textRect = rect.adjusted(iconSize, 0, -8, 0);
|
||||
else
|
||||
textRect = rect.adjusted(iconSize, 0, 0, 0);
|
||||
|
||||
if (pressed)
|
||||
{
|
||||
textRect.adjust(5, 0, 1, 0);
|
||||
iconRect.adjust(4, 0, 4, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
textRect.adjust(4, 0, 0, 0);
|
||||
iconRect.adjust(3, 0, 3, 0);
|
||||
}
|
||||
icon.paint(painter, iconRect);
|
||||
|
||||
QColor textColor = tree->palette().color(enabled ? QPalette::Active : QPalette::Disabled, selected && !showButtonFrame ? QPalette::HighlightedText : QPalette::ButtonText);
|
||||
tree->_drawRowValue(*painter, text, font, textRect, textColor, false, false);
|
||||
}
|
||||
|
||||
void PropertyDrawContext::drawValueText(bool highlighted, const wchar_t* text) const
|
||||
{
|
||||
QColor textColor = highlighted ? tree->palette().highlight().color() : tree->palette().buttonText().color();
|
||||
QRect textRect(widgetRect.left() + 3, widgetRect.top() + 2, widgetRect.width() - 6, widgetRect.height() - 4);
|
||||
tree->_drawRowValue(*painter, text, &tree->font(), textRect, textColor, false, false);
|
||||
}
|
||||
|
||||
void PropertyDrawContext::drawEntry(const wchar_t* text, bool pathEllipsis, bool grayBackground, int trailingOffset) const
|
||||
{
|
||||
QRect rt = widgetRect;
|
||||
rt.adjust(0, 0, -trailingOffset, 0);
|
||||
|
||||
// the drawing context requires context so that the style sheet can be used:
|
||||
QFrame frameForContext;
|
||||
QLineEdit forContext;
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 11, 0))
|
||||
QStyleOptionFrameV2 option;
|
||||
option.features = QStyleOptionFrameV2::None;
|
||||
#else
|
||||
QStyleOptionFrame option;
|
||||
option.features = QStyleOptionFrame::None;
|
||||
#endif
|
||||
option.state = QStyle::State_Sunken;
|
||||
option.lineWidth = tree->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option, &frameForContext);
|
||||
option.midLineWidth = 0;
|
||||
if (!grayBackground)
|
||||
option.state |= QStyle::State_Enabled;
|
||||
else {
|
||||
option.palette.setCurrentColorGroup(QPalette::Disabled);
|
||||
}
|
||||
if (captured)
|
||||
option.state |= QStyle::State_HasFocus;
|
||||
option.rect = rt; // option.rect is the rectangle to be drawn on.
|
||||
QRect textRect = tree->style()->subElementRect(QStyle::SE_LineEditContents, &option, &forContext);
|
||||
if (!textRect.isValid())
|
||||
{
|
||||
textRect = rt;
|
||||
textRect.adjust(3, 1, -3, -2);
|
||||
}
|
||||
else {
|
||||
textRect.adjust(2, 1, -2, -1);
|
||||
}
|
||||
|
||||
// make sure the context control is polished (ie, ready for rendering) since we need to use its color palette:
|
||||
forContext.ensurePolished();
|
||||
|
||||
// some styles rely on default pens
|
||||
painter->setPen(QPen(forContext.palette().color(QPalette::Text)));
|
||||
painter->setBrush(QBrush(forContext.palette().color(QPalette::Base)));
|
||||
|
||||
tree->style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, painter, &forContext);
|
||||
tree->_drawRowValue(*painter, text, &tree->font(), textRect, forContext.palette().color(QPalette::Text), pathEllipsis, false);
|
||||
// end amazno changes
|
||||
}
|
||||
|
||||
|
||||
QFont* propertyTreeDefaultFont()
|
||||
{
|
||||
static QFont font;
|
||||
return &font;
|
||||
}
|
||||
|
||||
QFont* propertyTreeDefaultBoldFont()
|
||||
{
|
||||
static QFont font;
|
||||
font.setBold(true);
|
||||
return &font;
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYDRAWCONTEXT_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYDRAWCONTEXT_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <QRect>
|
||||
#include "Color.h"
|
||||
#include "EditorCommonAPI.h"
|
||||
|
||||
class QPainter;
|
||||
class QImage;
|
||||
class QBrush;
|
||||
class QRect;
|
||||
class QIcon;
|
||||
class QColor;
|
||||
class QFont;
|
||||
struct RGBAImage;
|
||||
namespace Serialization { struct IconXPM; }
|
||||
struct Color;
|
||||
|
||||
struct IconXPMCache
|
||||
{
|
||||
void initialize();
|
||||
void finalize();
|
||||
void flush();
|
||||
|
||||
~IconXPMCache();
|
||||
|
||||
QImage* getImageForIcon(const Serialization::IconXPM& icon);
|
||||
private:
|
||||
struct BitmapCache {
|
||||
std::vector<Color> pixels;
|
||||
QImage* bitmap;
|
||||
};
|
||||
|
||||
static bool parseXPM(RGBAImage* out, const Serialization::IconXPM& xpm);
|
||||
typedef std::map<const char* const*, BitmapCache> IconToBitmap;
|
||||
IconToBitmap iconToImageMap_;
|
||||
};
|
||||
|
||||
|
||||
void fillRoundRectangle(QPainter& p, const QBrush& brush, const QRect& r, const QColor& borderColor, int radius);
|
||||
void drawRoundRectangle(QPainter& p, const QRect &_r, unsigned int color, int radius, int width);
|
||||
|
||||
|
||||
enum CheckState {
|
||||
CHECK_SET,
|
||||
CHECK_NOT_SET,
|
||||
CHECK_IN_BETWEEN
|
||||
};
|
||||
|
||||
enum {
|
||||
BUTTON_POPUP_ARROW = 1 << 0,
|
||||
BUTTON_DISABLED = 1 << 1,
|
||||
BUTTON_FOCUSED = 1 << 2,
|
||||
BUTTON_PRESSED = 1 << 3,
|
||||
BUTTON_CENTER = 1 << 4
|
||||
};
|
||||
|
||||
class QPropertyTree;
|
||||
struct EDITOR_COMMON_API PropertyDrawContext {
|
||||
const QPropertyTree* tree;
|
||||
QPainter* painter;
|
||||
QRect widgetRect;
|
||||
QRect lineRect;
|
||||
bool captured;
|
||||
bool m_pressed;
|
||||
|
||||
void drawIcon(const QRect& rect, const Serialization::IconXPM& icon) const;
|
||||
void drawCheck(const QRect& rect, bool disabled, CheckState checked) const;
|
||||
void drawButton(const QRect& rect, const wchar_t* text, int buttonFlags, const QFont* font, const Color* optionalColorOverride = 0) const;
|
||||
void drawButtonWithIcon(const QIcon& icon, const QRect& rect, const wchar_t* text, bool selected, bool pressed, bool focused, bool enabled, bool showButtonFrame, const QFont* font) const;
|
||||
void drawValueText(bool highlighted, const wchar_t* text) const;
|
||||
void drawEntry(const wchar_t* text, bool pathEllipsis, bool grayBackground, int trailingOffset) const;
|
||||
|
||||
PropertyDrawContext()
|
||||
: tree(0)
|
||||
, painter(0)
|
||||
, captured(false)
|
||||
, m_pressed(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYDRAWCONTEXT_H
|
||||
@@ -1,377 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include "Serialization.h"
|
||||
#include "Serialization/Enum.h"
|
||||
#include "Serialization/Callback.h"
|
||||
#include "PropertyTreeModel.h"
|
||||
#include "PropertyIArchive.h"
|
||||
#include "PropertyRowBool.h"
|
||||
#include "PropertyRowString.h"
|
||||
#include "PropertyRowNumber.h"
|
||||
#include "PropertyRowPointer.h"
|
||||
#include "PropertyRowObject.h"
|
||||
#include "Unicode.h"
|
||||
|
||||
using Serialization::TypeID;
|
||||
|
||||
PropertyIArchive::PropertyIArchive(PropertyTreeModel* model, PropertyRow* root)
|
||||
: IArchive(INPUT | EDIT)
|
||||
, model_(model)
|
||||
, currentNode_(0)
|
||||
, lastNode_(0)
|
||||
, root_(root)
|
||||
{
|
||||
stack_.push_back(Level());
|
||||
|
||||
if (!root_)
|
||||
root_ = model_->root();
|
||||
else
|
||||
currentNode_ = root;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(Serialization::IString& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "string")){
|
||||
if(PropertyRowString* row = static_cast<PropertyRowString*>(currentNode_))
|
||||
value.set(fromWideChar(row->value().c_str()).c_str());
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(Serialization::IWString& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "string")){
|
||||
if(PropertyRowString* row = static_cast<PropertyRowString*>(currentNode_)) {
|
||||
value.set(row->value().c_str());
|
||||
}
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(bool& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "bool")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(char& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "char")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Signed types
|
||||
bool PropertyIArchive::operator()(int8& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "int8")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(int16& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "int16")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(int32& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "int32")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(int64& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "int64")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unsigned types
|
||||
bool PropertyIArchive::operator()(uint8& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "uint8")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(uint16& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "uint16")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(uint32& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "uint32")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(uint64& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "uint64")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(float& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "float")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(double& value, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "double")){
|
||||
currentNode_->assignToPrimitive(&value, sizeof(value));
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(Serialization::IContainer& ser, const char* name, const char* label)
|
||||
{
|
||||
const char* typeName = ser.containerType().name();
|
||||
if(!openRow(name, label, typeName))
|
||||
return false;
|
||||
|
||||
size_t size = 0;
|
||||
if(currentNode_->multiValue())
|
||||
size = ser.size();
|
||||
else{
|
||||
size = currentNode_->count();
|
||||
size = ser.resize(size);
|
||||
}
|
||||
|
||||
stack_.push_back(Level());
|
||||
|
||||
size_t index = 0;
|
||||
if(ser.size() > 0)
|
||||
while(index < size)
|
||||
{
|
||||
ser(*this, "", "<");
|
||||
ser.next();
|
||||
++index;
|
||||
}
|
||||
|
||||
stack_.pop_back();
|
||||
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
PropertyRow* nonLeafNode = 0;
|
||||
if(openRow(name, label, ser.type().name())){
|
||||
if (currentNode_->isLeaf()) {
|
||||
if(!currentNode_->isRoot()){
|
||||
currentNode_->assignTo(ser);
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
nonLeafNode = currentNode_;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
stack_.push_back(Level());
|
||||
|
||||
ser(*this);
|
||||
|
||||
stack_.pop_back();
|
||||
|
||||
if (nonLeafNode)
|
||||
nonLeafNode->closeNonLeaf(ser, *this);
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PropertyIArchive::operator()(Serialization::IPointer& ser, const char* name, const char* label)
|
||||
{
|
||||
const char* baseName = ser.baseType().name();
|
||||
|
||||
if(openRow(name, label, baseName)){
|
||||
if (!currentNode_->isPointer()) {
|
||||
closeRow(name);
|
||||
return false;
|
||||
}
|
||||
|
||||
YASLI_ASSERT(currentNode_);
|
||||
PropertyRowPointer* row = static_cast<PropertyRowPointer*>(currentNode_);
|
||||
if(!row){
|
||||
closeRow(name);
|
||||
return false;
|
||||
}
|
||||
row->assignTo(ser);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
stack_.push_back(Level());
|
||||
|
||||
if(ser.get() != 0)
|
||||
ser.serializer()( *this );
|
||||
|
||||
stack_.pop_back();
|
||||
|
||||
closeRow(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(Serialization::ICallback& callback, const char* name, const char* label)
|
||||
{
|
||||
return callback.SerializeValue(*this, name, label);
|
||||
}
|
||||
|
||||
bool PropertyIArchive::operator()(Serialization::Object& obj, const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, obj.type().name())){
|
||||
bool result = false;
|
||||
if (currentNode_->isObject()) {
|
||||
PropertyRowObject* rowObj = static_cast<PropertyRowObject*>(currentNode_);
|
||||
result = rowObj->assignTo(&obj);
|
||||
}
|
||||
closeRow(name);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyIArchive::OpenBlock(const char* name, const char* label)
|
||||
{
|
||||
if(openRow(name, label, "block")){
|
||||
stack_.push_back(Level());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void PropertyIArchive::CloseBlock()
|
||||
{
|
||||
closeRow("block");
|
||||
stack_.pop_back();
|
||||
}
|
||||
|
||||
bool PropertyIArchive::openRow(const char* name, [[maybe_unused]] const char* label, const char* typeName)
|
||||
{
|
||||
if(!name)
|
||||
return false;
|
||||
|
||||
if(!currentNode_){
|
||||
lastNode_ = currentNode_ = model_->root();
|
||||
YASLI_ASSERT(currentNode_);
|
||||
if (currentNode_ && strcmp(currentNode_->typeName(), typeName) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
YASLI_ESCAPE(currentNode_, return false);
|
||||
|
||||
if(currentNode_->empty())
|
||||
return false;
|
||||
|
||||
Level& level = stack_.back();
|
||||
|
||||
PropertyRow* node = 0;
|
||||
if(currentNode_->isContainer()){
|
||||
if (level.rowIndex < int(currentNode_->children_.size()))
|
||||
node = currentNode_->children_[level.rowIndex];
|
||||
++level.rowIndex;
|
||||
}
|
||||
else {
|
||||
node = currentNode_->findFromIndex(&level.rowIndex, name, typeName, level.rowIndex);
|
||||
++level.rowIndex;
|
||||
}
|
||||
|
||||
if(node){
|
||||
lastNode_ = node;
|
||||
if(node->isContainer() || !node->multiValue()){
|
||||
currentNode_ = node;
|
||||
if (currentNode_ && strcmp(currentNode_->typeName(), typeName) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PropertyIArchive::closeRow([[maybe_unused]] const char* name)
|
||||
{
|
||||
YASLI_ESCAPE(currentNode_, return);
|
||||
currentNode_ = currentNode_->parent();
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYIARCHIVE_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYIARCHIVE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Serialization/IArchive.h"
|
||||
|
||||
namespace Serialization{
|
||||
class CEnumDescription;
|
||||
class Object;
|
||||
}
|
||||
|
||||
class PropertyRow;
|
||||
class PropertyTreeModel;
|
||||
|
||||
class PropertyIArchive : public Serialization::IArchive{
|
||||
public:
|
||||
PropertyIArchive(PropertyTreeModel* model, PropertyRow* root);
|
||||
|
||||
protected:
|
||||
bool operator()(Serialization::IString& value, const char* name, const char* label);
|
||||
bool operator()(Serialization::IWString& value, const char* name, const char* label);
|
||||
bool operator()(bool& value, const char* name, const char* label);
|
||||
bool operator()(char& value, const char* name, const char* label);
|
||||
|
||||
// Signed types
|
||||
bool operator()(int8& value, const char* name, const char* label);
|
||||
bool operator()(int16& value, const char* name, const char* label);
|
||||
bool operator()(int32& value, const char* name, const char* label);
|
||||
bool operator()(int64& value, const char* name, const char* label);
|
||||
// Unsigned types
|
||||
bool operator()(uint8& value, const char* name, const char* label);
|
||||
bool operator()(uint16& value, const char* name, const char* label);
|
||||
bool operator()(uint32& value, const char* name, const char* label);
|
||||
bool operator()(uint64& value, const char* name, const char* label);
|
||||
|
||||
bool operator()(float& value, const char* name, const char* label);
|
||||
bool operator()(double& value, const char* name, const char* label);
|
||||
|
||||
bool operator()(const Serialization::SStruct& ser, const char* name, const char* label);
|
||||
bool operator()(Serialization::IPointer& ser, const char* name, const char* label);
|
||||
bool operator()(Serialization::IContainer& ser, const char* name, const char* label);
|
||||
bool operator()(Serialization::Object& obj, const char* name, const char* label);
|
||||
bool operator()(Serialization::ICallback& callback, const char* name, const char* label);
|
||||
using Serialization::IArchive::operator();
|
||||
|
||||
bool OpenBlock(const char* name, const char* label);
|
||||
void CloseBlock();
|
||||
|
||||
protected:
|
||||
bool needDefaultArchive([[maybe_unused]] const char* baseName) const { return false; }
|
||||
private:
|
||||
bool openRow(const char* name, const char* label, const char* typeName);
|
||||
void closeRow(const char* name);
|
||||
|
||||
struct Level {
|
||||
int rowIndex;
|
||||
Level() : rowIndex(0) {}
|
||||
};
|
||||
|
||||
vector<Level> stack_;
|
||||
|
||||
PropertyTreeModel* model_;
|
||||
PropertyRow* currentNode_;
|
||||
PropertyRow* lastNode_;
|
||||
PropertyRow* root_;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYIARCHIVE_H
|
||||
@@ -1,487 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include <math.h>
|
||||
#include <memory>
|
||||
|
||||
#include "PropertyTreeModel.h"
|
||||
#include "QPropertyTree.h"
|
||||
|
||||
#include "PropertyRowContainer.h"
|
||||
#include "PropertyRowBool.h"
|
||||
#include "PropertyRowString.h"
|
||||
#include "PropertyRowNumber.h"
|
||||
#include "PropertyRowPointer.h"
|
||||
#include "PropertyRowObject.h"
|
||||
#include "ConstStringList.h"
|
||||
#include "Unicode.h"
|
||||
|
||||
#include "Serialization.h"
|
||||
#include "PropertyOArchive.h"
|
||||
#include "Serialization/Callback.h"
|
||||
using Serialization::TypeID;
|
||||
|
||||
|
||||
PropertyOArchive::PropertyOArchive(PropertyTreeModel* model, PropertyRow* root, ValidatorBlock* validator)
|
||||
: IArchive(OUTPUT | EDIT | VALIDATION | DOCUMENTATION)
|
||||
, model_(model)
|
||||
, currentNode_(root)
|
||||
, lastNode_(0)
|
||||
, updateMode_(false)
|
||||
, defaultValueCreationMode_(false)
|
||||
, rootNode_(root)
|
||||
, outlineMode_(false)
|
||||
, validator_(validator)
|
||||
{
|
||||
stack_.push_back(Level());
|
||||
YASLI_ASSERT(model != 0);
|
||||
if(!rootNode_->empty()){
|
||||
updateMode_ = true;
|
||||
stack_.back().oldRows.swap(rootNode_->children_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PropertyOArchive::PropertyOArchive(PropertyTreeModel* model, bool forDefaultType)
|
||||
: IArchive(OUTPUT | EDIT | VALIDATION | DOCUMENTATION)
|
||||
, model_(model)
|
||||
, currentNode_(0)
|
||||
, lastNode_(0)
|
||||
, updateMode_(false)
|
||||
, defaultValueCreationMode_(forDefaultType)
|
||||
, rootNode_(0)
|
||||
, outlineMode_(false)
|
||||
, validator_(0)
|
||||
{
|
||||
rootNode_ = new PropertyRow();
|
||||
rootNode_->setName("root");
|
||||
currentNode_ = rootNode_.get();
|
||||
stack_.push_back(Level());
|
||||
}
|
||||
|
||||
PropertyOArchive::~PropertyOArchive()
|
||||
{
|
||||
}
|
||||
|
||||
PropertyRow* PropertyOArchive::defaultValueRootNode()
|
||||
{
|
||||
if (!rootNode_)
|
||||
return 0;
|
||||
return rootNode_->childByIndex(0);
|
||||
}
|
||||
|
||||
void PropertyOArchive::enterNode(PropertyRow* row)
|
||||
{
|
||||
currentNode_ = row;
|
||||
|
||||
stack_.push_back(Level());
|
||||
Level& level = stack_.back();
|
||||
level.oldRows.swap(row->children_);
|
||||
row->children_.reserve(level.oldRows.size());
|
||||
}
|
||||
|
||||
void PropertyOArchive::closeStruct([[maybe_unused]] const char* name)
|
||||
{
|
||||
stack_.pop_back();
|
||||
|
||||
if(currentNode_){
|
||||
lastNode_ = currentNode_;
|
||||
currentNode_ = currentNode_->parent();
|
||||
}
|
||||
}
|
||||
|
||||
static PropertyRow* findRow(int* index, PropertyRows& rows, const char* name, const char* typeName, int startIndex)
|
||||
{
|
||||
int count = int(rows.size());
|
||||
for(int i = startIndex; i < count; ++i){
|
||||
PropertyRow* row = rows[i];
|
||||
if (!row)
|
||||
continue;
|
||||
if(((row->name() == name) || strcmp(row->name(), name) == 0) &&
|
||||
(row->typeName() == typeName || strcmp(row->typeName(), typeName) == 0)) {
|
||||
*index = (int)i;
|
||||
return row;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < startIndex; ++i){
|
||||
PropertyRow* row = rows[i];
|
||||
if (!row)
|
||||
continue;
|
||||
if(((row->name() == name) || strcmp(row->name(), name) == 0) &&
|
||||
(row->typeName() == typeName || strcmp(row->typeName(), typeName) == 0)) {
|
||||
*index = (int)i;
|
||||
return row;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class RowType, class ValueType>
|
||||
RowType* PropertyOArchive::updateRow(const char* name, const char* label, const char* typeName, const ValueType& value)
|
||||
{
|
||||
SharedPtr<RowType> newRow;
|
||||
if(currentNode_ == 0){
|
||||
if (rootNode_)
|
||||
newRow = static_cast<RowType*>(rootNode_.get());
|
||||
else
|
||||
newRow.reset(new RowType());
|
||||
newRow->setNames(name, label, typeName);
|
||||
if(updateMode_){
|
||||
model_->setRoot(newRow);
|
||||
return newRow;
|
||||
}
|
||||
else{
|
||||
if(defaultValueCreationMode_)
|
||||
rootNode_ = newRow;
|
||||
else
|
||||
model_->setRoot(newRow);
|
||||
newRow->setValueAndContext(value, *this);
|
||||
return newRow;
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
Level& level = stack_.back();
|
||||
int rowIndex;
|
||||
PropertyRow* oldRow = findRow(&rowIndex, level.oldRows, name, typeName, level.rowIndex);
|
||||
|
||||
const char* oldLabel = 0;
|
||||
if(oldRow){
|
||||
oldRow->setMultiValue(false);
|
||||
newRow = static_cast<RowType*>(oldRow);
|
||||
level.oldRows[rowIndex] = 0;
|
||||
level.rowIndex = rowIndex + 1;
|
||||
oldLabel = oldRow->label();
|
||||
newRow->setNames(name, label, typeName);
|
||||
}
|
||||
else{
|
||||
PropertyRowFactory& factory = PropertyRowFactory::the();
|
||||
newRow = static_cast<RowType*>(factory.create(typeName));
|
||||
if(!newRow)
|
||||
newRow.reset(new RowType());
|
||||
newRow->setNames(name, label, typeName);
|
||||
if(model_->expandLevels() != 0 && (model_->expandLevels() == -1 || model_->expandLevels() >= currentNode_->level()))
|
||||
newRow->_setExpanded(true);
|
||||
}
|
||||
currentNode_->add(newRow);
|
||||
if (!oldRow || oldLabel != label) {
|
||||
// for new rows we should mark all parents with labelChanged_
|
||||
newRow->setLabelChanged();
|
||||
newRow->setLabelChangedToChildren();
|
||||
}
|
||||
newRow->setValueAndContext(value, *this);
|
||||
return newRow;
|
||||
}
|
||||
}
|
||||
|
||||
template<class RowType, class ValueType>
|
||||
PropertyRow* PropertyOArchive::updateRowPrimitive(const char* name, const char* label, const char* typeName, const ValueType& value, const void* handle, const Serialization::TypeID& typeId)
|
||||
{
|
||||
SharedPtr<RowType> newRow;
|
||||
|
||||
if(currentNode_ == 0)
|
||||
return 0;
|
||||
|
||||
int rowIndex;
|
||||
Level& level = stack_.back();
|
||||
PropertyRow* oldRow = findRow(&rowIndex, level.oldRows, name, typeName, level.rowIndex);
|
||||
|
||||
const char* oldLabel = 0;
|
||||
if(oldRow){
|
||||
oldRow->setMultiValue(false);
|
||||
newRow.reset(static_cast<RowType*>(oldRow));
|
||||
level.oldRows[rowIndex] = 0;
|
||||
level.rowIndex = rowIndex + 1;
|
||||
oldLabel = oldRow->label();
|
||||
oldRow->setNames(name, label, typeName);
|
||||
}
|
||||
else{
|
||||
newRow = new RowType();
|
||||
newRow->setNames(name, label, typeName);
|
||||
if(model_->expandLevels() != 0){
|
||||
if(model_->expandLevels() == -1 || model_->expandLevels() >= currentNode_->level())
|
||||
newRow->_setExpanded(true);
|
||||
}
|
||||
}
|
||||
currentNode_->add(newRow);
|
||||
if (!oldRow || oldLabel != label)
|
||||
{
|
||||
// for new rows we should mark all parents with labelChanged_
|
||||
newRow->setLabelChanged();
|
||||
}
|
||||
|
||||
newRow->setValue(value, handle, typeId);
|
||||
return newRow;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(const Serialization::SStruct& ser, const char* name, const char* label)
|
||||
{
|
||||
const char* typeName = ser.type().name();
|
||||
|
||||
lastNode_ = currentNode_;
|
||||
bool hideChildren = outlineMode_ && currentNode_ && currentNode_->isContainer();
|
||||
PropertyRow* row = updateRow<PropertyRow>(name, label, typeName, ser);
|
||||
row->setHideChildren(hideChildren);
|
||||
|
||||
PropertyRow* nonLeaf = 0;
|
||||
if(!row->isLeaf() || currentNode_ == 0){
|
||||
enterNode(row);
|
||||
|
||||
if(currentNode_->isLeaf())
|
||||
return false;
|
||||
else
|
||||
nonLeaf = currentNode_;
|
||||
}
|
||||
else{
|
||||
lastNode_ = row;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ser)
|
||||
ser(*this);
|
||||
|
||||
if (nonLeaf)
|
||||
nonLeaf->closeNonLeaf(ser, *this);
|
||||
|
||||
closeStruct(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(Serialization::IString& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowString>(name, label, "string", value.get(), value.handle(), value.type());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(Serialization::IWString& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowString>(name, label, "string", value.get(), value.handle(), value.type());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(bool& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowBool>(name, label, "bool", value, &value, Serialization::TypeID::get<bool>());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(char& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<char> >(name, label, "char", value, &value, Serialization::TypeID::get<char>());
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
bool PropertyOArchive::operator()(int8& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<int8> >(name, label, "int8", value, &value, Serialization::TypeID::get<int8>());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(int16& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<int16> >(name, label, "int16", value, &value, Serialization::TypeID::get<int16>());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(int32& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<int32> >(name, label, "int32", value, &value, Serialization::TypeID::get<int32>());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(int64& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<int64> >(name, label, "int64", value, &value, Serialization::TypeID::get<int64>());
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
bool PropertyOArchive::operator()(uint8& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<uint8> >(name, label, "uint8", value, &value, Serialization::TypeID::get<uint8>());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(uint16& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<uint16> >(name, label, "uint16", value, &value, Serialization::TypeID::get<uint16>());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(uint32& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<uint32> >(name, label, "uint32", value, &value, Serialization::TypeID::get<uint32>());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(uint64& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<uint64> >(name, label, "uint64", value, &value, Serialization::TypeID::get<uint64>());
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
bool PropertyOArchive::operator()(float& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<float> >(name, label, "float", value, &value, Serialization::TypeID::get<float>());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(double& value, const char* name, const char* label)
|
||||
{
|
||||
lastNode_ = updateRowPrimitive<PropertyRowNumber<double> >(name, label, "double", value, &value, Serialization::TypeID::get<double>());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PropertyOArchive::operator()(Serialization::IContainer& ser, const char *name, const char *label)
|
||||
{
|
||||
const char* elementTypeName = ser.elementType().name();
|
||||
enterNode(updateRow<PropertyRowContainer>(name, label, ser.containerType().name(), ser));
|
||||
|
||||
if (!model_->defaultTypeRegistered(elementTypeName)) {
|
||||
PropertyOArchive ar(model_, true);
|
||||
ar.SetOutlineMode(outlineMode_);
|
||||
ar.SetFilter(GetFilter());
|
||||
ar.SetInnerContext(GetInnerContext());
|
||||
model_->addDefaultType(0, elementTypeName); // add empty default to prevent recursion
|
||||
ser.serializeNewElement(ar, "", (label&&*label=='!')?"!<":"<");
|
||||
if (ar.defaultValueRootNode() != 0)
|
||||
model_->addDefaultType(ar.defaultValueRootNode(), elementTypeName);
|
||||
}
|
||||
if ( ser.size() > 0 )
|
||||
while( true ) {
|
||||
ser(*this, "", (label&&*label=='!')?"!<":"<");
|
||||
if ( !ser.next() )
|
||||
break;
|
||||
}
|
||||
currentNode_->labelChanged();
|
||||
closeStruct(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(Serialization::IPointer& ptr, const char *name, const char *label)
|
||||
{
|
||||
lastNode_ = currentNode_;
|
||||
|
||||
bool hideChildren = outlineMode_ && currentNode_ && currentNode_->isContainer();
|
||||
PropertyRow* row = updateRow<PropertyRowPointer>(name, label, ptr.baseType().name(), ptr);
|
||||
row->setHideChildren(hideChildren);
|
||||
enterNode(row);
|
||||
{
|
||||
TypeID baseType = ptr.baseType();
|
||||
Serialization::IClassFactory* factory = ptr.factory();
|
||||
size_t count = factory->size();
|
||||
|
||||
const char* nullLabel = factory->nullLabel();
|
||||
if (!(nullLabel && nullLabel[0] == '\0'))
|
||||
{
|
||||
PropertyDefaultDerivedTypeValue nullValue;
|
||||
nullValue.factory = factory;
|
||||
nullValue.factoryIndex = -1;
|
||||
nullValue.label = nullLabel ? nullLabel : "[ null ]";
|
||||
model_->addDefaultType(baseType, nullValue);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < count; ++i) {
|
||||
const Serialization::TypeDescription *desc = factory->descriptionByIndex((int)i);
|
||||
if (!model_->defaultTypeRegistered(baseType, desc->name())){
|
||||
PropertyOArchive ar(model_, true);
|
||||
ar.SetOutlineMode(outlineMode_);
|
||||
ar.SetInnerContext(GetInnerContext());
|
||||
ar.SetFilter(GetFilter());
|
||||
|
||||
PropertyDefaultDerivedTypeValue defaultValue;
|
||||
defaultValue.registeredName = desc->name();
|
||||
defaultValue.factory = factory;
|
||||
defaultValue.factoryIndex = int(i);
|
||||
defaultValue.label = desc->label();
|
||||
|
||||
model_->addDefaultType(baseType, defaultValue);
|
||||
factory->serializeNewByIndex(ar, (int)i, "name", "label");
|
||||
if (ar.defaultValueRootNode() != 0) {
|
||||
ar.defaultValueRootNode()->setTypeName(desc->name());
|
||||
defaultValue.root = ar.defaultValueRootNode();
|
||||
model_->addDefaultType(baseType, defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Serialization::SStruct ser = ptr.serializer())
|
||||
ser(*this);
|
||||
closeStruct(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(Serialization::ICallback& callback, const char* name, const char* label)
|
||||
{
|
||||
if (!callback.SerializeValue(*this, name, label))
|
||||
return false;
|
||||
|
||||
lastNode_->setCallback(callback.Clone());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::operator()(Serialization::Object& obj, const char *name, const char *label)
|
||||
{
|
||||
PropertyRowObject* row = 0;
|
||||
row = updateRow<PropertyRowObject>(name, label, obj.type().name(), obj);
|
||||
|
||||
lastNode_ = row;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyOArchive::OpenBlock(const char* name, const char* label)
|
||||
{
|
||||
PropertyRow* row = updateRow<PropertyRow>(name, label, "block", Serialization::SStruct());
|
||||
lastNode_ = currentNode_;
|
||||
enterNode(row);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PropertyOArchive::ValidatorMessage(bool error, const void* handle, const Serialization::TypeID& type, const char* message)
|
||||
{
|
||||
if (validator_)
|
||||
{
|
||||
ValidatorEntry entry(error ? VALIDATOR_ENTRY_ERROR : VALIDATOR_ENTRY_WARNING,
|
||||
handle,
|
||||
type,
|
||||
message);
|
||||
validator_->AddEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyOArchive::DocumentLastField(const char* message)
|
||||
{
|
||||
if (lastNode_ && (!currentNode_ || lastNode_->parent() == currentNode_))
|
||||
lastNode_->setTooltip(message ? message : "");
|
||||
else if (currentNode_)
|
||||
currentNode_->setTooltip(message ? message : "");
|
||||
}
|
||||
|
||||
void PropertyOArchive::CloseBlock()
|
||||
{
|
||||
closeStruct("block");
|
||||
}
|
||||
|
||||
void PropertyOArchive::SetOutlineMode(bool outlineMode)
|
||||
{
|
||||
outlineMode_ = outlineMode;
|
||||
}
|
||||
|
||||
// vim:ts=4 sw=4:
|
||||
@@ -1,112 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYOARCHIVE_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYOARCHIVE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Serialization/IArchive.h"
|
||||
#include "Serialization/Pointers.h"
|
||||
|
||||
namespace Serialization
|
||||
{
|
||||
class CEnumDescription;
|
||||
class Object;
|
||||
struct ICallback;
|
||||
}
|
||||
|
||||
class PropertyRow;
|
||||
class PropertyTreeModel;
|
||||
class ValidatorBlock;
|
||||
|
||||
using Serialization::SharedPtr;
|
||||
|
||||
class PropertyOArchive : public Serialization::IArchive{
|
||||
public:
|
||||
PropertyOArchive(PropertyTreeModel* model, PropertyRow* root, ValidatorBlock* validator);
|
||||
~PropertyOArchive();
|
||||
|
||||
void SetOutlineMode(bool outlineMode);
|
||||
|
||||
inline const SharedPtr<PropertyRow>& currentNode() const {
|
||||
return currentNode_;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool operator()(Serialization::IString& value, const char* name, const char* label);
|
||||
bool operator()(Serialization::IWString& value, const char* name, const char* label);
|
||||
bool operator()(bool& value, const char* name, const char* label);
|
||||
bool operator()(char& value, const char* name, const char* label);
|
||||
|
||||
bool operator()(int8& value, const char* name, const char* label);
|
||||
bool operator()(int16& value, const char* name, const char* label);
|
||||
bool operator()(int32& value, const char* name, const char* label);
|
||||
bool operator()(int64& value, const char* name, const char* label);
|
||||
|
||||
bool operator()(uint8& value, const char* name, const char* label);
|
||||
bool operator()(uint16& value, const char* name, const char* label);
|
||||
bool operator()(uint32& value, const char* name, const char* label);
|
||||
bool operator()(uint64& value, const char* name, const char* label);
|
||||
|
||||
bool operator()(float& value, const char* name, const char* label);
|
||||
bool operator()(double& value, const char* name, const char* label);
|
||||
|
||||
bool operator()(const Serialization::SStruct& ser, const char* name, const char* label);
|
||||
bool operator()(Serialization::IPointer& ptr, const char *name, const char *label);
|
||||
bool operator()(Serialization::IContainer& ser, const char *name, const char *label);
|
||||
bool operator()(Serialization::Object& obj, const char *name, const char *label);
|
||||
bool operator()(Serialization::ICallback& ser, const char *name, const char *label);
|
||||
using Serialization::IArchive::operator();
|
||||
|
||||
bool OpenBlock(const char* name, const char* label);
|
||||
void CloseBlock();
|
||||
void ValidatorMessage(bool error, const void* handle, const Serialization::TypeID& type, const char* message);
|
||||
void DocumentLastField(const char* docString);
|
||||
|
||||
protected:
|
||||
PropertyOArchive(PropertyTreeModel* model, bool forDefaultType);
|
||||
|
||||
private:
|
||||
struct Level {
|
||||
std::vector<SharedPtr<PropertyRow> > oldRows;
|
||||
int rowIndex;
|
||||
Level() : rowIndex(0) {}
|
||||
};
|
||||
std::vector<Level> stack_;
|
||||
|
||||
template<class RowType, class ValueType>
|
||||
PropertyRow* updateRowPrimitive(const char* name, const char* label, const char* typeName, const ValueType& value, const void* handle, const Serialization::TypeID& typeId);
|
||||
|
||||
template<class RowType, class ValueType>
|
||||
RowType* updateRow(const char* name, const char* label, const char* typeName, const ValueType& value);
|
||||
|
||||
void enterNode(PropertyRow* row); // sets currentNode
|
||||
void closeStruct(const char* name);
|
||||
PropertyRow* defaultValueRootNode();
|
||||
|
||||
bool updateMode_;
|
||||
bool defaultValueCreationMode_;
|
||||
PropertyTreeModel* model_;
|
||||
ValidatorBlock* validator_;
|
||||
SharedPtr<PropertyRow> currentNode_;
|
||||
SharedPtr<PropertyRow> lastNode_;
|
||||
|
||||
// for defaultArchive
|
||||
SharedPtr<PropertyRow> rootNode_;
|
||||
std::string typeName_;
|
||||
const char* derivedTypeName_;
|
||||
std::string derivedTypeNameAlt_;
|
||||
bool outlineMode_;
|
||||
};
|
||||
|
||||
// vim:ts=4 sw=4:
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYOARCHIVE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,575 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <typeinfo>
|
||||
#include <algorithm>
|
||||
#include "Serialization/Serializer.h"
|
||||
#include "Serialization/StringList.h"
|
||||
#include <Serialization/Pointers.h>
|
||||
#include "Factory.h"
|
||||
#include "ConstStringList.h"
|
||||
#include "Strings.h"
|
||||
#include "../EditorCommonAPI.h"
|
||||
#include "Serialization/ClassFactory.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
#include <QRect>
|
||||
#include <QCursor>
|
||||
#endif
|
||||
|
||||
namespace Serialization { struct ICallback; }
|
||||
|
||||
class QWidget;
|
||||
class QFont;
|
||||
class QPainter;
|
||||
class QMenu;
|
||||
class QKeyEvent;
|
||||
|
||||
using std::vector;
|
||||
class QPropertyTree;
|
||||
class PropertyRow;
|
||||
class PropertyTreeModel;
|
||||
class PopupMenuItem;
|
||||
struct PropertyDrawContext;
|
||||
struct EDITOR_COMMON_API ContainerMenuHandler;
|
||||
class PropertyRowContainer;
|
||||
|
||||
enum ScanResult {
|
||||
SCAN_FINISHED,
|
||||
SCAN_CHILDREN,
|
||||
SCAN_SIBLINGS,
|
||||
SCAN_CHILDREN_SIBLINGS,
|
||||
};
|
||||
|
||||
struct EDITOR_COMMON_API PropertyRowMenuHandler : QObject
|
||||
{
|
||||
public:
|
||||
virtual ~PropertyRowMenuHandler() {}
|
||||
|
||||
};
|
||||
|
||||
struct PropertyActivationEvent
|
||||
{
|
||||
enum Reason
|
||||
{
|
||||
REASON_PRESS,
|
||||
REASON_RELEASE,
|
||||
REASON_DOUBLECLICK,
|
||||
REASON_KEYBOARD,
|
||||
REASON_NEW_ELEMENT
|
||||
};
|
||||
|
||||
QPropertyTree* tree;
|
||||
Reason reason;
|
||||
bool force;
|
||||
QPoint clickPoint;
|
||||
|
||||
PropertyActivationEvent()
|
||||
: force(false)
|
||||
, clickPoint(0, 0)
|
||||
, tree(0)
|
||||
, reason(REASON_PRESS)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct PropertyDragEvent
|
||||
{
|
||||
QPropertyTree* tree;
|
||||
QPoint pos;
|
||||
QPoint start;
|
||||
QPoint lastDelta;
|
||||
QPoint totalDelta;
|
||||
};
|
||||
|
||||
struct PropertyHoverInfo
|
||||
{
|
||||
QCursor cursor;
|
||||
QString toolTip;
|
||||
|
||||
PropertyHoverInfo()
|
||||
: cursor()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
enum DragCheckBegin {
|
||||
DRAG_CHECK_IGNORE,
|
||||
DRAG_CHECK_SET,
|
||||
DRAG_CHECK_UNSET
|
||||
};
|
||||
|
||||
class PropertyRowWidget : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PropertyRowWidget(PropertyRow* row, QPropertyTree* tree);
|
||||
virtual ~PropertyRowWidget();
|
||||
virtual QWidget* actualWidget() { return 0; }
|
||||
virtual void showPopup() {}
|
||||
virtual void commit() = 0;
|
||||
PropertyRow* row() { return row_; }
|
||||
PropertyTreeModel* model() { return model_; }
|
||||
protected:
|
||||
PropertyRow* row_;
|
||||
QPropertyTree* tree_;
|
||||
PropertyTreeModel* model_;
|
||||
};
|
||||
|
||||
class PropertyTreeTransaction;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
class EDITOR_COMMON_API PropertyRow : public Serialization::RefCounter
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
public:
|
||||
enum WidgetPlacement {
|
||||
WIDGET_NONE,
|
||||
WIDGET_ICON,
|
||||
WIDGET_AFTER_NAME,
|
||||
WIDGET_VALUE,
|
||||
WIDGET_AFTER_PULLED,
|
||||
WIDGET_INSTEAD_OF_TEXT
|
||||
};
|
||||
|
||||
typedef std::vector< Serialization::SharedPtr<PropertyRow> > Rows;
|
||||
typedef Rows::iterator iterator;
|
||||
typedef Rows::const_iterator const_iterator;
|
||||
|
||||
PropertyRow();
|
||||
virtual ~PropertyRow();
|
||||
|
||||
void setNames(const char* name, const char* label, const char* typeName);
|
||||
|
||||
bool selected() const{ return selected_; }
|
||||
void setSelected(bool selected) { selected_ = selected; }
|
||||
bool expanded() const{ return expanded_; }
|
||||
void _setExpanded(bool expanded); // use QPropertyTree::expandRow
|
||||
void setExpandedRecursive(QPropertyTree* tree, bool expanded);
|
||||
|
||||
void setMatchFilter(bool matchFilter) { matchFilter_ = matchFilter; }
|
||||
bool matchFilter() const { return matchFilter_; }
|
||||
|
||||
void setBelongsToFilteredRow(bool belongs) { belongsToFilteredRow_ = belongs; }
|
||||
bool belongsToFilteredRow() const { return belongsToFilteredRow_; }
|
||||
|
||||
bool visible(const QPropertyTree* tree) const;
|
||||
bool hasVisibleChildren(const QPropertyTree* tree, bool internalCall = false) const;
|
||||
|
||||
const PropertyRow* hit(const QPropertyTree* tree, QPoint point) const;
|
||||
PropertyRow* hit(const QPropertyTree* tree, QPoint point);
|
||||
PropertyRow* parent() { return parent_; }
|
||||
const PropertyRow* parent() const{ return parent_; }
|
||||
void setParent(PropertyRow* row) { parent_ = row; }
|
||||
bool isRoot() const { return !parent_; }
|
||||
int level() const;
|
||||
|
||||
void add(PropertyRow* row);
|
||||
void addAfter(PropertyRow* row, PropertyRow* after);
|
||||
void addBefore(PropertyRow* row, PropertyRow* before);
|
||||
|
||||
template<class Op> bool scanChildren(Op& op);
|
||||
template<class Op> bool scanChildren(Op& op, QPropertyTree* tree);
|
||||
template<class Op> bool scanChildrenReverse(Op& op, QPropertyTree* tree);
|
||||
template<class Op> bool scanChildrenBottomUp(Op& op, QPropertyTree* tree);
|
||||
|
||||
PropertyRow* childByIndex(int index);
|
||||
const PropertyRow* childByIndex(int index) const;
|
||||
int childIndex(const PropertyRow* row) const;
|
||||
bool isChildOf(const PropertyRow* row) const;
|
||||
|
||||
bool empty() const{ return children_.empty(); }
|
||||
iterator find(PropertyRow* row) { return std::find(children_.begin(), children_.end(), row); }
|
||||
PropertyRow* findFromIndex(int* outIndex, const char* name, const char* typeName, int startIndex) const;
|
||||
PropertyRow* findByAddress(const void* handle);
|
||||
virtual const void* searchHandle() const;
|
||||
iterator begin() { return children_.begin(); }
|
||||
iterator end() { return children_.end(); }
|
||||
const_iterator begin() const{ return children_.begin(); }
|
||||
const_iterator end() const{ return children_.end(); }
|
||||
std::size_t count() const{ return children_.size(); }
|
||||
iterator erase(iterator it){ return children_.erase(it); }
|
||||
void clear(){ children_.clear(); }
|
||||
void erase(PropertyRow* row);
|
||||
void swapChildren(PropertyRow* row, PropertyTreeModel* model);
|
||||
|
||||
void assignRowState(const PropertyRow& row, bool recurse);
|
||||
void assignRowProperties(PropertyRow* row);
|
||||
void replaceAndPreserveState(PropertyRow* oldRow, PropertyRow* newRow, PropertyTreeModel* model);
|
||||
|
||||
const char* name() const{ return name_; }
|
||||
void setName(const char* name) { name_ = name; }
|
||||
const char* label() const { return label_; }
|
||||
const char* labelUndecorated() const { return labelUndecorated_; }
|
||||
void setLabel(const char* label);
|
||||
void setLabelChanged();
|
||||
void setTooltip(const char* tooltip);
|
||||
bool setValidatorEntry(int index, int count);
|
||||
int validatorCount() const{ return validatorCount_; }
|
||||
int validatorIndex() const{ return validatorIndex_; }
|
||||
void resetValidatorIcons();
|
||||
void addValidatorIcons(bool hasWarnings, bool hasErrors);
|
||||
const char* tooltip() const { return tooltip_; }
|
||||
void setLayoutChanged();
|
||||
void setLabelChangedToChildren();
|
||||
void setLayoutChangedToChildren();
|
||||
void setHideChildren(bool hideChildren) { hideChildren_ = hideChildren; }
|
||||
bool hideChildren() const { return hideChildren_; }
|
||||
void updateLabel(const QPropertyTree* tree, int index, bool parentHidesNonInlineChildren);
|
||||
void updateTextSizeInitial(const QPropertyTree* tree, int index, bool force);
|
||||
virtual void labelChanged() {}
|
||||
void parseControlCodes(const QPropertyTree* tree, const char* label, bool changeLabel);
|
||||
const char* typeName() const{ return typeName_; }
|
||||
virtual const char* typeNameForFilter(QPropertyTree* tree) const;
|
||||
void setTypeName(const char* typeName) { typeName_ = typeName; }
|
||||
const char* rowText(char* containerLabelBuffer, size_t bufsiz, const QPropertyTree* tree, int rowIndex) const;
|
||||
|
||||
PropertyRow* findSelected();
|
||||
PropertyRow* find(const char* name, const char* nameAlt, const char* typeName);
|
||||
const PropertyRow* find(const char* name, const char* nameAlt, const char* typeName) const;
|
||||
void intersect(const PropertyRow* row);
|
||||
|
||||
int verticalIndex(QPropertyTree* tree, PropertyRow* row);
|
||||
PropertyRow* rowByVerticalIndex(QPropertyTree* tree, int index);
|
||||
int horizontalIndex(QPropertyTree* tree, PropertyRow* row);
|
||||
PropertyRow* rowByHorizontalIndex(QPropertyTree* tree, int index);
|
||||
|
||||
virtual bool assignToPrimitive([[maybe_unused]] void* object, [[maybe_unused]] size_t size) const{ return false; }
|
||||
virtual bool assignTo([[maybe_unused]] const Serialization::SStruct& ser) const{ return false; }
|
||||
virtual bool assignToByPointer(void* instance, const Serialization::TypeID& type) const{ return assignTo(Serialization::SStruct(type, instance, type.sizeOf(), 0)); }
|
||||
virtual void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) { serializer_ = ser; }
|
||||
virtual void handleChildrenChange() {}
|
||||
virtual string valueAsString() const;
|
||||
virtual wstring valueAsWString() const;
|
||||
|
||||
int height() const{ return size_.y(); }
|
||||
|
||||
virtual int widgetSizeMin(const QPropertyTree*) const { return userWidgetSize() >= 0 ? userWidgetSize() : 0; }
|
||||
virtual int floorHeight() const{ return 0; }
|
||||
|
||||
void calcPulledRows(int* minTextSize, int* freePulledChildren, int* minimalWidth, const QPropertyTree* tree, int index);
|
||||
void calculateMinimalSize(const QPropertyTree* tree, int posX, int availableWidth, bool force, int* extraSizeRemainder, int* _extraSize, int index);
|
||||
void setTextSize(const QPropertyTree* tree, int rowIndex, float multiplier);
|
||||
void calculateTotalSizes(int* minTextSize);
|
||||
void adjustVerticalPosition(const QPropertyTree* tree, int& totalHeight);
|
||||
|
||||
virtual bool isWidgetFixed() const{ return userFixedWidget_ || (widgetPlacement() != WIDGET_VALUE && widgetPlacement() != WIDGET_INSTEAD_OF_TEXT); }
|
||||
|
||||
virtual WidgetPlacement widgetPlacement() const{ return WIDGET_NONE; }
|
||||
|
||||
QRect rect() const{ return QRect(pos_.x(), pos_.y(), size_.x(), size_.y()); }
|
||||
QRect rectIncludingChildren(const QPropertyTree* tree) const;
|
||||
QRect textRect(const QPropertyTree* tree) const;
|
||||
QRect widgetRect(const QPropertyTree* tree) const;
|
||||
QRect plusRect(const QPropertyTree* tree) const;
|
||||
QRect floorRect(const QPropertyTree* tree) const;
|
||||
QRect validatorRect(const QPropertyTree* tree) const;
|
||||
QRect validatorWarningIconRect(const QPropertyTree* tree) const;
|
||||
QRect validatorErrorIconRect(const QPropertyTree* tree) const;
|
||||
void adjustHoveredRect(QRect& hoveredRect);
|
||||
int heightIncludingChildren() const{ return heightIncludingChildren_; }
|
||||
const QFont* rowFont(const QPropertyTree* tree) const;
|
||||
|
||||
void drawRow(QPainter& painter, const QPropertyTree* tree, int rowIndex, bool selectionPass);
|
||||
void drawPlus(QPainter& p, const QPropertyTree* tree, const QRect& rect, bool expanded, bool selected, bool grayed) const;
|
||||
void drawStaticText(QPainter& p, const QRect& widgetRect);
|
||||
|
||||
virtual void redraw(const PropertyDrawContext& context);
|
||||
virtual PropertyRowWidget* createWidget([[maybe_unused]] QPropertyTree* tree) { return 0; }
|
||||
|
||||
virtual bool isContainer() const{ return false; }
|
||||
virtual bool isPointer() const{ return false; }
|
||||
virtual bool isObject() const{ return false; }
|
||||
|
||||
virtual bool isLeaf() const{ return false; }
|
||||
virtual void closeNonLeaf([[maybe_unused]] const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) {}
|
||||
virtual bool isStatic() const{ return pulledContainer_ == 0; }
|
||||
virtual bool isSelectable() const{ return (!userReadOnly() && !userReadOnlyRecurse()) || (!pulledUp() && !pulledBefore()); }
|
||||
virtual bool activateOnAdd() const{ return false; }
|
||||
virtual bool inlineInShortArrays() const{ return false; }
|
||||
|
||||
bool canBeToggled(const QPropertyTree* tree) const;
|
||||
bool canBeDragged() const;
|
||||
bool canBeDroppedOn(const PropertyRow* parentRow, const PropertyRow* beforeChild, const QPropertyTree* tree) const;
|
||||
void dropInto(PropertyRow* parentRow, PropertyRow* cursorRow, QPropertyTree* tree, bool before);
|
||||
virtual bool getHoverInfo(PropertyHoverInfo* hit, [[maybe_unused]] const QPoint& cursorPos, [[maybe_unused]] const QPropertyTree* tree) const {
|
||||
hit->toolTip = QString::fromUtf8(tooltip_);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool onActivate(const PropertyActivationEvent& e);
|
||||
virtual bool processesKey(QPropertyTree* tree, const QKeyEvent* ev); // returns true if it wants to process key events; otherwise, they will get processed by shortcuts in some cases, like delete
|
||||
virtual bool onKeyDown(QPropertyTree* tree, const QKeyEvent* ev);
|
||||
virtual bool onMouseDown([[maybe_unused]] QPropertyTree* tree, [[maybe_unused]] QPoint point, [[maybe_unused]] bool& changed) { return false; }
|
||||
virtual void onMouseDrag([[maybe_unused]] const PropertyDragEvent& e) {}
|
||||
virtual void onMouseStill([[maybe_unused]] const PropertyDragEvent& e) {}
|
||||
virtual void onMouseUp([[maybe_unused]] QPropertyTree* tree, [[maybe_unused]] QPoint point) {}
|
||||
// "drag check" allows you to "paint" with the mouse through checkboxes to set all values at once
|
||||
virtual DragCheckBegin onMouseDragCheckBegin() { return DRAG_CHECK_IGNORE; }
|
||||
virtual bool onMouseDragCheck([[maybe_unused]] QPropertyTree* tree, [[maybe_unused]] bool value) { return false; }
|
||||
virtual bool onContextMenu(QMenu &menu, QPropertyTree* tree);
|
||||
virtual ContainerMenuHandler* createMenuHandler(QPropertyTree* tree, PropertyRowContainer* container);
|
||||
|
||||
virtual bool isFullRow(const QPropertyTree* tree) const;
|
||||
|
||||
// User states.
|
||||
// Assigned using control codes (characters in the beginning of label)
|
||||
// fixed widget doesn't expand automatically to occupy all available place
|
||||
bool userFixedWidget() const{ return userFixedWidget_; }
|
||||
bool userFullRow() const { return userFullRow_; }
|
||||
void setUserReadOnly(bool userReadOnly) { userReadOnly_ = userReadOnly; }
|
||||
virtual bool userReadOnly() const { return userReadOnly_; }
|
||||
void propagateFlagsTopToBottom();
|
||||
virtual bool userReadOnlyRecurse() const { return userReadOnlyRecurse_; }
|
||||
bool userWidgetToContent() const { return userWidgetToContent_; }
|
||||
int userWidgetSize() const{ return userWidgetSize_; }
|
||||
bool userNonCopyable() const { return userNonCopyable_; }
|
||||
|
||||
// multiValue is used to edit properties of multiple objects simulateneously
|
||||
bool multiValue() const { return multiValue_; }
|
||||
void setMultiValue(bool multiValue) { multiValue_ = multiValue; }
|
||||
|
||||
// pulledRow - is the one that is pulled up to the parents row
|
||||
// (created with ^ in the beginning of label)
|
||||
bool pulledUp() const { return pulledUp_; }
|
||||
bool pulledBefore() const { return pulledBefore_; }
|
||||
bool hasPulled() const { return hasPulled_; }
|
||||
bool packedAfterPreviousRow() const { return packedAfterPreviousRow_; }
|
||||
bool pulledSelected() const;
|
||||
PropertyRow* nonPulledParent();
|
||||
void setPulledContainer(PropertyRow* container){ pulledContainer_ = container; }
|
||||
PropertyRow* pulledContainer() { return pulledContainer_; }
|
||||
const PropertyRow* pulledContainer() const{ return pulledContainer_; }
|
||||
|
||||
Serialization::SharedPtr<PropertyRow> clone(ConstStringList* constStrings) const;
|
||||
|
||||
Serialization::SStruct serializer() const{ return serializer_; }
|
||||
virtual Serialization::TypeID typeId() const{ return serializer_.type(); }
|
||||
void setSerializer(const Serialization::SStruct& ser) { serializer_ = ser; }
|
||||
virtual void serializeValue([[maybe_unused]] Serialization::IArchive& ar) {}
|
||||
void setCallback(Serialization::ICallback* callback);
|
||||
Serialization::ICallback* callback() { return callback_; }
|
||||
virtual void Serialize(Serialization::IArchive& ar);
|
||||
|
||||
static void setConstStrings(ConstStringList* constStrings){ constStrings_ = constStrings; }
|
||||
|
||||
protected:
|
||||
void init(const char* name, const char* nameAlt, const char* typeName);
|
||||
PropertyRow* findChildFromDescendant(PropertyRow* row) const;
|
||||
|
||||
virtual void overrideTextColor([[maybe_unused]] QColor& textColor) {}
|
||||
|
||||
const char* name_;
|
||||
const char* label_;
|
||||
const char* labelUndecorated_;
|
||||
const char* typeName_;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
Serialization::SStruct serializer_;
|
||||
PropertyRow* parent_;
|
||||
Serialization::ICallback* callback_;
|
||||
const char* tooltip_;
|
||||
Rows children_;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
unsigned int textHash_;
|
||||
|
||||
// do we really need QPoint here?
|
||||
QPoint pos_;
|
||||
QPoint size_;
|
||||
short int textPos_;
|
||||
short int textSizeInitial_;
|
||||
short int textSize_;
|
||||
short int widgetPos_; // widget == icon!
|
||||
short int widgetSize_;
|
||||
short int userWidgetSize_;
|
||||
unsigned short heightIncludingChildren_;
|
||||
unsigned short validatorIndex_;
|
||||
unsigned short validatorsHeight_;
|
||||
unsigned char validatorCount_;
|
||||
unsigned char plusSize_;
|
||||
bool visible_ : 1;
|
||||
bool matchFilter_ : 1;
|
||||
bool belongsToFilteredRow_ : 1;
|
||||
bool expanded_ : 1;
|
||||
bool selected_ : 1;
|
||||
bool labelChanged_ : 1;
|
||||
bool layoutChanged_ : 1;
|
||||
bool userReadOnly_ : 1;
|
||||
bool userReadOnlyRecurse_ : 1;
|
||||
bool userFixedWidget_ : 1;
|
||||
bool userFullRow_ : 1;
|
||||
bool userPackCheckboxes_ : 1;
|
||||
bool userWidgetToContent_ : 1;
|
||||
bool pulledUp_ : 1;
|
||||
bool pulledBefore_ : 1;
|
||||
bool packedAfterPreviousRow_ : 1;
|
||||
bool hasPulled_ : 1;
|
||||
bool multiValue_ : 1;
|
||||
bool hideChildren_ : 1;
|
||||
bool validatorHasErrors_ : 1;
|
||||
bool validatorHasWarnings_ : 1;
|
||||
bool userNonCopyable_ : 1;
|
||||
enum class FontWeight
|
||||
{
|
||||
Undefined,
|
||||
Bold,
|
||||
Regular
|
||||
};
|
||||
FontWeight fontWeight_;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
Serialization::SharedPtr<PropertyRow> pulledContainer_;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
static ConstStringList* constStrings_;
|
||||
friend class PropertyOArchive;
|
||||
friend class PropertyIArchive;
|
||||
};
|
||||
|
||||
inline unsigned int calculateHash(const char* str, unsigned hash = 5381)
|
||||
{
|
||||
while(*str)
|
||||
hash = hash * 33 + (unsigned char)*str++;
|
||||
return hash;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline unsigned int calculateHash(const T& t, unsigned hash = 5381)
|
||||
{
|
||||
for (int i = 0; i < sizeof(T); i++)
|
||||
hash = hash * 33 + ((unsigned char*)&t)[i];
|
||||
return hash;
|
||||
}
|
||||
|
||||
struct RowWidthCache
|
||||
{
|
||||
unsigned int valueHash;
|
||||
int width;
|
||||
|
||||
RowWidthCache() : valueHash(0), width(-1) {}
|
||||
int getOrUpdate(const QPropertyTree* tree, const PropertyRow* rowForValue, int extraSpace);
|
||||
};
|
||||
|
||||
typedef vector<Serialization::SharedPtr<PropertyRow> > PropertyRows;
|
||||
|
||||
template<bool value>
|
||||
struct StaticBool{
|
||||
enum { Value = value };
|
||||
};
|
||||
|
||||
struct LessStrCmp
|
||||
{
|
||||
bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Factory<const char*, PropertyRow, LessStrCmp> PropertyRowFactory;
|
||||
|
||||
template<class Op>
|
||||
bool PropertyRow::scanChildren(Op& op)
|
||||
{
|
||||
Rows::iterator it;
|
||||
|
||||
for(it = children_.begin(); it != children_.end(); ++it){
|
||||
ScanResult result = op(*it);
|
||||
if(result == SCAN_FINISHED)
|
||||
return false;
|
||||
if(result == SCAN_CHILDREN || result == SCAN_CHILDREN_SIBLINGS){
|
||||
if(!(*it)->scanChildren(op))
|
||||
return false;
|
||||
if(result == SCAN_CHILDREN)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Op>
|
||||
bool PropertyRow::scanChildren(Op& op, QPropertyTree* tree)
|
||||
{
|
||||
int numChildren = int(children_.size());
|
||||
for(int index = 0; index < numChildren; ++index){
|
||||
PropertyRow* child = children_[index];
|
||||
ScanResult result = op(child, tree, index);
|
||||
if(result == SCAN_FINISHED)
|
||||
return false;
|
||||
if(result == SCAN_CHILDREN || result == SCAN_CHILDREN_SIBLINGS){
|
||||
if(!child->scanChildren(op, tree))
|
||||
return false;
|
||||
if(result == SCAN_CHILDREN)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Op>
|
||||
bool PropertyRow::scanChildrenReverse(Op& op, QPropertyTree* tree)
|
||||
{
|
||||
int numChildren = (int)children_.size();
|
||||
for(int index = numChildren - 1; index >= 0; --index){
|
||||
PropertyRow* child = children_[index];
|
||||
ScanResult result = op(child, tree, index);
|
||||
if(result == SCAN_FINISHED)
|
||||
return false;
|
||||
if(result == SCAN_CHILDREN || result == SCAN_CHILDREN_SIBLINGS){
|
||||
if(!child->scanChildrenReverse(op, tree))
|
||||
return false;
|
||||
if(result == SCAN_CHILDREN)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Op>
|
||||
bool PropertyRow::scanChildrenBottomUp(Op& op, QPropertyTree* tree)
|
||||
{
|
||||
size_t numChildren = children_.size();
|
||||
for(size_t i = 0; i < numChildren; ++i)
|
||||
{
|
||||
PropertyRow* child = children_[i];
|
||||
if(!child->scanChildrenBottomUp(op, tree))
|
||||
return false;
|
||||
ScanResult result = op(child, tree);
|
||||
if(result == SCAN_FINISHED)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
EDITOR_COMMON_API PropertyRowFactory& GlobalPropertyRowFactory();
|
||||
EDITOR_COMMON_API Serialization::ClassFactory<PropertyRow>& GlobalPropertyRowClassFactory();
|
||||
|
||||
struct PropertyRowPtrSerializer : Serialization::SharedPtrSerializer<PropertyRow>
|
||||
{
|
||||
PropertyRowPtrSerializer(Serialization::SharedPtr<PropertyRow>& ptr) : SharedPtrSerializer(ptr) {}
|
||||
Serialization::ClassFactory<PropertyRow>* factory() const override { return &GlobalPropertyRowClassFactory(); }
|
||||
};
|
||||
|
||||
inline bool Serialize(Serialization::IArchive& ar, Serialization::SharedPtr<PropertyRow>& ptr, const char* name, const char* label)
|
||||
{
|
||||
PropertyRowPtrSerializer serializer(ptr);
|
||||
return ar(static_cast<Serialization::IPointer&>(serializer), name, label);
|
||||
}
|
||||
|
||||
#define REGISTER_PROPERTY_ROW(DataType, RowType) \
|
||||
PropertyRow* _Factory_For_##RowType() {return new RowType; }; \
|
||||
REGISTER_IN_FACTORY(PropertyRowFactory, Serialization::TypeID::get<DataType>().name(), RowType, _Factory_For_##RowType); \
|
||||
SERIALIZATION_CLASS_NAME_FOR_FACTORY(GlobalPropertyRowClassFactory(), PropertyRow, RowType, #DataType, #DataType);
|
||||
|
||||
// Exposes the necessary class factories to extend the property tree
|
||||
// Exposes the necessary class factories to extend the property tree
|
||||
EDITOR_COMMON_API Serialization::ClassFactory<PropertyRow>& GetPropertyRowClassFactory();
|
||||
EDITOR_COMMON_API PropertyRowFactory& GetPropertyRowFactory();
|
||||
@@ -1,168 +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.
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include <QIcon>
|
||||
|
||||
#include "Serialization/ClassFactory.h"
|
||||
#include "PropertyDrawContext.h"
|
||||
#include "PropertyRowImpl.h"
|
||||
#include "QPropertyTree.h"
|
||||
#include "PropertyTreeModel.h"
|
||||
#include "Serialization.h"
|
||||
#include "Color.h"
|
||||
#include "Unicode.h"
|
||||
#include "Serialization/Decorators/ActionButton.h"
|
||||
|
||||
using Serialization::IActionButton;
|
||||
using Serialization::IActionButtonPtr;
|
||||
|
||||
class PropertyRowActionButton
|
||||
: public PropertyRow
|
||||
{
|
||||
public:
|
||||
PropertyRowActionButton()
|
||||
: underMouse_()
|
||||
, pressed_()
|
||||
, minimalWidth_() {}
|
||||
bool isLeaf() const override { return true; }
|
||||
bool isStatic() const override { return false; }
|
||||
bool isSelectable() const override { return true; }
|
||||
|
||||
bool onActivate(const PropertyActivationEvent& e) override
|
||||
{
|
||||
if (e.reason == PropertyActivationEvent::REASON_KEYBOARD)
|
||||
{
|
||||
if (value_)
|
||||
{
|
||||
value_->Callback();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onMouseDown(QPropertyTree* tree, QPoint point, [[maybe_unused]] bool& changed) override
|
||||
{
|
||||
if (userReadOnly())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (widgetRect(tree).contains(point))
|
||||
{
|
||||
underMouse_ = true;
|
||||
pressed_ = true;
|
||||
tree->update();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void onMouseDrag(const PropertyDragEvent& e) override
|
||||
{
|
||||
if (userReadOnly())
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool underMouse = widgetRect(e.tree).contains(e.pos);
|
||||
if (underMouse != underMouse_)
|
||||
{
|
||||
underMouse_ = underMouse;
|
||||
e.tree->update();
|
||||
}
|
||||
}
|
||||
|
||||
void onMouseUp(QPropertyTree* tree, QPoint point) override
|
||||
{
|
||||
if (userReadOnly())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (widgetRect(tree).contains(point))
|
||||
{
|
||||
pressed_ = false;
|
||||
if (value_)
|
||||
{
|
||||
value_->Callback();
|
||||
}
|
||||
tree->update();
|
||||
}
|
||||
}
|
||||
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override
|
||||
{
|
||||
value_ = static_cast<IActionButton*>(ser.pointer())->Clone();
|
||||
const char* icon = value_->Icon();
|
||||
icon_ = icon && icon[0] ? QIcon() : QIcon(QString::fromLocal8Bit(icon));
|
||||
}
|
||||
bool assignTo([[maybe_unused]] const Serialization::SStruct& ser) const override { return true; }
|
||||
wstring valueAsWString() const override { return L""; }
|
||||
WidgetPlacement widgetPlacement() const override { return WIDGET_INSTEAD_OF_TEXT; }
|
||||
void serializeValue([[maybe_unused]] Serialization::IArchive& ar) override { }
|
||||
|
||||
int widgetSizeMin(const QPropertyTree* tree) const override
|
||||
{
|
||||
if (minimalWidth_ == 0)
|
||||
{
|
||||
QFontMetrics fm(tree->font());
|
||||
minimalWidth_ = (int)fm.horizontalAdvance(QString::fromLocal8Bit(labelUndecorated())) + 6 + (icon_.isNull() ? 0 : 18);
|
||||
}
|
||||
return minimalWidth_;
|
||||
}
|
||||
|
||||
void redraw(const PropertyDrawContext& context)
|
||||
{
|
||||
QRect rect = context.widgetRect.adjusted(-1, -1, 1, 1);
|
||||
bool pressed = pressed_ && underMouse_;
|
||||
|
||||
wstring text = toWideChar(labelUndecorated());
|
||||
if (icon_.isNull())
|
||||
{
|
||||
int buttonFlags = BUTTON_CENTER;
|
||||
if (pressed)
|
||||
{
|
||||
buttonFlags |= BUTTON_PRESSED;
|
||||
}
|
||||
if (selected())
|
||||
{
|
||||
buttonFlags |= BUTTON_FOCUSED;
|
||||
}
|
||||
if (userReadOnly())
|
||||
{
|
||||
buttonFlags |= BUTTON_DISABLED;
|
||||
}
|
||||
context.drawButton(rect, text.c_str(), buttonFlags, &context.tree->font());
|
||||
}
|
||||
else
|
||||
{
|
||||
context.drawButtonWithIcon(icon_, rect, text.c_str(), selected(), pressed, selected(), !userReadOnly(), true, &context.tree->font());
|
||||
}
|
||||
}
|
||||
bool isFullRow(const QPropertyTree* tree) const override
|
||||
{
|
||||
if (PropertyRow::isFullRow(tree))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return !userFixedWidget();
|
||||
}
|
||||
protected:
|
||||
mutable int minimalWidth_;
|
||||
bool underMouse_;
|
||||
bool pressed_;
|
||||
QIcon icon_;
|
||||
IActionButtonPtr value_;
|
||||
};
|
||||
|
||||
REGISTER_PROPERTY_ROW(IActionButton, PropertyRowActionButton);
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include "PropertyRowBool.h"
|
||||
#include "QPropertyTree.h"
|
||||
#include "PropertyTreeModel.h"
|
||||
#include "PropertyDrawContext.h"
|
||||
#include "Serialization/ClassFactory.h"
|
||||
#include "Serialization.h"
|
||||
#include <QKeyEvent>
|
||||
|
||||
SERIALIZATION_CLASS_NAME(PropertyRow, PropertyRowBool, "PropertyRowBool", "bool");
|
||||
|
||||
PropertyRowBool::PropertyRowBool()
|
||||
: value_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool PropertyRowBool::assignToPrimitive(void* object, [[maybe_unused]] size_t size) const
|
||||
{
|
||||
YASLI_ASSERT(size == sizeof(bool));
|
||||
*reinterpret_cast<bool*>(object) = value_;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyRowBool::assignToByPointer(void* instance, const Serialization::TypeID& type) const
|
||||
{
|
||||
return assignToPrimitive(instance, type.sizeOf());
|
||||
}
|
||||
|
||||
void PropertyRowBool::redraw(const PropertyDrawContext& context)
|
||||
{
|
||||
context.drawCheck(widgetRect(context.tree), userReadOnly(), multiValue() ? CHECK_IN_BETWEEN : (value_ ? CHECK_SET : CHECK_NOT_SET));
|
||||
}
|
||||
|
||||
bool PropertyRowBool::processesKey(QPropertyTree* tree, const QKeyEvent* ev)
|
||||
{
|
||||
if (QKeySequence(ev->key()) == QKeySequence(Qt::Key_Space))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return PropertyRow::processesKey(tree, ev);
|
||||
}
|
||||
|
||||
bool PropertyRowBool::onKeyDown(QPropertyTree* tree, const QKeyEvent* ev)
|
||||
{
|
||||
if (QKeySequence(ev->key()) == QKeySequence(Qt::Key_Space))
|
||||
{
|
||||
PropertyActivationEvent e;
|
||||
e.tree = tree;
|
||||
e.reason = e.REASON_KEYBOARD;
|
||||
onActivate(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
return PropertyRow::onKeyDown(tree, ev);
|
||||
}
|
||||
|
||||
bool PropertyRowBool::onActivate(const PropertyActivationEvent& e)
|
||||
{
|
||||
if (e.reason != e.REASON_RELEASE)
|
||||
{
|
||||
if (!this->userReadOnly())
|
||||
{
|
||||
e.tree->model()->rowAboutToBeChanged(this);
|
||||
value_ = !value_;
|
||||
e.tree->model()->rowChanged(this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DragCheckBegin PropertyRowBool::onMouseDragCheckBegin()
|
||||
{
|
||||
if (userReadOnly())
|
||||
{
|
||||
return DRAG_CHECK_IGNORE;
|
||||
}
|
||||
return value_ ? DRAG_CHECK_UNSET : DRAG_CHECK_SET;
|
||||
}
|
||||
|
||||
bool PropertyRowBool::onMouseDragCheck(QPropertyTree* tree, bool value)
|
||||
{
|
||||
if (value_ != value)
|
||||
{
|
||||
tree->model()->rowAboutToBeChanged(this);
|
||||
value_ = value;
|
||||
tree->model()->rowChanged(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PropertyRowBool::serializeValue(Serialization::IArchive& ar)
|
||||
{
|
||||
ar(value_, "value", "Value");
|
||||
}
|
||||
|
||||
int PropertyRowBool::widgetSizeMin(const QPropertyTree* tree) const
|
||||
{
|
||||
return aznumeric_cast<int>(tree->_defaultRowHeight() * 0.9f);
|
||||
}
|
||||
@@ -1,50 +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.
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWBOOL_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWBOOL_H
|
||||
#pragma once
|
||||
|
||||
#include "PropertyRow.h"
|
||||
#include "Unicode.h"
|
||||
|
||||
class PropertyRowBool
|
||||
: public PropertyRow
|
||||
{
|
||||
public:
|
||||
PropertyRowBool();
|
||||
bool assignToPrimitive(void* val, size_t size) const override;
|
||||
bool assignToByPointer(void* instance, const Serialization::TypeID& type) const;
|
||||
void setValue(bool value, const void* handle, [[maybe_unused]] const Serialization::TypeID& typeId) { value_ = value; serializer_.setPointer((void*)handle); serializer_.setType(Serialization::TypeID::get<bool>()); }
|
||||
|
||||
void redraw(const PropertyDrawContext& context);
|
||||
bool isLeaf() const{ return true; }
|
||||
bool isStatic() const{ return false; }
|
||||
|
||||
bool onActivate(const PropertyActivationEvent& e);
|
||||
DragCheckBegin onMouseDragCheckBegin() override;
|
||||
bool onMouseDragCheck(QPropertyTree* tree, bool value) override;
|
||||
wstring valueAsWString() const{ return value_ ? L"true" : L"false"; }
|
||||
string valueAsString() const{ return value_ ? "true" : "false"; }
|
||||
WidgetPlacement widgetPlacement() const{ return WIDGET_ICON; }
|
||||
void serializeValue(Serialization::IArchive& ar);
|
||||
int widgetSizeMin(const QPropertyTree* tree) const override;
|
||||
bool processesKey(QPropertyTree* tree, const QKeyEvent* ev) override;
|
||||
bool onKeyDown(QPropertyTree* tree, const QKeyEvent* ev) override;
|
||||
protected:
|
||||
bool value_;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWBOOL_H
|
||||
@@ -1,241 +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.
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include "PropertyRowColor.h"
|
||||
#include "Serialization/ClassFactory.h"
|
||||
#include <Cry_Color.h>
|
||||
#include <QMenu>
|
||||
#include <QFileDialog>
|
||||
#include <QPainter>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/ColorPicker.h>
|
||||
#include <AzQtComponents/Utilities/Conversions.h>
|
||||
|
||||
using Serialization::Vec3AsColor;
|
||||
typedef SerializableColor_tpl<unsigned char> SerializableColorB;
|
||||
typedef SerializableColor_tpl<float> SerializableColorF;
|
||||
|
||||
QColor ToQColor(const ColorB& v)
|
||||
{
|
||||
return QColor(v.r, v.g, v.b, v.a);
|
||||
}
|
||||
|
||||
void FromQColor(SerializableColorB& vColor, QColor color)
|
||||
{
|
||||
vColor.r = color.red();
|
||||
vColor.g = color.green();
|
||||
vColor.b = color.blue();
|
||||
vColor.a = color.alpha();
|
||||
}
|
||||
|
||||
|
||||
QColor ToQColor(const Vec3AsColor& v)
|
||||
{
|
||||
return QColor(int(v.v.x * 255.0f), int(v.v.y * 255.0f), int(v.v.z * 255.0f));
|
||||
}
|
||||
|
||||
void FromQColor(Vec3AsColor& vColor, QColor color)
|
||||
{
|
||||
vColor.v.x = color.red() / 255.0f;
|
||||
vColor.v.y = color.green() / 255.0f;
|
||||
vColor.v.z = color.blue() / 255.0f;
|
||||
}
|
||||
|
||||
QColor ToQColor(const SerializableColorF& v)
|
||||
{
|
||||
return QColor::fromRgbF(v.r, v.g, v.b, v.a);
|
||||
}
|
||||
|
||||
void FromQColor(SerializableColorF& vColor, QColor color)
|
||||
{
|
||||
vColor.r = aznumeric_cast<float>(color.redF());
|
||||
vColor.g = aznumeric_cast<float>(color.greenF());
|
||||
vColor.b = aznumeric_cast<float>(color.blueF());
|
||||
vColor.a = aznumeric_cast<float>(color.alphaF());
|
||||
}
|
||||
|
||||
|
||||
template <class ColorClass>
|
||||
bool PropertyRowColor<ColorClass>::pickColor(QPropertyTree* tree)
|
||||
{
|
||||
const AZ::Color initialColor = AzQtComponents::fromQColor(color_);
|
||||
const AZ::Color color = AzQtComponents::ColorPicker::getColor(AzQtComponents::ColorPicker::Configuration::RGB, initialColor, QObject::tr("Select Color"));
|
||||
|
||||
if (color != initialColor)
|
||||
{
|
||||
tree->model()->rowAboutToBeChanged(this);
|
||||
color_.setRed(color.GetR8());
|
||||
color_.setGreen(color.GetG8());
|
||||
color_.setBlue(color.GetB8());
|
||||
colorChanged_ = true;
|
||||
tree->model()->rowChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class ColorClass>
|
||||
bool PropertyRowColor<ColorClass>::onActivate(const PropertyActivationEvent& e)
|
||||
{
|
||||
return pickColor(e.tree);
|
||||
}
|
||||
|
||||
template <class ColorClass>
|
||||
void PropertyRowColor<ColorClass>::setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] IArchive& ar)
|
||||
{
|
||||
color_ = ToQColor(*(ColorClass*)ser.pointer());
|
||||
colorChanged_ = false;
|
||||
}
|
||||
|
||||
template <class ColorClass>
|
||||
bool PropertyRowColor<ColorClass>::assignTo(const Serialization::SStruct& ser) const
|
||||
{
|
||||
FromQColor(*((ColorClass*)ser.pointer()), color_);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class ColorClass>
|
||||
string PropertyRowColor<ColorClass>::valueAsString() const
|
||||
{
|
||||
char buf[64];
|
||||
sprintf_s(buf, "%d %d %d", (int)color_.red(), (int)color_.green(), (int)color_.blue());
|
||||
return string(buf);
|
||||
}
|
||||
|
||||
template <class ColorClass>
|
||||
bool PropertyRowColor<ColorClass>::onContextMenu(QMenu& menu, QPropertyTree* tree)
|
||||
{
|
||||
Serialization::SharedPtr<PropertyRowColor> selfPointer(this);
|
||||
ColorMenuHandler* handler = new ColorMenuHandler(tree, this);
|
||||
menu.addAction("Pick Color", handler, SLOT(onMenuPickColor()));
|
||||
tree->addMenuHandler(handler);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ColorClass>
|
||||
void PropertyRowColor<ColorClass>::redraw(const PropertyDrawContext& context)
|
||||
{
|
||||
static QImage checkboardPattern;
|
||||
if (checkboardPattern.isNull())
|
||||
{
|
||||
int size = 12;
|
||||
static vector<int> pixels(size * size);
|
||||
for (int i = 0; i < pixels.size(); ++i)
|
||||
{
|
||||
pixels[i] = ((i / size) / (size / 2) + (i % size) / (size / 2)) % 2 ? 0xffffffff : 0x000000ff;
|
||||
}
|
||||
checkboardPattern = QImage((unsigned char*)pixels.data(), size, size, size * 4, QImage::Format_RGBA8888);
|
||||
}
|
||||
|
||||
QRect r = context.widgetRect.adjusted(0, 0, 0, -1);
|
||||
|
||||
context.painter->save();
|
||||
context.painter->setPen(QPen(Qt::NoPen));
|
||||
context.painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
context.painter->setBrush(context.tree->palette().color(QPalette::Dark));
|
||||
context.painter->setPen(Qt::NoPen);
|
||||
context.painter->drawRoundedRect(r, 2, 2);
|
||||
r = r.adjusted(1, 1, -1, -1);
|
||||
QRect cr = r.adjusted(0, 0, -r.width() / 2, 0);
|
||||
context.painter->setBrushOrigin(cr.topRight() + QPoint(1, 0));
|
||||
context.painter->setBrush(QBrush(checkboardPattern));
|
||||
|
||||
context.painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
context.painter->drawRoundedRect(r, 2, 2);
|
||||
|
||||
context.painter->setPen(QPen(Qt::NoPen));
|
||||
context.painter->setClipRect(cr);
|
||||
context.painter->setBrush(QBrush(color_));
|
||||
context.painter->drawRoundedRect(r, 2, 2);
|
||||
|
||||
cr = r.adjusted(r.width() / 2, 0, 0, 0);
|
||||
context.painter->setClipRect(cr);
|
||||
context.painter->setBrush(QBrush(QColor(color_.red(), color_.green(), color_.blue(), 255)));
|
||||
context.painter->drawRoundedRect(r, 2, 2);
|
||||
context.painter->restore();
|
||||
}
|
||||
|
||||
template <class ColorClass>
|
||||
void PropertyRowColor<ColorClass>::closeNonLeaf(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar)
|
||||
{
|
||||
color_ = ToQColor(*(ColorClass*)ser.pointer());
|
||||
}
|
||||
|
||||
static int componentFromRowValue(const char* str, ColorB*)
|
||||
{
|
||||
return clamp_tpl(atoi(str), 0, 255);
|
||||
}
|
||||
|
||||
static int componentFromRowValue(const char* str, ColorF*)
|
||||
{
|
||||
return clamp_tpl(int(atof(str) * 255.0f + 0.5f), 0, 255);
|
||||
}
|
||||
|
||||
static int componentFromRowValue(const char* str, Vec3AsColor*)
|
||||
{
|
||||
return clamp_tpl(int(atof(str) * 255.0f + 0.5f), 0, 255);
|
||||
}
|
||||
|
||||
template<class ColorClass>
|
||||
void PropertyRowColor<ColorClass>::handleChildrenChange()
|
||||
{
|
||||
// generally is not needed unless we are using callbacks
|
||||
PropertyRow* rows[4] = {
|
||||
childByIndex(0),
|
||||
childByIndex(1),
|
||||
childByIndex(2),
|
||||
childByIndex(3)
|
||||
};
|
||||
|
||||
if (rows[0])
|
||||
{
|
||||
color_.setRed(componentFromRowValue(rows[0]->valueAsString().c_str(), (ColorClass*)0));
|
||||
}
|
||||
if (rows[1])
|
||||
{
|
||||
color_.setGreen(componentFromRowValue(rows[1]->valueAsString().c_str(), (ColorClass*)0));
|
||||
}
|
||||
if (rows[2])
|
||||
{
|
||||
color_.setBlue(componentFromRowValue(rows[2]->valueAsString().c_str(), (ColorClass*)0));
|
||||
}
|
||||
if (rows[3])
|
||||
{
|
||||
color_.setAlpha(componentFromRowValue(rows[3]->valueAsString().c_str(), (ColorClass*)0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ColorMenuHandler::ColorMenuHandler(QPropertyTree* tree, IPropertyRowColor* propertyRowColor)
|
||||
: propertyRowColor(propertyRowColor)
|
||||
, tree(tree)
|
||||
{
|
||||
}
|
||||
|
||||
void ColorMenuHandler::onMenuPickColor()
|
||||
{
|
||||
propertyRowColor->pickColor(tree);
|
||||
}
|
||||
|
||||
typedef PropertyRowColor<SerializableColorB> PropertyRowColorB;
|
||||
typedef PropertyRowColor<Vec3AsColor> PropertyRowVec3AsColor;
|
||||
typedef PropertyRowColor<SerializableColorF> PropertyRowColorF;
|
||||
|
||||
REGISTER_PROPERTY_ROW(SerializableColorB, PropertyRowColorB);
|
||||
REGISTER_PROPERTY_ROW(Vec3AsColor, PropertyRowVec3AsColor);
|
||||
REGISTER_PROPERTY_ROW(SerializableColorF, PropertyRowColorF);
|
||||
|
||||
#include <QPropertyTree/moc_PropertyRowColor.cpp>
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "PropertyDrawContext.h"
|
||||
#include "QPropertyTree.h"
|
||||
#include "PropertyTreeModel.h"
|
||||
#include <Serialization.h>
|
||||
#endif
|
||||
|
||||
struct IPropertyRowColor
|
||||
{
|
||||
virtual bool pickColor(QPropertyTree* tree) = 0;
|
||||
};
|
||||
|
||||
template <class ColorClass>
|
||||
class PropertyRowColor
|
||||
: public PropertyRow
|
||||
, public IPropertyRowColor
|
||||
{
|
||||
public:
|
||||
PropertyRowColor()
|
||||
: colorChanged_(false) {}
|
||||
|
||||
bool isLeaf() const override { return colorChanged_; }
|
||||
bool isStatic() const override { return false; }
|
||||
WidgetPlacement widgetPlacement() const{ return WIDGET_AFTER_PULLED; }
|
||||
int widgetSizeMin(const QPropertyTree* tree) const { return userWidgetSize() >= 0 ? userWidgetSize() : tree->_defaultRowHeight()* 2 - 4; }
|
||||
void handleChildrenChange() override;
|
||||
|
||||
void setValueAndContext(const Serialization::SStruct& ser, Serialization::IArchive& ar) override;
|
||||
bool assignTo(const Serialization::SStruct& ser) const override;
|
||||
void closeNonLeaf(const Serialization::SStruct& ser, Serialization::IArchive& ar);
|
||||
|
||||
bool onActivate(const PropertyActivationEvent& ev) override;
|
||||
|
||||
string valueAsString() const;
|
||||
void redraw(const PropertyDrawContext& context);
|
||||
|
||||
bool onContextMenu(QMenu& menu, QPropertyTree* tree);
|
||||
|
||||
bool pickColor(QPropertyTree* tree) override;
|
||||
|
||||
private:
|
||||
QColor color_;
|
||||
bool colorChanged_;
|
||||
};
|
||||
|
||||
struct ColorMenuHandler
|
||||
: PropertyRowMenuHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QPropertyTree * tree;
|
||||
IPropertyRowColor* propertyRowColor;
|
||||
|
||||
ColorMenuHandler(QPropertyTree* tree, IPropertyRowColor* propertyRowColor);
|
||||
~ColorMenuHandler(){};
|
||||
|
||||
public slots:
|
||||
void onMenuPickColor();
|
||||
};
|
||||
@@ -1,158 +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 "EditorCommon_precompiled.h"
|
||||
#include "PropertyRowColorPicker.h"
|
||||
#include "Serialization/ClassFactory.h"
|
||||
#include <IEditor.h>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
#include <QIcon>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/ColorPicker.h>
|
||||
#include <AzQtComponents/Utilities/Conversions.h>
|
||||
|
||||
bool PropertyRowColorPicker::onActivate(const PropertyActivationEvent& e)
|
||||
{
|
||||
if (e.reason == e.REASON_RELEASE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// ColorF -> QColor.
|
||||
AZ::Color initialColor;
|
||||
initialColor.SetR(color_.r);
|
||||
initialColor.SetG(color_.g);
|
||||
initialColor.SetB(color_.b);
|
||||
initialColor.SetA(color_.a);
|
||||
|
||||
const AZ::Color colorFromDialog = AzQtComponents::ColorPicker::getColor(AzQtComponents::ColorPicker::Configuration::RGBA,
|
||||
initialColor,
|
||||
QObject::tr("Select Color"));
|
||||
|
||||
if (initialColor == colorFromDialog)
|
||||
{
|
||||
// The user cancelled the dialog box.
|
||||
// Nothing more to do.
|
||||
return false;
|
||||
}
|
||||
|
||||
// QColor -> ColorF.
|
||||
ColorF color(colorFromDialog.GetR(),
|
||||
colorFromDialog.GetG(),
|
||||
colorFromDialog.GetB(),
|
||||
colorFromDialog.GetA());
|
||||
|
||||
e.tree->model()->rowAboutToBeChanged(this);
|
||||
color_ = color;
|
||||
e.tree->model()->rowChanged(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
void PropertyRowColorPicker::setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar)
|
||||
{
|
||||
ColorPicker* value = (ColorPicker*)ser.pointer();
|
||||
color_ = *value->color;
|
||||
}
|
||||
|
||||
bool PropertyRowColorPicker::assignTo(const Serialization::SStruct& ser) const
|
||||
{
|
||||
((ColorPicker*)ser.pointer())->SetColor(&color_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PropertyRowColorPicker::serializeValue(Serialization::IArchive& ar)
|
||||
{
|
||||
ar(color_, "color");
|
||||
}
|
||||
|
||||
const QIcon& PropertyRowColorPicker::buttonIcon([[maybe_unused]] const QPropertyTree* tree, [[maybe_unused]] int index) const
|
||||
{
|
||||
// Color-chip.
|
||||
|
||||
QColor color((int)(color_.r * 255.0f),
|
||||
(int)(color_.g * 255.0f),
|
||||
(int)(color_.b * 255.0f));
|
||||
QPen pen(color);
|
||||
QBrush brush(color);
|
||||
|
||||
QPixmap pixmap(16, 16);
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&pixmap);
|
||||
painter.setBrush(brush);
|
||||
painter.setPen(pen);
|
||||
painter.drawEllipse(0, 0, 15, 15);
|
||||
|
||||
static QIcon icon;
|
||||
icon.addPixmap(pixmap);
|
||||
return icon;
|
||||
}
|
||||
|
||||
string PropertyRowColorPicker::valueAsString() const
|
||||
{
|
||||
int r = (int)(255.0f * color_.r);
|
||||
int g = (int)(255.0f * color_.g);
|
||||
int b = (int)(255.0f * color_.b);
|
||||
int a = (int)(255.0f * color_.a);
|
||||
string value;
|
||||
value.Format("#%02x%02x%02x%02x", r, g, b, a);
|
||||
return value;
|
||||
}
|
||||
|
||||
void PropertyRowColorPicker::clear()
|
||||
{
|
||||
color_ = Col_White;
|
||||
}
|
||||
|
||||
bool PropertyRowColorPicker::onContextMenu(QMenu& menu, QPropertyTree* tree)
|
||||
{
|
||||
QAction* action = menu.addAction("Clear");
|
||||
QObject::connect(action,
|
||||
&QAction::triggered,
|
||||
tree,
|
||||
[ this, tree ]
|
||||
{
|
||||
tree->model()->rowAboutToBeChanged(this);
|
||||
clear();
|
||||
tree->model()->rowChanged(this);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PropertyRowColorPicker::processesKey(QPropertyTree* tree, const QKeyEvent* ev)
|
||||
{
|
||||
if (QKeySequence(ev->key()) == QKeySequence(Qt::Key_Delete))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return PropertyRowField::processesKey(tree, ev);
|
||||
}
|
||||
|
||||
bool PropertyRowColorPicker::onKeyDown(QPropertyTree* tree, const QKeyEvent* ev)
|
||||
{
|
||||
if (ev->key() == Qt::Key_Delete)
|
||||
{
|
||||
tree->model()->rowAboutToBeChanged(this);
|
||||
clear();
|
||||
tree->model()->rowChanged(this);
|
||||
return true;
|
||||
}
|
||||
return PropertyRowField::onKeyDown(tree, ev);
|
||||
}
|
||||
|
||||
REGISTER_PROPERTY_ROW(ColorPicker, PropertyRowColorPicker);
|
||||
DECLARE_SEGMENT(PropertyRowColorPicker)
|
||||
|
||||
@@ -1,56 +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.
|
||||
*
|
||||
*/
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCOLORPICKER_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCOLORPICKER_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "PropertyDrawContext.h"
|
||||
#include "PropertyRowField.h"
|
||||
#include "QPropertyTree.h"
|
||||
#include "PropertyTreeModel.h"
|
||||
#include "Serialization.h"
|
||||
#include <Serialization/Decorators/ColorPicker.h>
|
||||
#include <Serialization/Decorators/ColorPickerImpl.h>
|
||||
#include <Serialization/Decorators/IconXPM.h>
|
||||
#endif
|
||||
|
||||
using Serialization::ColorPicker;
|
||||
|
||||
class PropertyRowColorPicker
|
||||
: public PropertyRowField
|
||||
{
|
||||
public:
|
||||
void clear();
|
||||
|
||||
bool isLeaf() const override { return true; }
|
||||
bool isStatic() const override { return false; }
|
||||
|
||||
void setValueAndContext(const Serialization::SStruct& ser, Serialization::IArchive& ar) override;
|
||||
bool assignTo(const Serialization::SStruct& ser) const override;
|
||||
bool onActivate(const PropertyActivationEvent& e) override;
|
||||
|
||||
int buttonCount() const override { return 1; }
|
||||
virtual const QIcon& buttonIcon(const QPropertyTree* tree, int index) const override;
|
||||
string valueAsString() const override;
|
||||
void serializeValue(Serialization::IArchive& ar);
|
||||
|
||||
bool onContextMenu(QMenu& menu, QPropertyTree* tree);
|
||||
|
||||
bool processesKey(QPropertyTree* tree, const QKeyEvent* ev) override;
|
||||
bool onKeyDown(QPropertyTree* tree, const QKeyEvent* ev) override;
|
||||
|
||||
private:
|
||||
ColorF color_;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCOLORPICKER_H
|
||||
@@ -1,439 +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 "EditorCommon_precompiled.h"
|
||||
#include "PropertyRowContainer.h"
|
||||
#include "PropertyRowPointer.h"
|
||||
#include "QPropertyTree.h"
|
||||
#include "PropertyTreeModel.h"
|
||||
#include "PropertyDrawContext.h"
|
||||
#include "Serialization.h"
|
||||
#include "PropertyRowPointer.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QKeyEvent>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
ContainerMenuHandler::ContainerMenuHandler(QPropertyTree* tree, PropertyRowContainer* container)
|
||||
: element()
|
||||
, container(container)
|
||||
, tree(tree)
|
||||
, pointerIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
SERIALIZATION_CLASS_NAME(PropertyRow, PropertyRowContainer, "PropertyRowContainer", "Container");
|
||||
|
||||
PropertyRowContainer::PropertyRowContainer()
|
||||
: fixedSize_(false)
|
||||
, elementTypeName_("")
|
||||
, inlined_(false)
|
||||
{
|
||||
buttonLabel_[0] = '\0';
|
||||
}
|
||||
|
||||
struct ClassMenuItemAdderRowContainer
|
||||
: ClassMenuItemAdder
|
||||
{
|
||||
ClassMenuItemAdderRowContainer(PropertyRowContainer* row, QPropertyTree* tree, bool insert = false)
|
||||
: row_(row)
|
||||
, tree_(tree)
|
||||
, insert_(insert) {}
|
||||
|
||||
void addAction(QMenu& menu, const char* text, int index) override
|
||||
{
|
||||
ContainerMenuHandler* handler = row_->createMenuHandler(tree_, row_);
|
||||
tree_->addMenuHandler(handler);
|
||||
handler->pointerIndex = index;
|
||||
|
||||
QAction* action = menu.addAction(text);
|
||||
QObject::connect(action, SIGNAL(triggered()), handler, SLOT(onMenuAppendPointerByIndex()));
|
||||
}
|
||||
protected:
|
||||
PropertyRowContainer* row_;
|
||||
QPropertyTree* tree_;
|
||||
bool insert_;
|
||||
};
|
||||
|
||||
void PropertyRowContainer::redraw(const PropertyDrawContext& context)
|
||||
{
|
||||
QRect widgetRect = context.widgetRect;
|
||||
if (widgetRect.width() == 0 || inlined_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
QRect rt = widgetRect;
|
||||
rt.adjust(0, 1, -1, -1);
|
||||
QColor brushColor = context.tree->palette().button().color();
|
||||
QLinearGradient gradient(rt.left(), rt.top(), rt.left(), rt.bottom());
|
||||
gradient.setColorAt(0.0f, brushColor);
|
||||
gradient.setColorAt(0.6f, brushColor);
|
||||
gradient.setColorAt(1.0f, context.tree->palette().color(QPalette::Shadow));
|
||||
QBrush brush(gradient);
|
||||
|
||||
const wchar_t* text = multiValue() ? L"..." : buttonLabel_;
|
||||
int buttonFlags = BUTTON_CENTER | BUTTON_POPUP_ARROW;
|
||||
if (userReadOnly())
|
||||
{
|
||||
buttonFlags |= BUTTON_DISABLED;
|
||||
}
|
||||
if (context.m_pressed)
|
||||
{
|
||||
buttonFlags |= BUTTON_PRESSED;
|
||||
}
|
||||
context.drawButton(rt, text, buttonFlags, &context.tree->font());
|
||||
}
|
||||
|
||||
|
||||
bool PropertyRowContainer::onActivate(const PropertyActivationEvent& e)
|
||||
{
|
||||
if (e.reason == e.REASON_RELEASE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (userReadOnly())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (inlined_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QMenu menu;
|
||||
generateMenu(menu, e.tree, true);
|
||||
e.tree->_setPressedRow(this);
|
||||
menu.exec(e.tree->_toScreen(QPoint(widgetPos_, pos_.y() + e.tree->_defaultRowHeight())));
|
||||
e.tree->_setPressedRow(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
ContainerMenuHandler* PropertyRowContainer::createMenuHandler(QPropertyTree* tree, PropertyRowContainer* container)
|
||||
{
|
||||
return new ContainerMenuHandler(tree, container);
|
||||
}
|
||||
|
||||
void PropertyRowContainer::generateMenu(QMenu& menu, QPropertyTree* tree, bool addActions)
|
||||
{
|
||||
ContainerMenuHandler* handler = createMenuHandler(tree, this);
|
||||
tree->addMenuHandler(handler);
|
||||
|
||||
if (fixedSize_)
|
||||
{
|
||||
if (!inlined_)
|
||||
{
|
||||
menu.addAction("[ Fixed Size Container ]")->setEnabled(false);
|
||||
}
|
||||
}
|
||||
else if (userReadOnly())
|
||||
{
|
||||
menu.addAction("[ Read Only Container ]")->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addActions)
|
||||
{
|
||||
PropertyRow* row = defaultRow(tree->model());
|
||||
if (row && row->isPointer())
|
||||
{
|
||||
QMenu* createItem = menu.addMenu("Add");
|
||||
menu.addSeparator();
|
||||
|
||||
PropertyRowPointer* pointerRow = static_cast<PropertyRowPointer*>(row);
|
||||
ClassMenuItemAdderRowContainer(this, tree).generateMenu(*createItem, tree->model()->typeStringList(pointerRow->baseType()));
|
||||
}
|
||||
else
|
||||
{
|
||||
menu.addAction("Insert", handler, SLOT(onMenuAddElement()));
|
||||
menu.addAction("Add", handler, SLOT(onMenuAppendElement()), Qt::Key_Insert);
|
||||
}
|
||||
}
|
||||
|
||||
if (!menu.isEmpty())
|
||||
{
|
||||
menu.addSeparator();
|
||||
}
|
||||
|
||||
QAction* removeAll = menu.addAction(pulledUp() ? "Remove Children" : "Remove All");
|
||||
removeAll->setShortcut(QKeySequence("Shift+Delete"));
|
||||
removeAll->setEnabled(!userReadOnly());
|
||||
QObject::connect(removeAll, SIGNAL(triggered()), handler, SLOT(onMenuRemoveAll()));
|
||||
}
|
||||
}
|
||||
|
||||
bool PropertyRowContainer::onContextMenu(QMenu& menu, QPropertyTree* tree)
|
||||
{
|
||||
if (!menu.isEmpty())
|
||||
{
|
||||
menu.addSeparator();
|
||||
}
|
||||
|
||||
generateMenu(menu, tree, true);
|
||||
|
||||
if (pulledUp())
|
||||
{
|
||||
return !menu.isEmpty();
|
||||
}
|
||||
|
||||
return PropertyRow::onContextMenu(menu, tree);
|
||||
}
|
||||
|
||||
|
||||
void ContainerMenuHandler::onMenuRemoveAll()
|
||||
{
|
||||
tree->model()->rowAboutToBeChanged(container);
|
||||
container->clear();
|
||||
tree->model()->rowChanged(container);
|
||||
}
|
||||
|
||||
PropertyRow* PropertyRowContainer::defaultRow(PropertyTreeModel* model)
|
||||
{
|
||||
PropertyRow* defaultType = model->defaultType(elementTypeName_);
|
||||
//YASLI_ASSERT(defaultType);
|
||||
//YASLI_ASSERT(defaultType->numRef() == 1);
|
||||
return defaultType;
|
||||
}
|
||||
|
||||
const PropertyRow* PropertyRowContainer::defaultRow(const PropertyTreeModel* model) const
|
||||
{
|
||||
const PropertyRow* defaultType = model->defaultType(elementTypeName_);
|
||||
return defaultType;
|
||||
}
|
||||
|
||||
void ContainerMenuHandler::onMenuAddElement()
|
||||
{
|
||||
container->addElement(tree, false);
|
||||
}
|
||||
|
||||
void ContainerMenuHandler::onMenuAppendElement()
|
||||
{
|
||||
container->addElement(tree, true);
|
||||
}
|
||||
|
||||
PropertyRow* PropertyRowContainer::addElement(QPropertyTree* tree, bool append)
|
||||
{
|
||||
tree->model()->rowAboutToBeChanged(this);
|
||||
PropertyRow* defaultType = defaultRow(tree->model());
|
||||
YASLI_ESCAPE(defaultType != 0, return 0);
|
||||
SharedPtr<PropertyRow> clonedRow = defaultType->clone(tree->model()->constStrings());
|
||||
if (count() == 0)
|
||||
{
|
||||
tree->expandRow(this);
|
||||
}
|
||||
if (append)
|
||||
{
|
||||
add(clonedRow);
|
||||
}
|
||||
else
|
||||
{
|
||||
addBefore(clonedRow, 0);
|
||||
}
|
||||
clonedRow->setHideChildren(tree->outlineMode());
|
||||
clonedRow->setLabelChanged();
|
||||
clonedRow->setLabelChangedToChildren();
|
||||
setMultiValue(false);
|
||||
if (expanded())
|
||||
{
|
||||
tree->model()->selectRow(clonedRow, true);
|
||||
}
|
||||
tree->expandRow(clonedRow);
|
||||
TreePath path = tree->model()->pathFromRow(clonedRow);
|
||||
tree->model()->rowChanged(clonedRow);
|
||||
clonedRow = tree->model()->rowFromPath(path);
|
||||
tree->update();
|
||||
clonedRow = tree->model()->rowFromPath(path);
|
||||
if (clonedRow)
|
||||
{
|
||||
PropertyTreeModel::Selection sel;
|
||||
sel.push_back(path);
|
||||
tree->model()->setSelection(sel);
|
||||
if (clonedRow->activateOnAdd())
|
||||
{
|
||||
PropertyActivationEvent e;
|
||||
e.tree = tree;
|
||||
e.reason = e.REASON_NEW_ELEMENT;
|
||||
clonedRow->onActivate(e);
|
||||
}
|
||||
}
|
||||
return clonedRow;
|
||||
}
|
||||
|
||||
|
||||
void ContainerMenuHandler::onMenuAppendPointerByIndex()
|
||||
{
|
||||
PropertyRow* defaultType = container->defaultRow(tree->model());
|
||||
PropertyRowPointer* defaultTypePointer = static_cast<PropertyRowPointer*>(defaultType);
|
||||
SharedPtr<PropertyRow> clonedRow = defaultType->clone(tree->model()->constStrings());
|
||||
if (container->count() == 0)
|
||||
{
|
||||
tree->expandRow(container);
|
||||
}
|
||||
container->add(clonedRow);
|
||||
clonedRow->setLabelChanged();
|
||||
clonedRow->setLabelChangedToChildren();
|
||||
clonedRow->setHideChildren(tree->outlineMode());
|
||||
container->setMultiValue(false);
|
||||
PropertyRowPointer* clonedRowPointer = static_cast<PropertyRowPointer*>(clonedRow.get());
|
||||
clonedRowPointer->setDerivedType(defaultTypePointer->derivedTypeName(), defaultTypePointer->factory());
|
||||
clonedRowPointer->setBaseType(defaultTypePointer->baseType());
|
||||
clonedRowPointer->setFactory(defaultTypePointer->factory());
|
||||
if (container->expanded())
|
||||
{
|
||||
tree->model()->selectRow(clonedRow, true);
|
||||
}
|
||||
tree->expandRow(clonedRowPointer);
|
||||
PropertyTreeModel::Selection sel = tree->model()->selection();
|
||||
|
||||
CreatePointerMenuHandler handler;
|
||||
handler.tree = tree;
|
||||
handler.row = clonedRowPointer;
|
||||
handler.index = pointerIndex;
|
||||
handler.onMenuCreateByIndex();
|
||||
tree->model()->setSelection(sel);
|
||||
tree->update();
|
||||
}
|
||||
|
||||
void ContainerMenuHandler::onMenuChildInsertBefore()
|
||||
{
|
||||
tree->model()->rowAboutToBeChanged(container);
|
||||
PropertyRow* defaultType = tree->model()->defaultType(container->elementTypeName());
|
||||
if (!defaultType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SharedPtr<PropertyRow> clonedRow = defaultType->clone(tree->model()->constStrings());
|
||||
clonedRow->setHideChildren(tree->outlineMode());
|
||||
element->setSelected(false);
|
||||
container->addBefore(clonedRow, element);
|
||||
container->setMultiValue(false);
|
||||
tree->model()->selectRow(clonedRow, true);
|
||||
PropertyTreeModel::Selection sel = tree->model()->selection();
|
||||
tree->model()->rowChanged(clonedRow);
|
||||
tree->model()->setSelection(sel);
|
||||
tree->update();
|
||||
clonedRow = tree->selectedRow();
|
||||
if (clonedRow->activateOnAdd())
|
||||
{
|
||||
PropertyActivationEvent e;
|
||||
e.tree = tree;
|
||||
e.reason = PropertyActivationEvent::REASON_NEW_ELEMENT;
|
||||
clonedRow->onActivate(e);
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerMenuHandler::onMenuChildRemove()
|
||||
{
|
||||
tree->model()->rowAboutToBeChanged(container);
|
||||
container->erase(element);
|
||||
container->setMultiValue(false);
|
||||
tree->model()->rowChanged(container);
|
||||
}
|
||||
|
||||
|
||||
void PropertyRowContainer::labelChanged()
|
||||
{
|
||||
swprintf(buttonLabel_, sizeof(buttonLabel_) / sizeof(buttonLabel_[0]), L"%zi", count());
|
||||
}
|
||||
|
||||
void PropertyRowContainer::serializeValue(IArchive& ar)
|
||||
{
|
||||
ar(ConstStringWrapper(constStrings_, elementTypeName_), "elementTypeName", "ElementTypeName");
|
||||
ar(fixedSize_, "fixedSize", "fixedSize");
|
||||
}
|
||||
|
||||
string PropertyRowContainer::valueAsString() const
|
||||
{
|
||||
char buf[32] = { 0 };
|
||||
sprintf_s(buf, "%d", (int)children_.size());
|
||||
return string(buf);
|
||||
}
|
||||
|
||||
const char* PropertyRowContainer::typeNameForFilter(QPropertyTree* tree) const
|
||||
{
|
||||
const PropertyRow* defaultType = defaultRow(tree->model());
|
||||
if (defaultType)
|
||||
{
|
||||
return defaultType->typeNameForFilter(tree);
|
||||
}
|
||||
else
|
||||
{
|
||||
return elementTypeName_;
|
||||
}
|
||||
}
|
||||
|
||||
bool PropertyRowContainer::processesKeyContainer([[maybe_unused]] QPropertyTree* tree, const QKeyEvent* ev)
|
||||
{
|
||||
if (ev->key() == Qt::Key_Delete && ev->modifiers() == Qt::SHIFT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ev->key() == Qt::Key_Insert && ev->modifiers() == Qt::NoModifier)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyRowContainer::processesKey(QPropertyTree* tree, const QKeyEvent* ev)
|
||||
{
|
||||
if (processesKeyContainer(tree, ev))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return PropertyRow::processesKey(tree, ev);
|
||||
}
|
||||
|
||||
bool PropertyRowContainer::onKeyDownContainer(QPropertyTree* tree, const QKeyEvent* ev)
|
||||
{
|
||||
if (userReadOnly())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<ContainerMenuHandler> handler(createMenuHandler(tree, this));
|
||||
if (ev->key() == Qt::Key_Delete && ev->modifiers() == Qt::SHIFT)
|
||||
{
|
||||
handler->onMenuRemoveAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ev->key() == Qt::Key_Insert && ev->modifiers() == Qt::NoModifier)
|
||||
{
|
||||
handler->onMenuAppendElement();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PropertyRowContainer::onKeyDown(QPropertyTree* tree, const QKeyEvent* ev)
|
||||
{
|
||||
if (onKeyDownContainer(tree, ev))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return PropertyRow::onKeyDown(tree, ev);
|
||||
}
|
||||
|
||||
int PropertyRowContainer::widgetSizeMin(const QPropertyTree* tree) const
|
||||
{
|
||||
return inlined_ ? 0 : (userWidgetSize() >= 0 ? userWidgetSize() : aznumeric_cast<int>(tree->_defaultRowHeight() * 1.7f));
|
||||
}
|
||||
|
||||
#include <QPropertyTree/moc_PropertyRowContainer.cpp>
|
||||
@@ -1,96 +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_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCONTAINER_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCONTAINER_H
|
||||
#pragma once
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "PropertyRow.h"
|
||||
#endif
|
||||
|
||||
|
||||
class EDITOR_COMMON_API PropertyRowContainer;
|
||||
struct EDITOR_COMMON_API ContainerMenuHandler
|
||||
: PropertyRowMenuHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
QPropertyTree * tree;
|
||||
PropertyRowContainer* container;
|
||||
PropertyRow* element;
|
||||
int pointerIndex;
|
||||
|
||||
ContainerMenuHandler(QPropertyTree* tree, PropertyRowContainer* container);
|
||||
|
||||
public slots:
|
||||
virtual void onMenuAddElement();
|
||||
virtual void onMenuAppendElement();
|
||||
virtual void onMenuAppendPointerByIndex();
|
||||
virtual void onMenuRemoveAll();
|
||||
virtual void onMenuChildInsertBefore();
|
||||
virtual void onMenuChildRemove();
|
||||
};
|
||||
|
||||
class EDITOR_COMMON_API PropertyRowContainer
|
||||
: public PropertyRow
|
||||
{
|
||||
public:
|
||||
PropertyRowContainer();
|
||||
bool isContainer() const{ return true; }
|
||||
bool onActivate(const PropertyActivationEvent& e);
|
||||
bool onContextMenu(QMenu& item, QPropertyTree* tree);
|
||||
virtual ContainerMenuHandler* createMenuHandler(QPropertyTree* tree, PropertyRowContainer* container) override;
|
||||
void redraw(const PropertyDrawContext& context);
|
||||
bool processesKeyContainer(QPropertyTree* tree, const QKeyEvent* ev);
|
||||
bool processesKey(QPropertyTree* tree, const QKeyEvent* ev) override;
|
||||
bool onKeyDownContainer(QPropertyTree* tree, const QKeyEvent* key);
|
||||
bool onKeyDown(QPropertyTree* tree, const QKeyEvent* key) override;
|
||||
|
||||
void labelChanged() override;
|
||||
bool isStatic() const{ return false; }
|
||||
bool isSelectable() const{ return userWidgetSize() == 0 ? false : true; }
|
||||
PropertyRow* addElement(QPropertyTree* tree, bool append);
|
||||
void setInlined(bool inlined) { inlined_ = inlined; }
|
||||
bool isInlined() const{ return inlined_; }
|
||||
|
||||
PropertyRow* defaultRow(PropertyTreeModel* model);
|
||||
const PropertyRow* defaultRow(const PropertyTreeModel* model) const;
|
||||
void serializeValue(Serialization::IArchive& ar);
|
||||
|
||||
const char* elementTypeName() const{ return elementTypeName_; }
|
||||
using PropertyRow::setValueAndContext;
|
||||
virtual void setValueAndContext(const Serialization::IContainer& value, [[maybe_unused]] Serialization::IArchive& ar)
|
||||
{
|
||||
fixedSize_ = value.isFixedSize();
|
||||
elementTypeName_ = value.elementType().name();
|
||||
serializer_.setPointer(value.pointer());
|
||||
serializer_.setType(value.containerType());
|
||||
}
|
||||
const char* typeNameForFilter(QPropertyTree* tree) const override;
|
||||
string valueAsString() const;
|
||||
// C-array is an example of fixed size container
|
||||
bool isFixedSize() const{ return fixedSize_; }
|
||||
WidgetPlacement widgetPlacement() const override { return inlined_ ? WIDGET_NONE : WIDGET_AFTER_NAME; }
|
||||
int widgetSizeMin(const QPropertyTree* tree) const override;
|
||||
|
||||
protected:
|
||||
virtual void generateMenu(QMenu& menu, QPropertyTree* tree, bool addActions);
|
||||
|
||||
const char* elementTypeName_;
|
||||
wchar_t buttonLabel_[8];
|
||||
bool fixedSize_;
|
||||
bool inlined_;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCONTAINER_H
|
||||
@@ -1,84 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include "PropertyRowField.h"
|
||||
#include "PropertyDrawContext.h"
|
||||
#include "QPropertyTree.h"
|
||||
#include "QPropertyTreeStyle.h"
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
enum { BUTTON_SIZE = 16 };
|
||||
|
||||
QRect PropertyRowField::fieldRect(const QPropertyTree* tree) const
|
||||
{
|
||||
QRect fieldRect = widgetRect(tree);
|
||||
fieldRect.setRight(fieldRect.right() - buttonCount() * BUTTON_SIZE);
|
||||
return fieldRect;
|
||||
}
|
||||
|
||||
bool PropertyRowField::onActivate(const PropertyActivationEvent& e)
|
||||
{
|
||||
if (e.reason == e.REASON_PRESS) {
|
||||
int buttonCount = this->buttonCount();
|
||||
QRect buttonsRect = widgetRect(e.tree);
|
||||
buttonsRect.setLeft(buttonsRect.right() - buttonCount * BUTTON_SIZE);
|
||||
|
||||
if (buttonsRect.contains(e.clickPoint)) {
|
||||
int buttonIndex = buttonCount - (e.clickPoint.x() - buttonsRect.x()) / BUTTON_SIZE - 1;
|
||||
if (buttonIndex >= 0 && buttonIndex < buttonCount)
|
||||
{
|
||||
if (onActivateButton(buttonIndex, e))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PropertyRow::onActivate(e);
|
||||
}
|
||||
|
||||
void PropertyRowField::redraw(const PropertyDrawContext& context)
|
||||
{
|
||||
int buttonCount = this->buttonCount();
|
||||
int offset = 0;
|
||||
for (int i = 0; i < buttonCount; ++i) {
|
||||
const QIcon& icon = buttonIcon(context.tree, i);
|
||||
QRect iconRect(context.widgetRect.right() - offset - BUTTON_SIZE, context.widgetRect.top(), BUTTON_SIZE, context.widgetRect.height());
|
||||
icon.paint(context.painter, iconRect, Qt::AlignCenter, userReadOnly() ? QIcon::Disabled : QIcon::Normal);
|
||||
offset += BUTTON_SIZE;
|
||||
}
|
||||
|
||||
int iconSpace = offset ? offset + 2 : 0;
|
||||
if(multiValue())
|
||||
context.drawEntry(L" ... ", false, true, iconSpace);
|
||||
else if(userReadOnly())
|
||||
context.drawValueText(pulledSelected(), valueAsWString().c_str());
|
||||
else
|
||||
context.drawEntry(valueAsWString().c_str(), usePathEllipsis(), false, iconSpace);
|
||||
|
||||
}
|
||||
|
||||
const QIcon& PropertyRowField::buttonIcon([[maybe_unused]] const QPropertyTree* tree, [[maybe_unused]] int index) const
|
||||
{
|
||||
static QIcon defaultIcon;
|
||||
return defaultIcon;
|
||||
}
|
||||
|
||||
int PropertyRowField::widgetSizeMin(const QPropertyTree* tree) const
|
||||
{
|
||||
if (userWidgetSize() >= 0)
|
||||
return userWidgetSize();
|
||||
|
||||
if (userWidgetToContent_)
|
||||
return widthCache_.getOrUpdate(tree, this, 0);
|
||||
else
|
||||
return 40;
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWFIELD_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWFIELD_H
|
||||
#pragma once
|
||||
|
||||
#include "PropertyRow.h"
|
||||
class QIcon;
|
||||
|
||||
class PropertyRowField : public PropertyRow
|
||||
{
|
||||
public:
|
||||
WidgetPlacement widgetPlacement() const override{ return WIDGET_VALUE; }
|
||||
int widgetSizeMin(const QPropertyTree* tree) const override;
|
||||
|
||||
virtual int buttonCount() const{ return 0; }
|
||||
virtual const QIcon& buttonIcon(const QPropertyTree* tree, int index) const;
|
||||
virtual bool usePathEllipsis() const { return false; }
|
||||
virtual bool onActivateButton([[maybe_unused]] int buttonIndex, [[maybe_unused]] const PropertyActivationEvent& e) { return false; }
|
||||
|
||||
void redraw(const PropertyDrawContext& context) override;
|
||||
bool onActivate(const PropertyActivationEvent& e) override;
|
||||
protected:
|
||||
QRect fieldRect(const QPropertyTree* tree) const;
|
||||
void drawButtons(int* offset);
|
||||
|
||||
mutable RowWidthCache widthCache_;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWFIELD_H
|
||||
@@ -1,119 +0,0 @@
|
||||
/**
|
||||
* yasli - Serialization Library.
|
||||
* Copyright (C) 2007-2013 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#include "EditorCommon_precompiled.h"
|
||||
#include "Serialization/ClassFactory.h"
|
||||
|
||||
#include "PropertyDrawContext.h"
|
||||
#include "PropertyRowImpl.h"
|
||||
#include "QPropertyTree.h"
|
||||
#include "PropertyTreeModel.h"
|
||||
#include "Serialization.h"
|
||||
#include "Color.h"
|
||||
#include "Serialization/Decorators/IconXPM.h"
|
||||
using Serialization::IconXPM;
|
||||
using Serialization::IconXPMToggle;
|
||||
|
||||
class PropertyRowIconXPM : public PropertyRow{
|
||||
public:
|
||||
void redraw(const PropertyDrawContext& context)
|
||||
{
|
||||
QRect rect = context.widgetRect;
|
||||
context.drawIcon(rect, icon_);
|
||||
}
|
||||
|
||||
bool isLeaf() const{ return true; }
|
||||
bool isStatic() const{ return false; }
|
||||
bool isSelectable() const{ return false; }
|
||||
|
||||
bool onActivate([[maybe_unused]] const PropertyActivationEvent& e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override {
|
||||
YASLI_ESCAPE(ser.size() == sizeof(IconXPM), return);
|
||||
icon_ = *(IconXPM*)(ser.pointer());
|
||||
}
|
||||
wstring valueAsWString() const{ return L""; }
|
||||
WidgetPlacement widgetPlacement() const{ return WIDGET_ICON; }
|
||||
void serializeValue([[maybe_unused]] Serialization::IArchive& ar) {}
|
||||
int widgetSizeMin(const QPropertyTree* tree) const override{ return tree->_defaultRowHeight(); }
|
||||
int height() const{ return 16; }
|
||||
protected:
|
||||
IconXPM icon_;
|
||||
};
|
||||
|
||||
class PropertyRowIconToggle : public PropertyRow{
|
||||
public:
|
||||
void redraw(const PropertyDrawContext& context) override
|
||||
{
|
||||
IconXPM& icon = value_ ? iconTrue_ : iconFalse_;
|
||||
context.drawIcon(context.widgetRect, icon);
|
||||
}
|
||||
|
||||
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override {
|
||||
YASLI_ESCAPE(ser.size() == sizeof(IconXPMToggle), return);
|
||||
const IconXPMToggle* icon = (IconXPMToggle*)(ser.pointer());
|
||||
iconTrue_ = icon->iconTrue_;
|
||||
iconFalse_ = icon->iconFalse_;
|
||||
value_ = icon->value_;
|
||||
}
|
||||
|
||||
bool assignTo(const Serialization::SStruct& ser) const override
|
||||
{
|
||||
IconXPMToggle* toggle = (IconXPMToggle*)ser.pointer();
|
||||
toggle->value_ = value_;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isLeaf() const override{ return true; }
|
||||
bool isStatic() const override{ return false; }
|
||||
bool isSelectable() const override{ return true; }
|
||||
bool onActivate(const PropertyActivationEvent& e)
|
||||
{
|
||||
if (e.reason != e.REASON_RELEASE)
|
||||
{
|
||||
e.tree->model()->rowAboutToBeChanged(this);
|
||||
value_ = !value_;
|
||||
e.tree->model()->rowChanged(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
DragCheckBegin onMouseDragCheckBegin() override
|
||||
{
|
||||
if (userReadOnly())
|
||||
return DRAG_CHECK_IGNORE;
|
||||
return value_ ? DRAG_CHECK_UNSET : DRAG_CHECK_SET;
|
||||
}
|
||||
bool onMouseDragCheck(QPropertyTree* tree, bool value) override
|
||||
{
|
||||
if (value_ != value) {
|
||||
tree->model()->rowAboutToBeChanged(this);
|
||||
value_ = value;
|
||||
tree->model()->rowChanged(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
wstring valueAsWString() const{ return value_ ? L"true" : L"false"; }
|
||||
WidgetPlacement widgetPlacement() const{ return WIDGET_ICON; }
|
||||
|
||||
int widgetSizeMin(const QPropertyTree* tree) const{ return tree->_defaultRowHeight(); }
|
||||
int height() const{ return 16; }
|
||||
|
||||
IconXPM iconTrue_;
|
||||
IconXPM iconFalse_;
|
||||
bool value_;
|
||||
};
|
||||
|
||||
REGISTER_PROPERTY_ROW(IconXPM, PropertyRowIconXPM);
|
||||
REGISTER_PROPERTY_ROW(IconXPMToggle, PropertyRowIconToggle);
|
||||
DECLARE_SEGMENT(PropertyRowIconXPM)
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* wWidgets - Lightweight UI Toolkit.
|
||||
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
||||
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
||||
*
|
||||
* This code is distributed under the MIT License:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWIMPL_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWIMPL_H
|
||||
#pragma once
|
||||
|
||||
#include "Serialization/STL.h"
|
||||
#include "PropertyRowField.h"
|
||||
#include "Serialization.h"
|
||||
|
||||
template<class Type>
|
||||
class PropertyRowImpl;
|
||||
|
||||
template<class Type>
|
||||
class PropertyRowImpl : public PropertyRowField{
|
||||
public:
|
||||
bool assignTo(const Serialization::SStruct& ser) const override {
|
||||
*reinterpret_cast<Type*>(ser.pointer()) = value();
|
||||
return true;
|
||||
}
|
||||
bool isLeaf() const override{ return true; }
|
||||
bool isStatic() const override{ return false; }
|
||||
void setValue(const Type& value) { value_ = value; }
|
||||
Type& value() { return value_; }
|
||||
const Type& value() const{ return value_; }
|
||||
|
||||
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override {
|
||||
YASLI_ESCAPE(ser.size() == sizeof(Type), return);
|
||||
value_ = *(Type*)(ser.pointer());
|
||||
}
|
||||
|
||||
void serializeValue(Serialization::IArchive& ar) override{
|
||||
ar(value_, "value", "Value");
|
||||
}
|
||||
protected:
|
||||
Type value_;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWIMPL_H
|
||||
@@ -1,152 +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 "EditorCommon_precompiled.h"
|
||||
#include "PropertyRowLocalFrame.h"
|
||||
#include <QIcon>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include "QPropertyTree.h"
|
||||
#include "PropertyTreeModel.h"
|
||||
#include <Serialization/Decorators/IGizmoSink.h>
|
||||
#include <Serialization/Decorators/LocalFrame.h>
|
||||
#include "Serialization/ClassFactory.h"
|
||||
#include "PropertyDrawContext.h"
|
||||
#include "Serialization.h"
|
||||
#include <Serialization/Decorators/LocalFrameImpl.h>
|
||||
|
||||
using Serialization::LocalPosition;
|
||||
|
||||
void LocalFrameMenuHandler::onMenuReset()
|
||||
{
|
||||
self->reset(tree);
|
||||
}
|
||||
|
||||
PropertyRowLocalFrameBase::PropertyRowLocalFrameBase()
|
||||
: m_sink(0)
|
||||
, m_gizmoIndex(-1)
|
||||
, m_handle(0)
|
||||
, m_reset(false)
|
||||
{
|
||||
}
|
||||
|
||||
PropertyRowLocalFrameBase::~PropertyRowLocalFrameBase()
|
||||
{
|
||||
m_sink = 0;
|
||||
}
|
||||
|
||||
bool PropertyRowLocalFrameBase::onActivate(const PropertyActivationEvent& e)
|
||||
{
|
||||
if (e.reason == e.REASON_RELEASE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
string PropertyRowLocalFrameBase::valueAsString() const
|
||||
{
|
||||
return string();
|
||||
}
|
||||
|
||||
bool PropertyRowLocalFrameBase::onContextMenu(QMenu& menu, QPropertyTree* tree)
|
||||
{
|
||||
Serialization::SharedPtr<PropertyRow> selfPointer(this);
|
||||
|
||||
LocalFrameMenuHandler* handler = new LocalFrameMenuHandler(tree, this);
|
||||
|
||||
menu.addAction("Reset", handler, SLOT(onMenuReset()));
|
||||
|
||||
tree->addMenuHandler(handler);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PropertyRowLocalFrameBase::reset(QPropertyTree* tree)
|
||||
{
|
||||
tree->model()->rowAboutToBeChanged(this);
|
||||
m_reset = true;
|
||||
tree->model()->rowChanged(this);
|
||||
}
|
||||
|
||||
void PropertyRowLocalFrameBase::redraw(const PropertyDrawContext& context)
|
||||
{
|
||||
static QIcon gizmo("Icons/animation/gizmo_location.png");
|
||||
gizmo.paint(context.painter, context.widgetRect.adjusted(1, 1, 1, 1), Qt::AlignRight);
|
||||
}
|
||||
|
||||
static void ResetTransform(Serialization::LocalPosition* l) { *l->value = ZERO; }
|
||||
static void ResetTransform(Serialization::LocalOrientation* l) { *l->value = IDENTITY; }
|
||||
static void ResetTransform(Serialization::LocalFrame* l) { *l->position = ZERO; *l->rotation = IDENTITY; }
|
||||
|
||||
template<class TLocal>
|
||||
class PropertyRowLocalFrameImpl
|
||||
: public PropertyRowLocalFrameBase
|
||||
{
|
||||
public:
|
||||
void setValueAndContext(const Serialization::SStruct& ser, Serialization::IArchive& ar) override
|
||||
{
|
||||
serializer_ = ser;
|
||||
|
||||
TLocal* value = (TLocal*)ser.pointer();
|
||||
m_handle = value->handle;
|
||||
m_reset = false;
|
||||
|
||||
if (label() && label()[0])
|
||||
{
|
||||
m_sink = ar.FindContext<Serialization::IGizmoSink>();
|
||||
if (m_sink)
|
||||
{
|
||||
m_gizmoIndex = m_sink->Write(*value, m_gizmoFlags, m_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void closeNonLeaf(const Serialization::SStruct& ser, Serialization::IArchive& ar) override
|
||||
{
|
||||
if (label() && label()[0] && ar.IsInput())
|
||||
{
|
||||
TLocal& value = *((TLocal*)ser.pointer());
|
||||
if (m_sink)
|
||||
{
|
||||
if (m_sink->CurrentGizmoIndex() == m_gizmoIndex)
|
||||
{
|
||||
m_sink->Read(&value, &m_gizmoFlags, m_handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sink->SkipRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool assignTo(const Serialization::SStruct& ser) const
|
||||
{
|
||||
if (m_reset)
|
||||
{
|
||||
TLocal& value = *((TLocal*)ser.pointer());
|
||||
ResetTransform(&value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef PropertyRowLocalFrameImpl<Serialization::LocalPosition> PropertyRowLocalPosition;
|
||||
typedef PropertyRowLocalFrameImpl<Serialization::LocalOrientation> PropertyRowLocalOrientation;
|
||||
typedef PropertyRowLocalFrameImpl<Serialization::LocalFrame> PropertyRowLocalFrame;
|
||||
|
||||
REGISTER_PROPERTY_ROW(Serialization::LocalPosition, PropertyRowLocalPosition);
|
||||
REGISTER_PROPERTY_ROW(Serialization::LocalOrientation, PropertyRowLocalOrientation);
|
||||
REGISTER_PROPERTY_ROW(Serialization::LocalFrame, PropertyRowLocalFrame);
|
||||
|
||||
#include <QPropertyTree/moc_PropertyRowLocalFrame.cpp>
|
||||
@@ -1,70 +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_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWLOCALFRAME_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWLOCALFRAME_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "Serialization/Decorators/IGizmoSink.h"
|
||||
#include "PropertyRowField.h"
|
||||
#include "QPropertyTree.h"
|
||||
#endif
|
||||
|
||||
struct IGizmoSink;
|
||||
|
||||
class PropertyRowLocalFrameBase
|
||||
: public PropertyRow
|
||||
{
|
||||
public:
|
||||
PropertyRowLocalFrameBase();
|
||||
~PropertyRowLocalFrameBase();
|
||||
|
||||
bool isLeaf() const override { return m_reset; }
|
||||
bool isStatic() const override { return false; }
|
||||
|
||||
bool onActivate(const PropertyActivationEvent& e) override;
|
||||
|
||||
WidgetPlacement widgetPlacement() const override { return WIDGET_AFTER_PULLED; }
|
||||
int widgetSizeMin(const QPropertyTree* tree) const override { return tree->_defaultRowHeight(); }
|
||||
|
||||
string valueAsString() const override;
|
||||
bool onContextMenu(QMenu& menu, QPropertyTree* tree) override;
|
||||
const void* searchHandle() const override { return m_handle; }
|
||||
void redraw(const PropertyDrawContext& context) override;
|
||||
|
||||
void reset(QPropertyTree* tree);
|
||||
protected:
|
||||
Serialization::IGizmoSink* m_sink;
|
||||
const void* m_handle;
|
||||
int m_gizmoIndex;
|
||||
mutable Serialization::GizmoFlags m_gizmoFlags;
|
||||
bool m_reset;
|
||||
};
|
||||
|
||||
struct LocalFrameMenuHandler
|
||||
: PropertyRowMenuHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QPropertyTree * tree;
|
||||
PropertyRowLocalFrameBase* self;
|
||||
|
||||
LocalFrameMenuHandler(QPropertyTree* tree, PropertyRowLocalFrameBase* self)
|
||||
: tree(tree)
|
||||
, self(self) {}
|
||||
public slots:
|
||||
void onMenuReset();
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWLOCALFRAME_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user