!XF (Sandbox) (DEV-7472) Integrating ce_task_proptree2_improvements to ce/main....
[CRYENGINE.git] / Code / Sandbox / Plugins / EditorCommon / Serialization / QPropertyTree2 / ResourcePicker.cpp
blobf5af8c11b429baaabe0bb25c159f0cbd064e06ca
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
2 #include "StdAfx.h"
3 #include "ResourcePicker.h"
4 #include "AssetDragDropLineEdit.h"
5 #include "AssetSystem/Asset.h"
6 #include "AssetSystem/AssetType.h"
8 #include <CrySerialization/Decorators/Resources.h>
9 #include <CrySerialization/Decorators/ResourceSelector.h>
11 #include "IResourceSelectorHost.h"
12 #include "CryIcon.h"
14 #include <IEditor.h>
15 #include <IUndoManager.h>
16 #include <QBoxLayout>
17 #include <QEvent>
18 #include <QLineEdit>
19 #include <QToolButton>
21 namespace Private_ResourcePickers
24 class ResourceSelectionCallback : public IResourceSelectionCallback
26 public:
27 virtual void SetValue(const char* newValue) override
29 if (m_onValueChanged)
31 m_onValueChanged(newValue);
35 void SetValueChangedCallback(const std::function<void(const char*)>& onValueChanged)
37 m_onValueChanged = onValueChanged;
40 private:
41 std::function<void(const char*)> m_onValueChanged;
45 CResourcePicker::CResourcePicker()
46 : m_pSelector(nullptr)
48 m_pLineEdit = new CAssetDragDropLineEdit();
50 m_pLayout = new QHBoxLayout();
51 m_pLayout->addWidget(m_pLineEdit);
52 m_pLayout->setMargin(0);
54 setLayout(m_pLayout);
55 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
57 // needs to be lambda because of default param
58 connect(m_pLineEdit, &QLineEdit::editingFinished, [this]() { OnValueChanged(m_pLineEdit->text().toStdString().c_str()); });
59 //Register to asset drop event from line picker
60 m_pLineEdit->signalValidAssetDropped.Connect([this](CAsset& newAsset)
62 OnValueChanged(newAsset.GetFile(0));
63 });
66 bool CResourcePicker::event(QEvent* pEvent)
68 if (pEvent->type() == QEvent::ToolTip)
70 if (m_pSelector->ShowTooltip(m_context, m_pLineEdit->text().toStdString().c_str()))
72 return true;
76 return QWidget::event(pEvent);
79 void CResourcePicker::OnValueChanged(const char* newValue)
81 //If we are confirming a continuous change (aka pressing ok on the resource selector) skip validation because the data
82 //has already been validated in the continuous step
83 if (!IsContinuousChange())
85 //in case of continuous change m_previousValue is already set to the last value in the resource picker, so it's fine to go ahead and submit and undo. If we are not doing continuous edit we need to actually skip repetition
86 if (m_previousValue == newValue)
88 return;
91 //Run validation check
92 SResourceValidationResult validatedPath = m_pSelector->ValidateValue(m_context, newValue, m_previousValue.toStdString().c_str());
94 //An empty validatedResource is not valid, but a set to an empty state needs to be allowed
95 if (!validatedPath.isValid && !validatedPath.validatedResource.empty())
97 CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_WARNING, "Invalid %s: %s", m_context.typeName, newValue);
98 m_pLineEdit->setText(m_previousValue);
99 if (m_pLineEdit->hasFocus())
101 m_pLineEdit->selectAll();
104 //we don't want an undo to be registered here as it will be just undoing to the same value (m_previousValue)
105 return;
109 m_previousValue = newValue;
111 OnChanged();
113 if (m_pLineEdit->hasFocus())
115 m_pLineEdit->selectAll();
119 void CResourcePicker::OnValueContinuousChange(const char* newValue)
121 m_pLineEdit->setText(newValue);
123 if (m_previousValue == newValue)
125 return;
128 // Run validation check
129 SResourceValidationResult validatedPath = m_pSelector->ValidateValue(m_context, newValue, m_previousValue.toStdString().c_str());
131 if (!validatedPath.isValid)
133 CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_WARNING, "Invalid %s: %s", m_context.typeName, newValue);
134 m_pLineEdit->setText(m_previousValue);
135 if (m_pLineEdit->hasFocus())
137 m_pLineEdit->selectAll();
139 return;
142 OnContinuousChanged();
144 //If we are in continuous edit it means that we are using the resource picker. The picker sets the string in the line edit to an always valid value
145 //and since we are using the picker the lined edit actually stores the previous value
146 m_previousValue = m_pLineEdit->text();
148 if (m_pLineEdit->hasFocus())
150 m_pLineEdit->selectAll();
154 void CResourcePicker::OnPick()
156 CRY_ASSERT(m_pSelector);
158 Private_ResourcePickers::ResourceSelectionCallback callback;
159 callback.SetValueChangedCallback([this](const char* newValue) { OnValueContinuousChange(newValue); });
160 m_context.callback = &callback;
162 SResourceSelectionResult result = m_pSelector->SelectResource(m_context, m_pLineEdit->text().toStdString().c_str());
164 if (result.selectionAccepted)
166 m_pLineEdit->setText(result.selectedResource.c_str());
167 OnValueChanged(result.selectedResource.c_str());
169 else
171 m_previousValue = result.selectedResource.c_str();
172 OnDiscarded();
176 void CResourcePicker::OnEdit()
178 m_pSelector->EditResource(m_context, m_pLineEdit->text().toStdString().c_str());
181 void CResourcePicker::OnPickLegacy()
183 m_context.useLegacyPicker = true;
184 OnPick();
185 m_context.useLegacyPicker = false;
188 void CResourcePicker::Init(Serialization::IResourceSelector* pSelector, const yasli::Archive& ar)
190 // If we have a valid selector and the type hasn't changed for this row, then return
191 if (m_pSelector && strcmp(pSelector->resourceType, m_context.typeName) == 0)
193 return;
196 m_type = pSelector->resourceType;
197 m_pSelector = GetIEditor()->GetResourceSelectorHost()->GetSelector(m_type.c_str());
199 m_context.resourceSelectorEntry = m_pSelector;
200 m_context.typeName = m_type.c_str();
201 m_context.parentWidget = QWidget::window(); // TODO: This used to be the root widget for the property tree
202 m_context.pCustomParams = pSelector->pCustomParams;
204 Serialization::TypeID contextTypeID = m_pSelector->GetContextType();
205 if (contextTypeID)
207 m_context.contextObject = ar.contextByType(contextTypeID);
208 m_context.contextObjectType = contextTypeID;
211 // Remove all buttons if we're reusing this row and create on demand based on the requirements of the selector
212 while (m_pLayout->count() > 1)
214 QLayoutItem* pItem = m_pLayout->itemAt(1);
215 m_pLayout->removeItem(pItem);
216 delete pItem;
219 if (m_pSelector->HasLegacyPicker())
221 AddButton("icons:General/LegacyResourceSelectorPicker.ico", "Legacy Open", &CResourcePicker::OnPickLegacy);
224 if (m_pSelector->CanEdit())
226 AddButton("icons:General/Edit_Asset.ico", "Edit", &CResourcePicker::OnEdit);
229 AddButton("icons:General/Folder.ico", "Open", &CResourcePicker::OnPick);
231 m_pLineEdit->SetResourceSelector(m_pSelector);
234 void CResourcePicker::AddButton(const char* szIconPath, const char* szToolTip, void (CResourcePicker::* pCallback)())
236 QToolButton* pButton = new QToolButton();
237 pButton->setIcon(CryIcon(szIconPath));
238 pButton->setToolTip(szToolTip);
239 m_pLayout->addWidget(pButton);
240 connect(pButton, &QToolButton::clicked, this, pCallback);
243 void CResourcePicker::SetValue(void* pValue, const yasli::TypeID& type, const yasli::Archive& ar)
245 //Note that when we get here we have no way of knowing the previous value, the pSelector holds the new value and the line edit too as we might have modified it with a new (possibly invalid) path
246 if (type != yasli::TypeID::get<Serialization::IResourceSelector>())
248 return;
251 Serialization::IResourceSelector* pSelector = (Serialization::IResourceSelector*)pValue;
253 Init(pSelector, ar);
255 m_pLineEdit->setText(pSelector->GetValue());
258 void CResourcePicker::GetValue(void* pValue, const yasli::TypeID& type) const
260 if (type != yasli::TypeID::get<Serialization::IResourceSelector>())
262 return;
265 Serialization::IResourceSelector* pSelector = (Serialization::IResourceSelector*)pValue;
266 pSelector->SetValue(m_pLineEdit->text().toStdString().c_str());
269 void CResourcePicker::Serialize(Serialization::IArchive& ar)
271 string lineEditText = m_pLineEdit->text().toStdString().c_str();
272 ar(lineEditText, "text", "Text");
273 QString newLineEditTextValue = lineEditText;
275 if (newLineEditTextValue != m_previousValue && ar.isInput())
277 m_pLineEdit->setText(newLineEditTextValue);
278 OnValueChanged(lineEditText);
282 void CResourcePicker::SetMultiEditValue()
284 m_pLineEdit->setText("");
285 m_pLineEdit->setPlaceholderText("Multiple Values");
288 namespace Serialization
290 REGISTER_PROPERTY_WIDGET(IResourceSelector, CResourcePicker);