1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
4 Relationship between Variable data, PropertyItem value string, and draw string
8 PropertyItem.m_value string:
9 Converted via Variable.Get/SetDisplayValue
10 = Same as Variable.Get(string) and Variable.Set(string), EXCEPT:
11 Enums converted to enum values
12 Color reformated to 8-bit range
13 SOHelper removes prefix before :
15 Same as .m_value, EXCEPT
16 .valueMultiplier conversion applied
17 Bool reformated to "True/False"
18 Curves replaced with "[Curve]"
19 bShowChildren vars add child draw strings
21 Set to .m_value, EXCEPT
22 Bool converted to "1/0"
23 File text replace \ with /
24 Vector expand single elem to 3 repeated
28 #include "PropertyItem.h"
29 #include "PropertyCtrl.h"
30 #include "InPlaceEdit.h"
31 #include "InPlaceComboBox.h"
32 #include "InPlaceButton.h"
33 #include "FillSliderCtrl.h"
34 #include "SplineCtrl.h"
35 #include "ColorGradientCtrl.h"
36 #include "SliderCtrlEx.h"
38 #include "Dialogs/CustomColorDialog.h"
40 #include "Controls/SharedFonts.h"
41 #include "Controls/NumberCtrl.h"
43 #include "UIEnumsDatabase.h"
44 #include "Dialogs/SelectSequenceDialog.h"
45 #include "Dialogs/GenericSelectItemDialog.h"
46 #include "Dialogs/SelectMissionObjectiveDialog.h"
48 #include <CrySystem/ITimer.h>
49 #include <CrySystem/ILocalizationManager.h>
51 #include "ISourceControl.h"
53 #include <CryString/CryName.h>
55 #include "Util/UIEnumerations.h"
56 #include "IDataBaseItem.h"
57 #include "IDataBaseManager.h"
58 #include "Objects/BaseObject.h"
60 #include "IResourceSelectorHost.h"
61 #include <CryString/UnicodeFunctions.h>
62 #include "Controls/QuestionDialog.h"
63 #include "Util/MFCUtil.h"
64 #include "Util/FileUtil.h"
65 #include <CryMovie/IMovieSystem.h>
67 //////////////////////////////////////////////////////////////////////////
68 #define CMD_ADD_CHILD_ITEM 100
69 #define CMD_ADD_ITEM 101
70 #define CMD_DELETE_ITEM 102
72 #define BUTTON_WIDTH (16)
73 #define NUMBER_CTRL_WIDTH 60
75 //////////////////////////////////////////////////////////////////////////
76 //! Undo object for Variable in property control..
77 class CUndoVariableChange
: public IUndoObject
80 CUndoVariableChange(IVariable
* var
, const char* undoDescription
)
82 // Stores the current state of this object.
84 m_undoDescription
= undoDescription
;
86 m_undo
= m_var
->Clone(false);
91 int size
= sizeof(*this);
93 //size += m_var->GetSize();
95 size
+= m_undo
->GetSize();
97 size
+= m_redo
->GetSize();
100 virtual const char* GetDescription() { return m_undoDescription
; };
101 virtual void Undo(bool bUndo
)
105 m_redo
= m_var
->Clone(false);
107 m_var
->CopyValue(m_undo
);
112 m_var
->CopyValue(m_redo
);
116 CString m_undoDescription
;
117 _smart_ptr
<IVariable
> m_undo
;
118 _smart_ptr
<IVariable
> m_redo
;
119 _smart_ptr
<IVariable
> m_var
;
122 //////////////////////////////////////////////////////////////////////////
130 } s_propertyTypeNames
[] =
132 { IVariable::DT_SIMPLE
, "Bool", ePropertyBool
, 2 },
133 { IVariable::DT_SIMPLE
, "Int", ePropertyInt
, 0 },
134 { IVariable::DT_SIMPLE
, "Float", ePropertyFloat
, 0 },
135 { IVariable::DT_SIMPLE
, "Vector", ePropertyVector2
, 10 },
136 { IVariable::DT_SIMPLE
, "Vector", ePropertyVector
, 10 },
137 { IVariable::DT_SIMPLE
, "Vector", ePropertyVector4
, 10 },
138 { IVariable::DT_SIMPLE
, "String", ePropertyString
, 3 },
139 { IVariable::DT_PERCENT
, "Float", ePropertyInt
, 13 },
140 { IVariable::DT_BOOLEAN
, "Boolean", ePropertyBool
, 2 },
141 { IVariable::DT_COLOR
, "Color", ePropertyColor
, 1 },
142 { IVariable::DT_CURVE
| IVariable::DT_PERCENT
, "FloatCurve", ePropertyFloatCurve
, 13 },
143 { IVariable::DT_CURVE
| IVariable::DT_COLOR
, "ColorCurve", ePropertyColorCurve
, 1 },
144 { IVariable::DT_ANGLE
, "Angle", ePropertyAngle
, 0 },
145 { IVariable::DT_FILE
, "File", ePropertyFile
, 7 },
146 { IVariable::DT_TEXTURE
, "Texture", ePropertyTexture
, 4 },
147 { IVariable::DT_ANIMATION
, "Animation", ePropertyAnimation
, -1 },
148 { IVariable::DT_OBJECT
, "Model", ePropertyModel
, 5 },
149 { IVariable::DT_SIMPLE
, "Selection", ePropertySelection
, -1 },
150 { IVariable::DT_SIMPLE
, "List", ePropertyList
, -1 },
151 { IVariable::DT_SHADER
, "Shader", ePropertyShader
, 9 },
152 { IVariable::DT_MATERIAL
, "Material", ePropertyMaterial
, 14 },
153 { IVariable::DT_AI_BEHAVIOR
, "AIBehavior", ePropertyAiBehavior
, 8 },
154 { IVariable::DT_AI_ANCHOR
, "AIAnchor", ePropertyAiAnchor
, 8 },
155 #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
156 { IVariable::DT_AI_CHARACTER
, "AICharacter", ePropertyAiCharacter
, 8 },
158 { IVariable::DT_AI_PFPROPERTIESLIST
, "AgentTypeList", ePropertyAiPFPropertiesList
, 8 },
159 { IVariable::DT_AIENTITYCLASSES
, "AI Entity Classes", ePropertyAiEntityClasses
, 8 },
160 { IVariable::DT_EQUIP
, "Equip", ePropertyEquip
, 11 },
161 { IVariable::DT_REVERBPRESET
, "ReverbPreset", ePropertyReverbPreset
, 11 },
162 { IVariable::DT_LOCAL_STRING
, "LocalString", ePropertyLocalString
, 3 },
163 { IVariable::DT_SOCLASS
, "Smart Object Class", ePropertySOClass
, 8 },
164 { IVariable::DT_SOCLASSES
, "Smart Object Classes", ePropertySOClasses
, 8 },
165 { IVariable::DT_SOSTATE
, "Smart Object State", ePropertySOState
, 8 },
166 { IVariable::DT_SOSTATES
, "Smart Object States", ePropertySOStates
, 8 },
167 { IVariable::DT_SOSTATEPATTERN
, "Smart Object State Pattern", ePropertySOStatePattern
, 8 },
168 { IVariable::DT_SOACTION
, "AI Action", ePropertySOAction
, 8 },
169 { IVariable::DT_SOHELPER
, "Smart Object Helper", ePropertySOHelper
, 8 },
170 { IVariable::DT_SONAVHELPER
, "Smart Object Navigation Helper", ePropertySONavHelper
, 8 },
171 { IVariable::DT_SOANIMHELPER
, "Smart Object Animation Helper", ePropertySOAnimHelper
, 8 },
172 { IVariable::DT_SOEVENT
, "Smart Object Event", ePropertySOEvent
, 8 },
173 { IVariable::DT_SOTEMPLATE
, "Smart Object Template", ePropertySOTemplate
, 8 },
174 { IVariable::DT_CUSTOMACTION
, "Custom Action", ePropertyCustomAction
, 7 },
175 { IVariable::DT_VEEDHELPER
, "Vehicle Helper", ePropertySelection
, -1 },
176 { IVariable::DT_VEEDPART
, "Vehicle Part", ePropertySelection
, -1 },
177 { IVariable::DT_VEEDCOMP
, "Vehicle Component", ePropertySelection
, -1 },
178 { IVariable::DT_GAMETOKEN
, "Game Token", ePropertyGameToken
, -1 },
179 { IVariable::DT_SEQUENCE
, "Sequence", ePropertySequence
, -1 },
180 { IVariable::DT_MISSIONOBJ
, "Mission Objective", ePropertyMissionObj
, -1 },
181 { IVariable::DT_USERITEMCB
, "User", ePropertyUser
, -1 },
182 { IVariable::DT_AITERRITORY
, "AITerritory", ePropertyAiTerritory
, 8 },
183 { IVariable::DT_AIWAVE
, "AIWave", ePropertyAiWave
, 8 },
184 { IVariable::DT_SEQUENCE_ID
, "SequenceId", ePropertySequenceId
, -1 },
185 { IVariable::DT_FLARE
, "Flare", ePropertyFlare
, 7 },
186 { IVariable::DT_PARTICLE_EFFECT
, "ParticleEffect", ePropertyParticleName
, 3 },
187 { IVariable::DT_GEOM_CACHE
, "Geometry Cache", ePropertyGeomCache
, 5 },
188 { IVariable::DT_AUDIO_TRIGGER
, "Audio Trigger", ePropertyAudioTrigger
, 6 },
189 { IVariable::DT_AUDIO_SWITCH
, "Audio Switch", ePropertyAudioSwitch
, 6 },
190 { IVariable::DT_AUDIO_SWITCH_STATE
, "Audio Switch", ePropertyAudioSwitchState
, 6 },
191 { IVariable::DT_AUDIO_RTPC
, "Audio Realtime Parameter Control", ePropertyAudioRTPC
, 6 },
192 { IVariable::DT_AUDIO_ENVIRONMENT
, "Audio Environment", ePropertyAudioEnvironment
, 6 },
193 { IVariable::DT_AUDIO_PRELOAD_REQUEST
, "Audio Preload Request", ePropertyAudioPreloadRequest
, 6 },
194 { IVariable::DT_DYNAMIC_RESPONSE_SIGNAL
, "Dynamic Response Signal", ePropertyDynamicResponseSignal
, 6 },
196 static int NumPropertyTypes
= sizeof(s_propertyTypeNames
) / sizeof(s_propertyTypeNames
[0]);
198 const char* DISPLAY_NAME_ATTR
= "DisplayName";
199 const char* VALUE_ATTR
= "Value";
200 const char* TYPE_ATTR
= "Type";
201 const char* TIP_ATTR
= "Tip";
202 const char* TIP_CVAR_ATTR
= "TipCVar";
203 const char* FILEFILTER_ATTR
= "FileFilters";
204 const int FLOAT_NUM_DIGITS
= 6;
206 static const char* PropertyTypeToResourceType(PropertyType type
)
208 // The strings below are names used together with
209 // REGISTER_RESOURCE_SELECTOR. See IResourceSelector.h.
212 case ePropertyAnimation
:
213 return "CharacterAnimation";
216 case ePropertyGeomCache
:
217 return "GeometryCache";
218 case ePropertyAudioTrigger
:
219 return "AudioTrigger";
220 case ePropertyAudioSwitch
:
221 return "AudioSwitch";
222 case ePropertyAudioSwitchState
:
223 return "AudioSwitchState";
224 case ePropertyAudioRTPC
:
226 case ePropertyAudioEnvironment
:
227 return "AudioEnvironment";
228 case ePropertyAudioPreloadRequest
:
229 return "AudioPreloadRequest";
230 case ePropertyDynamicResponseSignal
:
231 return "DynamicResponseSignal";
239 HDWP
CPropertyItem::s_HDWP
= 0;
241 //////////////////////////////////////////////////////////////////////////
243 namespace PropertyItem_Private
245 inline void FormatFloatForUICString(CString
& outstr
, int significantDigits
, double value
)
247 string crystr
= outstr
.GetString();
248 FormatFloatForUI(crystr
, significantDigits
, value
);
249 outstr
= crystr
.GetString();
253 //////////////////////////////////////////////////////////////////////////
254 // CPropertyItem implementation.
255 //////////////////////////////////////////////////////////////////////////
256 CPropertyItem::CPropertyItem(CPropertyCtrl
* pCtrl
)
258 m_propertyCtrl
= pCtrl
;
259 m_pControlsHostWnd
= 0;
261 m_bExpandable
= false;
263 m_bEditChildren
= false;
264 m_bShowChildren
= false;
266 m_bNoCategory
= false;
289 m_bIgnoreChildsUpdate
= false;
291 m_type
= ePropertyInvalid
;
294 m_bMoveControls
= false;
295 m_valueMultiplier
= 1;
298 m_bForceModified
= false;
302 m_nCategoryPageId
= -1;
304 m_strNoScriptDefault
= "<<undefined>>";
305 m_strScriptDefault
= m_strNoScriptDefault
;
308 CPropertyItem::~CPropertyItem()
310 // just to make sure we dont double (or infinitely recurse...) delete
313 DestroyInPlaceControl();
318 for (int i
= 0; i
< m_childs
.size(); i
++)
320 m_childs
[i
]->m_parent
= 0;
324 //////////////////////////////////////////////////////////////////////////
325 void CPropertyItem::SetXmlNode(XmlNodeRef
& node
)
328 // No Undo while just creating properties.
329 //GetIEditor()->GetIUndoManager()->Suspend();
331 //GetIEditor()->GetIUndoManager()->Resume();
334 //////////////////////////////////////////////////////////////////////////
335 void CPropertyItem::ParseXmlNode(bool bRecursive
/* =true */)
337 if (!m_node
->getAttr(DISPLAY_NAME_ATTR
, m_name
))
339 m_name
= m_node
->getTag();
343 bool bHasValue
= m_node
->getAttr(VALUE_ATTR
, value
);
346 m_node
->getAttr(TYPE_ATTR
, type
);
349 m_node
->getAttr(TIP_ATTR
, m_tip
);
351 // read description from associated console variable
353 m_node
->getAttr(TIP_CVAR_ATTR
, tipCVarName
);
354 if (!tipCVarName
.IsEmpty())
356 tipCVarName
.Replace("*", m_name
);
357 if (ICVar
* pCVar
= gEnv
->pConsole
->GetCVar(tipCVarName
))
358 m_tip
= pCVar
->GetHelp();
362 m_type
= ePropertyInvalid
;
363 for (int i
= 0; i
< NumPropertyTypes
; i
++)
365 if (stricmp(type
, s_propertyTypeNames
[i
].name
) == 0)
367 m_type
= s_propertyTypeNames
[i
].type
;
368 m_image
= s_propertyTypeNames
[i
].image
;
376 m_bHardMin
= m_bHardMax
= false;
377 if (m_type
== ePropertyFloat
|| m_type
== ePropertyInt
)
379 if (m_node
->getAttr("Min", m_rangeMin
))
381 if (m_node
->getAttr("Max", m_rangeMax
))
385 if (!m_node
->getAttr("Precision", nPrecision
))
386 nPrecision
= max(3 - int(log(m_rangeMax
- m_rangeMin
) / log(10.f
)), 0);
387 m_step
= powf(10.f
, -nPrecision
);
391 SetValue(value
, false);
393 m_bNoCategory
= false;
395 if ((m_type
== ePropertyVector
|| m_type
== ePropertyVector2
|| m_type
== ePropertyVector4
) && !m_propertyCtrl
->IsExtenedUI())
397 m_bEditChildren
= true;
401 if (m_type
== ePropertyVector
)
404 m_node
->getAttr(VALUE_ATTR
, vec
);
405 // Create 3 sub elements.
406 XmlNodeRef x
= m_node
->createNode("X");
407 XmlNodeRef y
= m_node
->createNode("Y");
408 XmlNodeRef z
= m_node
->createNode("Z");
409 x
->setAttr(TYPE_ATTR
, "Float");
410 y
->setAttr(TYPE_ATTR
, "Float");
411 z
->setAttr(TYPE_ATTR
, "Float");
413 x
->setAttr(VALUE_ATTR
, vec
.x
);
414 y
->setAttr(VALUE_ATTR
, vec
.y
);
415 z
->setAttr(VALUE_ATTR
, vec
.z
);
417 // Start ignoring all updates comming from childs. (Initializing childs).
418 m_bIgnoreChildsUpdate
= true;
420 CPropertyItemPtr itemX
= new CPropertyItem(m_propertyCtrl
);
421 itemX
->SetXmlNode(x
);
424 CPropertyItemPtr itemY
= new CPropertyItem(m_propertyCtrl
);
425 itemY
->SetXmlNode(y
);
428 CPropertyItemPtr itemZ
= new CPropertyItem(m_propertyCtrl
);
429 itemZ
->SetXmlNode(z
);
432 else if (m_type
== ePropertyVector2
)
435 m_node
->getAttr(VALUE_ATTR
, vec
);
436 // Create 3 sub elements.
437 XmlNodeRef x
= m_node
->createNode("X");
438 XmlNodeRef y
= m_node
->createNode("Y");
439 x
->setAttr(TYPE_ATTR
, "Float");
440 y
->setAttr(TYPE_ATTR
, "Float");
442 x
->setAttr(VALUE_ATTR
, vec
.x
);
443 y
->setAttr(VALUE_ATTR
, vec
.y
);
445 // Start ignoring all updates comming from childs. (Initializing childs).
446 m_bIgnoreChildsUpdate
= true;
448 CPropertyItemPtr itemX
= new CPropertyItem(m_propertyCtrl
);
449 itemX
->SetXmlNode(x
);
452 CPropertyItemPtr itemY
= new CPropertyItem(m_propertyCtrl
);
453 itemY
->SetXmlNode(y
);
456 else if (m_type
== ePropertyVector4
)
459 m_node
->getAttr(VALUE_ATTR
, vec
);
460 // Create 3 sub elements.
461 XmlNodeRef x
= m_node
->createNode("X");
462 XmlNodeRef y
= m_node
->createNode("Y");
463 XmlNodeRef z
= m_node
->createNode("Z");
464 XmlNodeRef w
= m_node
->createNode("W");
465 x
->setAttr(TYPE_ATTR
, "Float");
466 y
->setAttr(TYPE_ATTR
, "Float");
467 z
->setAttr(TYPE_ATTR
, "Float");
468 w
->setAttr(TYPE_ATTR
, "Float");
470 x
->setAttr(VALUE_ATTR
, vec
.x
);
471 y
->setAttr(VALUE_ATTR
, vec
.y
);
472 z
->setAttr(VALUE_ATTR
, vec
.z
);
473 w
->setAttr(VALUE_ATTR
, vec
.w
);
475 // Start ignoring all updates comming from childs. (Initializing childs).
476 m_bIgnoreChildsUpdate
= true;
478 CPropertyItemPtr itemX
= new CPropertyItem(m_propertyCtrl
);
479 itemX
->SetXmlNode(x
);
482 CPropertyItemPtr itemY
= new CPropertyItem(m_propertyCtrl
);
483 itemY
->SetXmlNode(y
);
486 CPropertyItemPtr itemZ
= new CPropertyItem(m_propertyCtrl
);
487 itemZ
->SetXmlNode(z
);
490 CPropertyItemPtr itemW
= new CPropertyItem(m_propertyCtrl
);
491 itemW
->SetXmlNode(w
);
494 m_bNoCategory
= true;
495 m_bExpandable
= true;
496 m_bIgnoreChildsUpdate
= false;
500 // If recursive and not vector.
502 m_bExpandable
= false;
504 for (int i
= 0; i
< m_node
->getChildCount(); i
++)
506 m_bIgnoreChildsUpdate
= true;
508 XmlNodeRef child
= m_node
->getChild(i
);
509 CPropertyItemPtr item
= new CPropertyItem(m_propertyCtrl
);
510 item
->SetXmlNode(m_node
->getChild(i
));
512 m_bExpandable
= true;
514 m_bIgnoreChildsUpdate
= false;
520 //////////////////////////////////////////////////////////////////////////
521 void CPropertyItem::SetVariable(IVariable
* var
)
523 if (var
== m_pVariable
)
526 _smart_ptr
<IVariable
> pInputVar
= var
;
528 // Release previous variable.
532 m_pVariable
= pInputVar
;
533 assert(m_pVariable
!= NULL
);
535 m_pVariable
->AddOnSetCallback(functor(*this, &CPropertyItem::OnVariableChange
));
536 m_pVariable
->EnableNotifyWithoutValueChange(m_bForceModified
);
539 m_name
= m_pVariable
->GetHumanName();
541 int dataType
= m_pVariable
->GetDataType();
544 m_type
= ePropertyInvalid
;
547 if (dataType
!= IVariable::DT_SIMPLE
)
549 for (i
= 0; i
< NumPropertyTypes
; i
++)
551 if (dataType
== s_propertyTypeNames
[i
].dataType
)
553 m_type
= s_propertyTypeNames
[i
].type
;
554 m_image
= s_propertyTypeNames
[i
].image
;
560 m_enumList
= m_pVariable
->GetEnumList();
561 if (m_enumList
!= NULL
)
563 m_type
= ePropertySelection
;
566 if (m_type
== ePropertyInvalid
)
568 switch (m_pVariable
->GetType())
571 m_type
= ePropertyInt
;
573 case IVariable::BOOL
:
574 m_type
= ePropertyBool
;
576 case IVariable::FLOAT
:
577 m_type
= ePropertyFloat
;
579 case IVariable::VECTOR2
:
580 m_type
= ePropertyVector2
;
582 case IVariable::VECTOR4
:
583 m_type
= ePropertyVector4
;
585 case IVariable::VECTOR
:
586 m_type
= ePropertyVector
;
588 case IVariable::STRING
:
589 m_type
= ePropertyString
;
592 for (i
= 0; i
< NumPropertyTypes
; i
++)
594 if (m_type
== s_propertyTypeNames
[i
].type
)
596 m_image
= s_propertyTypeNames
[i
].image
;
602 m_valueMultiplier
= 1;
606 m_bHardMin
= m_bHardMax
= false;
608 // Get variable limits.
609 m_pVariable
->GetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
611 // Check if value is percents.
612 if (dataType
== IVariable::DT_PERCENT
)
614 // Scale all values by 100.
615 m_valueMultiplier
= 100;
617 else if (dataType
== IVariable::DT_ANGLE
)
619 // Scale radians to degrees.
620 m_valueMultiplier
= RAD2DEG(1);
624 else if (dataType
== IVariable::DT_UIENUM
)
626 m_pEnumDBItem
= GetIEditor()->GetUIEnumsDatabase()->FindEnum(m_name
.GetString());
629 const bool useExplicitStep
= (m_pVariable
->GetFlags() & IVariable::UI_EXPLICIT_STEP
);
630 if (!useExplicitStep
)
632 // Limit step size to 1000.
633 int nPrec
= max(3 - int(log(m_rangeMax
- m_rangeMin
) / log(10.f
)), 0);
634 m_step
= max(m_step
, powf(10.f
, -nPrec
));
637 //////////////////////////////////////////////////////////////////////////
640 m_bNoCategory
= false;
644 case ePropertyAiPFPropertiesList
:
645 m_bEditChildren
= true;
646 AddChildrenForPFProperties();
647 m_bNoCategory
= true;
648 m_bExpandable
= true;
651 case ePropertyAiEntityClasses
:
652 m_bEditChildren
= true;
653 AddChildrenForAIEntityClasses();
654 m_bNoCategory
= true;
655 m_bExpandable
= true;
658 case ePropertyVector2
:
659 if (!m_propertyCtrl
->IsExtenedUI())
661 m_bEditChildren
= true;
665 m_pVariable
->Get(vec
);
666 IVariable
* pVX
= new CVariable
<float>;
668 pVX
->SetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
670 IVariable
* pVY
= new CVariable
<float>;
672 pVY
->SetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
675 // Start ignoring all updates coming from childs. (Initializing childs).
676 m_bIgnoreChildsUpdate
= true;
678 CPropertyItemPtr itemX
= new CPropertyItem(m_propertyCtrl
);
679 itemX
->SetVariable(pVX
);
682 CPropertyItemPtr itemY
= new CPropertyItem(m_propertyCtrl
);
683 itemY
->SetVariable(pVY
);
686 m_bNoCategory
= true;
687 m_bExpandable
= true;
689 m_bIgnoreChildsUpdate
= false;
693 case ePropertyVector4
:
694 if (!m_propertyCtrl
->IsExtenedUI())
696 m_bEditChildren
= true;
700 m_pVariable
->Get(vec
);
701 IVariable
* pVX
= new CVariable
<float>;
703 pVX
->SetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
705 IVariable
* pVY
= new CVariable
<float>;
707 pVY
->SetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
709 IVariable
* pVZ
= new CVariable
<float>;
711 pVZ
->SetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
713 IVariable
* pVW
= new CVariable
<float>;
715 pVW
->SetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
718 // Start ignoring all updates coming from childs. (Initializing childs).
719 m_bIgnoreChildsUpdate
= true;
721 CPropertyItemPtr itemX
= new CPropertyItem(m_propertyCtrl
);
722 itemX
->SetVariable(pVX
);
725 CPropertyItemPtr itemY
= new CPropertyItem(m_propertyCtrl
);
726 itemY
->SetVariable(pVY
);
729 CPropertyItemPtr itemZ
= new CPropertyItem(m_propertyCtrl
);
730 itemZ
->SetVariable(pVZ
);
733 CPropertyItemPtr itemW
= new CPropertyItem(m_propertyCtrl
);
734 itemZ
->SetVariable(pVW
);
737 m_bNoCategory
= true;
738 m_bExpandable
= true;
740 m_bIgnoreChildsUpdate
= false;
743 case ePropertyVector
:
744 if (!m_propertyCtrl
->IsExtenedUI())
746 m_bEditChildren
= true;
750 m_pVariable
->Get(vec
);
751 IVariable
* pVX
= new CVariable
<float>;
753 pVX
->SetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
755 IVariable
* pVY
= new CVariable
<float>;
757 pVY
->SetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
759 IVariable
* pVZ
= new CVariable
<float>;
761 pVZ
->SetLimits(m_rangeMin
, m_rangeMax
, m_step
, m_bHardMin
, m_bHardMax
);
764 // Start ignoring all updates coming from childs. (Initializing childs).
765 m_bIgnoreChildsUpdate
= true;
767 CPropertyItemPtr itemX
= new CPropertyItem(m_propertyCtrl
);
768 itemX
->SetVariable(pVX
);
771 CPropertyItemPtr itemY
= new CPropertyItem(m_propertyCtrl
);
772 itemY
->SetVariable(pVY
);
775 CPropertyItemPtr itemZ
= new CPropertyItem(m_propertyCtrl
);
776 itemZ
->SetVariable(pVZ
);
779 m_bNoCategory
= true;
780 m_bExpandable
= true;
782 m_bIgnoreChildsUpdate
= false;
787 if (m_pVariable
->GetNumVariables() > 0)
789 if (m_type
== ePropertyInvalid
)
790 m_type
= ePropertyTable
;
791 m_bExpandable
= true;
792 if (m_pVariable
->GetFlags() & IVariable::UI_SHOW_CHILDREN
)
793 m_bShowChildren
= true;
794 m_bIgnoreChildsUpdate
= true;
795 for (i
= 0; i
< m_pVariable
->GetNumVariables(); i
++)
797 CPropertyItemPtr item
= new CPropertyItem(m_propertyCtrl
);
798 item
->SetVariable(m_pVariable
->GetVariable(i
));
801 m_bIgnoreChildsUpdate
= false;
807 //////////////////////////////////////////////////////////////////////////
808 void CPropertyItem::ReleaseVariable()
812 // Unwire all from variable.
813 m_pVariable
->RemoveOnSetCallback(functor(*this, &CPropertyItem::OnVariableChange
));
818 //////////////////////////////////////////////////////////////////////////
819 //! Find item that reference specified property.
820 CPropertyItem
* CPropertyItem::FindItemByVar(IVariable
* pVar
)
822 if (m_pVariable
== pVar
)
824 for (int i
= 0; i
< m_childs
.size(); i
++)
826 CPropertyItem
* pFound
= m_childs
[i
]->FindItemByVar(pVar
);
833 //////////////////////////////////////////////////////////////////////////
834 CString
CPropertyItem::GetFullName() const
838 return m_parent
->GetFullName() + "::" + m_name
;
844 //////////////////////////////////////////////////////////////////////////
845 CPropertyItem
* CPropertyItem::FindItemByFullName(const CString
& name
)
847 if (GetFullName() == name
)
849 for (int i
= 0; i
< m_childs
.size(); i
++)
851 CPropertyItem
* pFound
= m_childs
[i
]->FindItemByFullName(name
);
858 //////////////////////////////////////////////////////////////////////////
859 void CPropertyItem::AddChild(CPropertyItem
* item
)
862 m_bExpandable
= true;
863 item
->m_parent
= this;
864 m_childs
.push_back(item
);
867 //////////////////////////////////////////////////////////////////////////
868 void CPropertyItem::RemoveChild(CPropertyItem
* item
)
870 // Find item and erase it from childs array.
871 for (int i
= 0; i
< m_childs
.size(); i
++)
873 if (item
== m_childs
[i
])
875 m_childs
.erase(m_childs
.begin() + i
);
881 //////////////////////////////////////////////////////////////////////////
882 void CPropertyItem::RemoveAllChildren()
887 //////////////////////////////////////////////////////////////////////////
888 void CPropertyItem::OnChildChanged(CPropertyItem
* child
)
890 if (m_bIgnoreChildsUpdate
)
897 if ((m_type
== ePropertyAiPFPropertiesList
) || (m_type
== ePropertyAiEntityClasses
))
899 for (int i
= 0; i
< m_childs
.size(); i
++)
903 CString value
= m_childs
[i
]->GetValue();
904 while (!(token
= value
.Tokenize(" ,", index
)).IsEmpty())
906 if (!sValue
.IsEmpty())
914 for (int i
= 0; i
< m_childs
.size(); i
++)
918 sValue
+= m_childs
[i
]->GetValue();
921 SetValue(sValue
, false);
923 if (m_bEditChildren
|| m_bShowChildren
)
927 //////////////////////////////////////////////////////////////////////////
928 void CPropertyItem::SetSelected(bool selected
)
930 m_bSelected
= selected
;
933 //////////////////////////////////////////////////////////////////////////
934 void CPropertyItem::SetExpanded(bool expanded
)
941 m_bExpanded
= expanded
;
944 bool CPropertyItem::IsDisabled() const
948 return m_pVariable
->GetFlags() & IVariable::UI_DISABLED
;
953 bool CPropertyItem::IsInvisible() const
957 return m_pVariable
->GetFlags() & IVariable::UI_INVISIBLE
;
962 bool CPropertyItem::IsBold() const
966 return m_pVariable
->GetFlags() & IVariable::UI_BOLD
;
971 //////////////////////////////////////////////////////////////////////////
972 void CPropertyItem::CreateInPlaceControl(CWnd
* pWndParent
, CRect
& ctrlRect
)
979 m_bMoveControls
= true;
980 CRect
nullRc(0, 0, 0, 0);
991 m_cCombo
= new CInPlaceComboBox();
992 m_cCombo
->SetReadOnly(true);
993 int unsorted
= m_pEnumDBItem
->strings
.size() && !strcmp(m_pEnumDBItem
->strings
[0], "#unsorted");
994 DWORD nSorting
= (unsorted
|| m_pVariable
&& m_pVariable
->GetFlags() & IVariable::UI_UNSORTED
) ? 0 : LBS_SORT
;
995 m_cCombo
->Create(NULL
, "", WS_CHILD
| WS_VISIBLE
| nSorting
, nullRc
, pWndParent
, 2);
996 m_cCombo
->SetUpdateCallback(functor(*this, &CPropertyItem::OnComboSelection
));
998 for (int i
= unsorted
; i
< m_pEnumDBItem
->strings
.size(); i
++)
999 m_cCombo
->AddString(m_pEnumDBItem
->strings
[i
]);
1003 m_cNumber
= new CNumberCtrl
;
1004 m_cNumber
->SetUpdateCallback(functor(*this, &CPropertyItem::OnNumberCtrlUpdate
));
1005 m_cNumber
->EnableUndo(m_name
+ " Modified");
1006 m_cNumber
->EnableNotifyWithoutValueChange(m_bForceModified
);
1007 //m_cNumber->SetBeginUpdateCallback( functor(*this,OnNumberCtrlBeginUpdate) );
1008 //m_cNumber->SetEndUpdateCallback( functor(*this,OnNumberCtrlEndUpdate) );
1010 // (digits behind the comma, only used for floats)
1011 if (m_type
== ePropertyFloat
)
1013 m_cNumber
->SetStep(m_step
);
1014 m_cNumber
->SetFloatFormatPrecision(FLOAT_NUM_DIGITS
);
1016 else if (m_type
== ePropertyAngle
)
1018 m_cNumber
->SetFloatFormatPrecision(FLOAT_NUM_DIGITS
);
1021 // Only for integers.
1022 if (m_type
== ePropertyInt
)
1023 m_cNumber
->SetInteger(true);
1024 m_cNumber
->SetMultiplier(m_valueMultiplier
);
1025 m_cNumber
->SetRange(m_bHardMin
? m_rangeMin
: -FLT_MAX
, m_bHardMax
? m_rangeMax
: FLT_MAX
);
1027 m_cNumber
->Create(pWndParent
, nullRc
, 1, CNumberCtrl::NOBORDER
| CNumberCtrl::LEFTALIGN
);
1028 m_cNumber
->SetLeftAlign(true);
1030 if (m_bHardMin
|| m_bHardMax
)
1032 m_cFillSlider
= new CFillSliderCtrl
;
1033 m_cFillSlider
->EnableUndo(m_name
+ " Modified");
1034 m_cFillSlider
->Create(WS_VISIBLE
| WS_CHILD
, nullRc
, pWndParent
, 2);
1035 m_cFillSlider
->SetUpdateCallback(functor(*this, &CPropertyItem::OnFillSliderCtrlUpdate
));
1036 m_cFillSlider
->SetRangeFloat(m_rangeMin
/ m_valueMultiplier
, m_rangeMax
/ m_valueMultiplier
, m_step
/ m_valueMultiplier
);
1042 case ePropertyTable
:
1043 if (!m_bEditChildren
)
1046 //These used to be a combo box but right now defaulting back to editbox
1047 case ePropertyAiTerritory
:
1048 case ePropertyAiWave
:
1050 case ePropertyString
:
1054 m_cCombo
= new CInPlaceComboBox();
1055 m_cCombo
->SetReadOnly(true);
1056 DWORD nSorting
= (m_pVariable
&& m_pVariable
->GetFlags() & IVariable::UI_UNSORTED
) ? 0 : LBS_SORT
;
1057 m_cCombo
->Create(NULL
, "", WS_CHILD
| WS_VISIBLE
| nSorting
, nullRc
, pWndParent
, 2);
1058 m_cCombo
->SetUpdateCallback(functor(*this, &CPropertyItem::OnComboSelection
));
1060 for (int i
= 0; i
< m_pEnumDBItem
->strings
.size(); i
++)
1061 m_cCombo
->AddString(m_pEnumDBItem
->strings
[i
]);
1066 // Here we must check the global table to see if this enum should be loaded from the XML.
1067 TDValues
* pcValue
= (m_pVariable
) ? GetEnumValues(m_pVariable
->GetName()) : NULL
;
1069 // If there is not even this, we THEN fall back to create the edit box.
1072 m_cCombo
= new CInPlaceComboBox();
1073 m_cCombo
->SetReadOnly(true);
1074 DWORD nSorting
= (m_pVariable
&& m_pVariable
->GetFlags() & IVariable::UI_UNSORTED
) ? 0 : LBS_SORT
;
1075 m_cCombo
->Create(NULL
, "", WS_CHILD
| WS_VISIBLE
| nSorting
, nullRc
, pWndParent
, 2);
1076 m_cCombo
->SetUpdateCallback(functor(*this, &CPropertyItem::OnComboSelection
));
1078 for (int i
= 0; i
< pcValue
->size(); i
++)
1080 m_cCombo
->AddString((*pcValue
)[i
]);
1085 // ... else, fall through to create edit box.
1087 case ePropertyVector
:
1088 case ePropertyVector2
:
1089 case ePropertyVector4
:
1090 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1091 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
, nullRc
, pWndParent
, 2);
1092 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1095 case ePropertyMaterial
:
1096 case ePropertyAiBehavior
:
1097 case ePropertyAiAnchor
:
1098 #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
1099 case ePropertyAiCharacter
:
1101 case ePropertyAiPFPropertiesList
:
1102 case ePropertyAiEntityClasses
:
1103 case ePropertyEquip
:
1104 case ePropertyReverbPreset
:
1105 case ePropertySOClass
:
1106 case ePropertySOClasses
:
1107 case ePropertySOState
:
1108 case ePropertySOStates
:
1109 case ePropertySOStatePattern
:
1110 case ePropertySOAction
:
1111 case ePropertySOHelper
:
1112 case ePropertySONavHelper
:
1113 case ePropertySOAnimHelper
:
1114 case ePropertySOEvent
:
1115 case ePropertySOTemplate
:
1116 case ePropertyCustomAction
:
1117 case ePropertyGameToken
:
1118 case ePropertyMissionObj
:
1119 case ePropertySequence
:
1120 case ePropertySequenceId
:
1122 case ePropertyLocalString
:
1123 case ePropertyParticleName
:
1124 case ePropertyFlare
:
1125 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1126 style
= WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
;
1127 if (m_type
== ePropertySequenceId
)
1128 style
|= ES_READONLY
;
1129 m_cEdit
->Create(style
, nullRc
, pWndParent
, 2);
1130 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1131 if (m_type
== ePropertyMaterial
)
1133 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnMaterialBrowseButton
));
1134 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1136 m_cButton2
= new CInPlaceButton(functor(*this, &CPropertyItem::OnMaterialPickSelectedButton
));
1137 m_cButton2
->Create("<", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 5);
1139 else if (m_type
== ePropertySequence
)
1141 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnSequenceBrowseButton
));
1142 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1144 else if (m_type
== ePropertySequenceId
)
1146 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnSequenceIdBrowseButton
));
1147 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1149 else if (m_type
== ePropertyMissionObj
)
1151 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnMissionObjButton
));
1152 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1154 else if (m_type
== ePropertyUser
)
1156 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnUserBrowseButton
));
1157 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1159 else if (m_type
== ePropertyLocalString
)
1161 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnLocalStringBrowseButton
));
1162 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1164 else if (GetIEditor()->CanEditDeprecatedProperty(m_type
))
1166 //handle with deprecated picker registration system
1167 //this only works for button-style pickers, improve system if necessary
1168 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnEditDeprecatedProperty
));
1169 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1173 case ePropertySelection
:
1176 m_cCombo
= new CInPlaceComboBox();
1177 m_cCombo
->SetReadOnly(true);
1178 DWORD nSorting
= (m_pVariable
&& m_pVariable
->GetFlags() & IVariable::UI_UNSORTED
) ? 0 : LBS_SORT
;
1179 m_cCombo
->Create(NULL
, "", WS_CHILD
| WS_VISIBLE
| nSorting
, nullRc
, pWndParent
, 2);
1180 m_cCombo
->SetUpdateCallback(functor(*this, &CPropertyItem::OnComboSelection
));
1184 for (uint i
= 0; cstr sEnumName
= m_enumList
->GetItemName(i
); i
++)
1186 m_cCombo
->AddString(sEnumName
);
1190 m_cCombo
->SetReadOnly(false);
1194 case ePropertyColor
:
1196 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1197 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
, nullRc
, pWndParent
, 2);
1198 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1199 m_cColorButton
= new CInPlaceColorButton(functor(*this, &CPropertyItem::OnColorBrowseButton
));
1200 m_cColorButton
->Create("", WS_CHILD
| WS_VISIBLE
| BS_PUSHBUTTON
| BS_OWNERDRAW
, nullRc
, pWndParent
, 4);
1204 case ePropertyFloatCurve
:
1206 m_cSpline
= new CSplineCtrl
;
1207 m_cSpline
->Create(WS_VISIBLE
| WS_CHILD
, nullRc
, pWndParent
, 2);
1208 m_cSpline
->SetUpdateCallback((CSplineCtrl::UpdateCallback
const&)functor(*this, &CPropertyItem::ReceiveFromControl
));
1209 m_cSpline
->SetTimeRange(0, 1);
1210 m_cSpline
->SetValueRange(0, 1);
1211 m_cSpline
->SetGrid(12, 12);
1212 m_cSpline
->SetSpline(m_pVariable
->GetSpline(true));
1216 case ePropertyColorCurve
:
1218 m_cColorSpline
= new CColorGradientCtrl
;
1219 m_cColorSpline
->Create(WS_VISIBLE
| WS_CHILD
, nullRc
, pWndParent
, 2);
1220 m_cColorSpline
->SetUpdateCallback((CColorGradientCtrl::UpdateCallback
const&)functor(*this, &CPropertyItem::ReceiveFromControl
));
1221 m_cColorSpline
->SetTimeRange(0, 1);
1222 m_cColorSpline
->SetSpline(m_pVariable
->GetSpline(true));
1226 case ePropertyTexture
:
1228 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1229 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
, nullRc
, pWndParent
, 2);
1230 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1232 HICON
hButtonIcon(NULL
);
1234 hButtonIcon
= (HICON
)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_FILE_BROWSE
), IMAGE_ICON
, 16, 15, LR_DEFAULTCOLOR
| LR_SHARED
);
1235 m_cButton3
= new CInPlaceButton(functor(*this, &CPropertyItem::OnFileBrowseButton
));
1236 m_cButton3
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1237 m_cButton3
->SetIcon(CSize(16, 15), hButtonIcon
);
1238 m_cButton3
->SetBorderGap(6);
1242 case ePropertyAnimation
:
1243 case ePropertyModel
:
1244 case ePropertyGeomCache
:
1245 case ePropertyAudioTrigger
:
1246 case ePropertyAudioSwitch
:
1247 case ePropertyAudioSwitchState
:
1248 case ePropertyAudioRTPC
:
1249 case ePropertyAudioEnvironment
:
1250 case ePropertyAudioPreloadRequest
:
1251 case ePropertyDynamicResponseSignal
:
1253 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1254 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
, nullRc
, pWndParent
, 2);
1255 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1257 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnResourceSelectorButton
));
1258 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1260 // Use file browse icon.
1261 HICON hOpenIcon
= (HICON
)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_FILE_BROWSE
), IMAGE_ICON
, 16, 15, LR_DEFAULTCOLOR
| LR_SHARED
);
1262 m_cButton
->SetIcon(CSize(16, 15), hOpenIcon
);
1263 m_cButton
->SetBorderGap(0);
1267 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1268 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
, nullRc
, pWndParent
, 2);
1269 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1271 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnFileBrowseButton
));
1272 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1274 // Use file browse icon.
1275 HICON hOpenIcon
= (HICON
)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_FILE_BROWSE
), IMAGE_ICON
, 16, 15, LR_DEFAULTCOLOR
| LR_SHARED
);
1276 //m_cButton->SetIcon( CSize(16,15),IDI_FILE_BROWSE );
1277 m_cButton
->SetIcon(CSize(16, 15), hOpenIcon
);
1278 m_cButton
->SetBorderGap(0);
1283 AddButton( "Add", CWDelegate(this,(TDelegate)OnAddItemButton) );
1289 MoveInPlaceControl(ctrlRect
);
1293 //////////////////////////////////////////////////////////////////////////
1294 void CPropertyItem::CreateControls(CWnd
* pWndParent
, CRect
& textRect
, CRect
& ctrlRect
)
1296 m_pControlsHostWnd
= pWndParent
;
1297 m_rcText
= textRect
;
1298 m_rcControl
= ctrlRect
;
1300 m_bMoveControls
= false;
1301 CRect
nullRc(0, 0, 0, 0);
1304 if (IsExpandable() && !m_propertyCtrl
->IsCategory(this))
1306 m_cExpandButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnExpandButton
));
1307 m_cExpandButton
->Create("", WS_CHILD
| WS_VISIBLE
| BS_PUSHBUTTON
, CRect(textRect
.left
, textRect
.top
+ 2, textRect
.left
+ 12, textRect
.top
+ 14), pWndParent
, 5);
1308 m_cExpandButton
->SetFlatStyle(TRUE
);
1310 m_cExpandButton
->SetIcon(CSize(8, 8), IDI_EXPAND1
);
1312 m_cExpandButton
->SetIcon(CSize(8, 8), IDI_EXPAND2
);
1313 textRect
.left
+= 12;
1314 RegisterCtrl(m_cExpandButton
);
1317 // Create static text. Update: put text on left of Bools as well, for UI consistency.
1318 // if (m_type != ePropertyBool)
1320 m_pStaticText
= new CColorCtrl
<CStatic
>;
1321 CString text
= GetName();
1322 if (m_type
!= ePropertyTable
)
1324 text
+= " . . . . . . . . . . . . . . . . . . . . . . . . . .";
1326 m_pStaticText
->Create(text
, WS_CHILD
| WS_VISIBLE
| SS_LEFT
, textRect
, pWndParent
);
1327 m_pStaticText
->SetFont(CFont::FromHandle((HFONT
)gMFCFonts
.hSystemFont
));
1328 RegisterCtrl(m_pStaticText
);
1335 m_cCheckBox
= new CInPlaceCheckBox(functor(*this, &CPropertyItem::OnCheckBoxButton
));
1336 m_cCheckBox
->Create("", WS_CHILD
| WS_VISIBLE
| BS_AUTOCHECKBOX
| WS_TABSTOP
, ctrlRect
, pWndParent
, 0);
1337 m_cCheckBox
->SetFont(m_propertyCtrl
->GetFont());
1338 RegisterCtrl(m_cCheckBox
);
1341 case ePropertyFloat
:
1343 case ePropertyAngle
:
1345 m_cNumber
= new CNumberCtrl
;
1346 m_cNumber
->SetUpdateCallback(functor(*this, &CPropertyItem::OnNumberCtrlUpdate
));
1347 m_cNumber
->EnableUndo(m_name
+ " Modified");
1348 RegisterCtrl(m_cNumber
);
1350 // (digits behind the comma, only used for floats)
1351 if (m_type
== ePropertyFloat
)
1352 m_cNumber
->SetStep(m_step
);
1354 // Only for integers.
1355 if (m_type
== ePropertyInt
)
1356 m_cNumber
->SetInteger(true);
1357 m_cNumber
->SetMultiplier(m_valueMultiplier
);
1358 m_cNumber
->SetRange(m_bHardMin
? m_rangeMin
: -FLT_MAX
, m_bHardMax
? m_rangeMax
: FLT_MAX
);
1360 m_cNumber
->Create(pWndParent
, nullRc
, 1);
1361 m_cNumber
->SetLeftAlign(true);
1364 CSliderCtrlEx *pSlider = new CSliderCtrlEx;
1365 //pSlider->EnableUndo( m_name + " Modified" );
1366 CRect rcSlider = ctrlRect;
1367 rcSlider.left += NUMBER_CTRL_WIDTH;
1368 pSlider->Create( WS_VISIBLE|WS_CHILD,rcSlider,pWndParent,2);
1370 if (m_bHardMin
|| m_bHardMax
)
1372 m_cFillSlider
= new CFillSliderCtrl
;
1373 m_cFillSlider
->SetFilledLook(true);
1374 //m_cFillSlider->SetFillStyle(CFillSliderCtrl::eFillStyle_Background);
1375 m_cFillSlider
->EnableUndo(m_name
+ " Modified");
1376 m_cFillSlider
->Create(WS_VISIBLE
| WS_CHILD
, nullRc
, pWndParent
, 2);
1377 m_cFillSlider
->SetUpdateCallback(functor(*this, &CPropertyItem::OnFillSliderCtrlUpdate
));
1378 m_cFillSlider
->SetRangeFloat(m_rangeMin
/ m_valueMultiplier
, m_rangeMax
/ m_valueMultiplier
, m_step
/ m_valueMultiplier
);
1379 RegisterCtrl(m_cFillSlider
);
1384 case ePropertyVector
:
1385 case ePropertyVector2
:
1386 case ePropertyVector4
:
1388 int numberOfElements
= 3;
1389 if (m_type
== ePropertyVector2
)
1390 numberOfElements
= 2;
1391 else if (m_type
== ePropertyVector4
)
1392 numberOfElements
= 4;
1394 CNumberCtrl
** cNumber
[4] = { &m_cNumber
, &m_cNumber1
, &m_cNumber2
, &m_cNumber3
};
1396 for (int a
= 0; a
< numberOfElements
; a
++)
1398 CNumberCtrl
* pNumber
= *cNumber
[a
] = new CNumberCtrl
;
1399 pNumber
->Create(pWndParent
, nullRc
, 1);
1400 pNumber
->SetLeftAlign(true);
1401 pNumber
->SetUpdateCallback(functor(*this, &CPropertyItem::OnNumberCtrlUpdate
));
1402 pNumber
->EnableUndo(m_name
+ " Modified");
1403 pNumber
->SetMultiplier(m_valueMultiplier
);
1404 pNumber
->SetRange(m_bHardMin
? m_rangeMin
: -FLT_MAX
, m_bHardMax
? m_rangeMax
: FLT_MAX
);
1405 RegisterCtrl(pNumber
);
1410 case ePropertyTable
:
1411 if (!m_bEditChildren
)
1413 //These used to be a combo box but right now defaulting back to editbox
1414 case ePropertyAiTerritory
:
1415 case ePropertyAiWave
:
1417 case ePropertyString
:
1418 //case ePropertyVector:
1420 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1421 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
| WS_TABSTOP
, nullRc
, pWndParent
, 2);
1422 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1423 RegisterCtrl(m_cEdit
);
1426 case ePropertyMaterial
:
1427 case ePropertyAiBehavior
:
1428 case ePropertyAiAnchor
:
1429 #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
1430 case ePropertyAiCharacter
:
1432 case ePropertyAiPFPropertiesList
:
1433 case ePropertyAiEntityClasses
:
1434 case ePropertyEquip
:
1435 case ePropertyReverbPreset
:
1436 case ePropertySOClass
:
1437 case ePropertySOClasses
:
1438 case ePropertySOState
:
1439 case ePropertySOStates
:
1440 case ePropertySOStatePattern
:
1441 case ePropertySOAction
:
1442 case ePropertySOHelper
:
1443 case ePropertySONavHelper
:
1444 case ePropertySOAnimHelper
:
1445 case ePropertyCustomAction
:
1446 case ePropertyGameToken
:
1447 case ePropertySequence
:
1448 case ePropertySequenceId
:
1450 case ePropertyLocalString
:
1451 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1452 style
= WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
| WS_TABSTOP
;
1453 if (m_type
== ePropertySequenceId
)
1454 style
|= ES_READONLY
;
1455 m_cEdit
->Create(style
, nullRc
, pWndParent
, 2);
1456 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1457 RegisterCtrl(m_cEdit
);
1459 if (m_type
== ePropertyMaterial
)
1461 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnMaterialBrowseButton
));
1462 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1464 m_cButton2
= new CInPlaceButton(functor(*this, &CPropertyItem::OnMaterialPickSelectedButton
));
1465 m_cButton2
->Create("<", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 5);
1467 else if (m_type
== ePropertySequence
)
1469 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnSequenceBrowseButton
));
1470 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1472 else if (m_type
== ePropertySequenceId
)
1474 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnSequenceIdBrowseButton
));
1475 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1477 else if (m_type
== ePropertyUser
)
1479 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnUserBrowseButton
));
1480 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1482 else if (m_type
== ePropertyLocalString
)
1484 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnLocalStringBrowseButton
));
1485 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1487 else if (GetIEditor()->CanEditDeprecatedProperty(m_type
))
1489 //handle with deprecated picker registration system
1490 //this only works for button-style pickers, improve system if necessary
1491 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnEditDeprecatedProperty
));
1492 m_cButton
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1497 RegisterCtrl(m_cButton
);
1501 RegisterCtrl(m_cButton2
);
1505 case ePropertySelection
:
1509 m_cCombo
= new CInPlaceComboBox();
1510 m_cCombo
->SetReadOnly(true);
1511 DWORD nSorting
= (m_pVariable
&& m_pVariable
->GetFlags() & IVariable::UI_UNSORTED
) ? 0 : LBS_SORT
;
1512 m_cCombo
->Create(NULL
, "", WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| nSorting
, nullRc
, pWndParent
, 2);
1513 m_cCombo
->SetUpdateCallback(functor(*this, &CPropertyItem::OnComboSelection
));
1514 RegisterCtrl(m_cCombo
);
1518 for (uint i
= 0; cstr sEnumName
= m_enumList
->GetItemName(i
); i
++)
1520 m_cCombo
->AddString(sEnumName
);
1524 m_cCombo
->SetReadOnly(false);
1528 case ePropertyColor
:
1530 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1531 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
| WS_TABSTOP
, nullRc
, pWndParent
, 2);
1532 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1533 RegisterCtrl(m_cEdit
);
1535 //m_cButton = new CInPlaceButton( functor(*this,OnColorBrowseButton) );
1536 //m_cButton->Create( "",WS_CHILD|WS_VISIBLE,nullRc,pWndParent,4 );
1537 m_cColorButton
= new CInPlaceColorButton(functor(*this, &CPropertyItem::OnColorBrowseButton
));
1538 m_cColorButton
->Create("", WS_CHILD
| WS_VISIBLE
| BS_PUSHBUTTON
| BS_OWNERDRAW
, nullRc
, pWndParent
, 4);
1539 RegisterCtrl(m_cColorButton
);
1543 case ePropertyFloatCurve
:
1545 m_cSpline
= new CSplineCtrl
;
1546 m_cSpline
->Create(WS_VISIBLE
| WS_CHILD
, nullRc
, pWndParent
, 2);
1547 m_cSpline
->SetUpdateCallback((CSplineCtrl::UpdateCallback
const&)functor(*this, &CPropertyItem::ReceiveFromControl
));
1548 m_cSpline
->SetTimeRange(0, 1);
1549 m_cSpline
->SetValueRange(0, 1);
1550 m_cSpline
->SetGrid(12, 12);
1551 m_cSpline
->SetSpline(m_pVariable
->GetSpline(true));
1552 RegisterCtrl(m_cSpline
);
1556 case ePropertyColorCurve
:
1558 m_cColorSpline
= new CColorGradientCtrl
;
1559 m_cColorSpline
->Create(WS_VISIBLE
| WS_CHILD
, nullRc
, pWndParent
, 2);
1560 m_cColorSpline
->SetUpdateCallback((CColorGradientCtrl::UpdateCallback
const&)functor(*this, &CPropertyItem::ReceiveFromControl
));
1561 m_cColorSpline
->SetTimeRange(0, 1);
1562 m_cColorSpline
->SetSpline(m_pVariable
->GetSpline(true));
1563 RegisterCtrl(m_cColorSpline
);
1567 case ePropertyTexture
:
1569 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1570 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
| WS_TABSTOP
, nullRc
, pWndParent
, 2);
1571 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1572 RegisterCtrl(m_cEdit
);
1574 HICON
hButtonIcon(NULL
);
1576 hButtonIcon
= (HICON
)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_FILE_BROWSE
), IMAGE_ICON
, 16, 15, LR_DEFAULTCOLOR
| LR_SHARED
);
1577 m_cButton3
= new CInPlaceButton(functor(*this, &CPropertyItem::OnFileBrowseButton
));
1578 m_cButton3
->Create("...", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1579 RegisterCtrl(m_cButton3
);
1580 //m_cButton3->SetIcon( CSize(16,15),hButtonIcon);
1581 //m_cButton3->SetBorderGap(6);
1583 hButtonIcon
= (HICON
)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_TIFF
), IMAGE_ICON
, 16, 15, LR_DEFAULTCOLOR
| LR_SHARED
);
1584 m_cButton4
= new CInPlaceButton(functor(*this, &CPropertyItem::OnTextureEditButton
));
1585 m_cButton4
->Create("", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 7); // edit selected texture semantics.
1586 m_cButton4
->SetIcon(CSize(16, 15), hButtonIcon
);
1587 m_cButton4
->SetBorderGap(6);
1588 RegisterCtrl(m_cButton4
);
1590 hButtonIcon
= (HICON
)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_PSD
), IMAGE_ICON
, 16, 15, LR_DEFAULTCOLOR
| LR_SHARED
);
1591 m_cButton5
= new CInPlaceButton(functor(*this, &CPropertyItem::OnPsdEditButton
));
1592 m_cButton5
->Create("", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 8); // edit selected texture semantics.
1593 m_cButton5
->SetIcon(CSize(16, 15), hButtonIcon
);
1594 m_cButton5
->SetBorderGap(6);
1595 RegisterCtrl(m_cButton5
);
1599 case ePropertyAnimation
:
1600 case ePropertyModel
:
1601 case ePropertyAudioTrigger
:
1602 case ePropertyAudioSwitch
:
1603 case ePropertyAudioSwitchState
:
1604 case ePropertyAudioRTPC
:
1605 case ePropertyAudioEnvironment
:
1606 case ePropertyAudioPreloadRequest
:
1607 case ePropertyDynamicResponseSignal
:
1609 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1610 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
| WS_TABSTOP
, nullRc
, pWndParent
, 2);
1611 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1612 RegisterCtrl(m_cEdit
);
1614 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnResourceSelectorButton
));
1615 m_cButton
->Create("", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1616 RegisterCtrl(m_cButton
);
1618 HICON hOpenIcon
= (HICON
)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_FILE_BROWSE
), IMAGE_ICON
, 16, 15, LR_DEFAULTCOLOR
| LR_SHARED
);
1619 m_cButton
->SetIcon(CSize(16, 15), hOpenIcon
);
1620 m_cButton
->SetBorderGap(6);
1624 m_cEdit
= new CInPlaceEdit(m_value
, functor(*this, &CPropertyItem::OnEditChanged
));
1625 m_cEdit
->Create(WS_CHILD
| WS_VISIBLE
| ES_AUTOHSCROLL
| ES_LEFT
| WS_TABSTOP
, nullRc
, pWndParent
, 2);
1626 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);
1627 RegisterCtrl(m_cEdit
);
1629 m_cButton
= new CInPlaceButton(functor(*this, &CPropertyItem::OnFileBrowseButton
));
1630 m_cButton
->Create("", WS_CHILD
| WS_VISIBLE
, nullRc
, pWndParent
, 4);
1631 RegisterCtrl(m_cButton
);
1633 // Use file browse icon.
1634 HICON hOpenIcon
= (HICON
)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_FILE_BROWSE
), IMAGE_ICON
, 16, 15, LR_DEFAULTCOLOR
| LR_SHARED
);
1635 m_cButton
->SetIcon(CSize(16, 15), hOpenIcon
);
1636 m_cButton
->SetBorderGap(6);
1642 m_cEdit
->ModifyStyleEx(0, WS_EX_CLIENTEDGE
);
1646 //m_cCombo->ModifyStyleEx( 0,WS_EX_CLIENTEDGE );
1649 MoveInPlaceControl(ctrlRect
);
1653 //////////////////////////////////////////////////////////////////////////
1654 void CPropertyItem::DestroyInPlaceControl(bool bRecursive
)
1656 if (!m_propertyCtrl
->IsExtenedUI() && !m_bForceModified
)
1657 ReceiveFromControl();
1659 SAFE_DELETE(m_pStaticText
);
1660 SAFE_DELETE(m_cNumber
);
1661 SAFE_DELETE(m_cNumber1
);
1662 SAFE_DELETE(m_cNumber2
);
1663 SAFE_DELETE(m_cNumber3
);
1664 SAFE_DELETE(m_cFillSlider
);
1665 SAFE_DELETE(m_cSpline
);
1666 SAFE_DELETE(m_cColorSpline
);
1667 SAFE_DELETE(m_cEdit
);
1668 SAFE_DELETE(m_cCombo
);
1669 SAFE_DELETE(m_cButton
);
1670 SAFE_DELETE(m_cButton2
);
1671 SAFE_DELETE(m_cButton3
);
1672 SAFE_DELETE(m_cButton4
);
1673 SAFE_DELETE(m_cButton5
);
1674 SAFE_DELETE(m_cExpandButton
);
1675 SAFE_DELETE(m_cCheckBox
);
1676 SAFE_DELETE(m_cColorButton
);
1680 int num
= GetChildCount();
1681 for (int i
= 0; i
< num
; i
++)
1683 GetChild(i
)->DestroyInPlaceControl(bRecursive
);
1689 //////////////////////////////////////////////////////////////////////////
1690 void CPropertyItem::MoveInPlaceControl(const CRect
& rect
)
1694 int nButtonWidth
= BUTTON_WIDTH
;
1695 if (m_propertyCtrl
->IsExtenedUI())
1702 if (m_type
== ePropertyColor
)
1704 rc
.right
= rc
.left
+ nButtonWidth
+ 2;
1705 RepositionWindow(m_cButton
, rc
);
1707 rc
.left
+= nButtonWidth
+ 2 + 4;
1708 if (rc
.right
> rc
.left
- 100)
1709 rc
.right
= rc
.left
+ 100;
1713 rc
.left
= rc
.right
- nButtonWidth
;
1714 RepositionWindow(m_cButton
, rc
);
1716 rc
.right
-= nButtonWidth
;
1721 rc
.right
= rc
.left
+ nButtonWidth
+ 2;
1722 RepositionWindow(m_cColorButton
, rc
);
1724 rc
.left
+= nButtonWidth
+ 2 + 4;
1725 if (rc
.right
> rc
.left
- 80)
1726 rc
.right
= rc
.left
+ 80;
1731 brc
.left
= brc
.right
- nButtonWidth
- 2;
1732 m_cButton4
->MoveWindow(brc
, FALSE
);
1733 rc
.right
-= nButtonWidth
+ 4;
1734 m_cButton4
->SetFont(m_propertyCtrl
->GetFont());
1739 brc
.left
= brc
.right
- nButtonWidth
- 2;
1740 m_cButton5
->MoveWindow(brc
, FALSE
);
1741 rc
.right
-= nButtonWidth
+ 4;
1742 m_cButton5
->SetFont(m_propertyCtrl
->GetFont());
1747 brc
.left
= brc
.right
- nButtonWidth
- 2;
1748 RepositionWindow(m_cButton2
, brc
);
1749 rc
.right
-= nButtonWidth
+ 4;
1754 brc
.left
= brc
.right
- nButtonWidth
- 2;
1755 RepositionWindow(m_cButton3
, brc
);
1756 rc
.right
-= nButtonWidth
+ 4;
1762 if (m_cNumber1
&& m_cNumber2
&& m_cNumber3
)
1764 int x
= NUMBER_CTRL_WIDTH
+ 4;
1765 CRect rc0
, rc1
, rc2
, rc3
;
1766 rc0
= CRect(rc
.left
, rc
.top
, rc
.left
+ NUMBER_CTRL_WIDTH
, rc
.bottom
);
1767 rc1
= CRect(rc
.left
+ x
, rc
.top
, rc
.left
+ x
+ NUMBER_CTRL_WIDTH
, rc
.bottom
);
1768 rc2
= CRect(rc
.left
+ x
* 2, rc
.top
, rc
.left
+ x
* 2 + NUMBER_CTRL_WIDTH
, rc
.bottom
);
1769 rc3
= CRect(rc
.left
+ x
* 3, rc
.top
, rc
.left
+ x
* 3 + NUMBER_CTRL_WIDTH
, rc
.bottom
);
1770 RepositionWindow(m_cNumber
, rc0
);
1771 RepositionWindow(m_cNumber1
, rc1
);
1772 RepositionWindow(m_cNumber2
, rc2
);
1773 RepositionWindow(m_cNumber3
, rc3
);
1775 else if (m_cNumber1
&& m_cNumber2
)
1777 int x
= NUMBER_CTRL_WIDTH
+ 4;
1778 CRect rc0
, rc1
, rc2
;
1779 rc0
= CRect(rc
.left
, rc
.top
, rc
.left
+ NUMBER_CTRL_WIDTH
, rc
.bottom
);
1780 rc1
= CRect(rc
.left
+ x
, rc
.top
, rc
.left
+ x
+ NUMBER_CTRL_WIDTH
, rc
.bottom
);
1781 rc2
= CRect(rc
.left
+ x
* 2, rc
.top
, rc
.left
+ x
* 2 + NUMBER_CTRL_WIDTH
, rc
.bottom
);
1782 RepositionWindow(m_cNumber
, rc0
);
1783 RepositionWindow(m_cNumber1
, rc1
);
1784 RepositionWindow(m_cNumber2
, rc2
);
1786 else if (m_cNumber1
)
1788 int x
= NUMBER_CTRL_WIDTH
+ 4;
1790 rc0
= CRect(rc
.left
, rc
.top
, rc
.left
+ NUMBER_CTRL_WIDTH
, rc
.bottom
);
1791 rc1
= CRect(rc
.left
+ x
, rc
.top
, rc
.left
+ x
+ NUMBER_CTRL_WIDTH
, rc
.bottom
);
1792 RepositionWindow(m_cNumber
, rc0
);
1793 RepositionWindow(m_cNumber1
, rc1
);
1797 //rcn.right = rc.left + NUMBER_CTRL_WIDTH;
1798 if (rcn
.Width() > NUMBER_CTRL_WIDTH
)
1799 rcn
.right
= rc
.left
+ NUMBER_CTRL_WIDTH
;
1800 RepositionWindow(m_cNumber
, rcn
);
1804 CRect rcSlider
= rc
;
1805 rcSlider
.left
= rcn
.right
+ 1;
1806 RepositionWindow(m_cFillSlider
, rcSlider
);
1811 RepositionWindow(m_cEdit
, rc
);
1815 RepositionWindow(m_cCombo
, rc
);
1819 // Grow beyond current line.
1820 rc
.bottom
= rc
.top
+ 48;
1822 RepositionWindow(m_cSpline
, rc
);
1826 // Grow beyond current line.
1827 rc
.bottom
= rc
.top
+ 32;
1829 RepositionWindow(m_cColorSpline
, rc
);
1833 //////////////////////////////////////////////////////////////////////////
1834 void CPropertyItem::SetFocus()
1838 m_cNumber
->SetFocus();
1842 m_cEdit
->SetFocus();
1846 m_cCombo
->SetFocus();
1848 if (!m_cNumber
&& !m_cEdit
&& !m_cCombo
)
1849 m_propertyCtrl
->SetFocus();
1852 //////////////////////////////////////////////////////////////////////////
1853 void CPropertyItem::ReceiveFromControl()
1860 m_cEdit
->GetWindowText(str
);
1865 if (!CUndo::IsRecording())
1868 SetValue(m_pEnumDBItem
->NameToValue(m_cCombo
->GetSelectedString()));
1870 SetValue(m_cCombo
->GetSelectedString());
1875 SetValue(m_pEnumDBItem
->NameToValue(m_cCombo
->GetSelectedString()));
1877 SetValue(m_cCombo
->GetSelectedString());
1882 if (m_cNumber1
&& m_cNumber2
&& m_cNumber3
)
1885 val
.Format("%g,%g,%g,%g", m_cNumber
->GetValue(), m_cNumber1
->GetValue(), m_cNumber2
->GetValue(), m_cNumber3
->GetValue());
1888 if (m_cNumber1
&& m_cNumber2
)
1891 val
.Format("%g,%g,%g", m_cNumber
->GetValue(), m_cNumber1
->GetValue(), m_cNumber2
->GetValue());
1894 else if (m_cNumber1
)
1897 val
.Format("%g,%g", m_cNumber
->GetValue(), m_cNumber1
->GetValue());
1902 SetValue(m_cNumber
->GetValueAsString());
1905 if (m_cSpline
!= 0 || m_cColorSpline
!= 0)
1907 // Variable was already directly updated.
1908 //OnVariableChange(m_pVariable);
1910 m_pVariable
->Get(m_value
);
1911 m_propertyCtrl
->OnItemChange(this);
1915 //////////////////////////////////////////////////////////////////////////
1916 void CPropertyItem::SendToControl()
1918 bool bInPlaceCtrl
= m_propertyCtrl
->IsExtenedUI();
1921 if (m_type
== ePropertyColor
)
1923 COLORREF clr
= StringToColor(m_value
);
1924 m_cButton
->SetColorFace(clr
);
1925 m_cButton
->RedrawWindow();
1926 bInPlaceCtrl
= true;
1928 m_cButton
->Invalidate();
1932 COLORREF clr
= StringToColor(m_value
);
1933 m_cColorButton
->SetColor(clr
);
1934 m_cColorButton
->Invalidate();
1935 bInPlaceCtrl
= true;
1939 m_cCheckBox
->SetChecked(GetBoolValue() ? BST_CHECKED
: BST_UNCHECKED
);
1940 m_cCheckBox
->Invalidate();
1944 m_cEdit
->SetText(m_value
);
1945 bInPlaceCtrl
= true;
1946 m_cEdit
->Invalidate();
1950 if (m_type
== ePropertyBool
)
1951 m_cCombo
->SetCurSel(GetBoolValue() ? 0 : 1);
1955 m_cCombo
->SelectString(-1, m_pEnumDBItem
->ValueToName(m_value
));
1957 m_cCombo
->SelectString(-1, m_value
);
1959 bInPlaceCtrl
= true;
1960 m_cCombo
->Invalidate();
1964 if (m_cNumber1
&& m_cNumber2
&& m_cNumber3
)
1967 sscanf(m_value
, "%f,%f,%f,%f", &x
, &y
, &z
, &w
);
1968 m_cNumber
->SetValue(x
);
1969 m_cNumber1
->SetValue(y
);
1970 m_cNumber2
->SetValue(z
);
1971 m_cNumber3
->SetValue(w
);
1973 else if (m_cNumber1
&& m_cNumber2
)
1976 sscanf(m_value
, "%f,%f,%f", &x
, &y
, &z
);
1977 m_cNumber
->SetValue(x
);
1978 m_cNumber1
->SetValue(y
);
1979 m_cNumber2
->SetValue(z
);
1981 else if (m_cNumber1
)
1984 sscanf(m_value
, "%f,%f", &x
, &y
);
1985 m_cNumber
->SetValue(x
);
1986 m_cNumber1
->SetValue(y
);
1990 m_cNumber
->SetValue(atof(m_value
));
1992 bInPlaceCtrl
= true;
1993 m_cNumber
->Invalidate();
1997 m_cFillSlider
->SetValue(atof(m_value
));
1998 bInPlaceCtrl
= true;
1999 m_cFillSlider
->Invalidate();
2004 m_propertyCtrl
->GetItemRect(this, rc
);
2005 m_propertyCtrl
->InvalidateRect(rc
, TRUE
);
2007 CWnd
* pFocusWindow
= CWnd::GetFocus();
2008 if (pFocusWindow
&& m_propertyCtrl
->IsChild(pFocusWindow
))
2009 m_propertyCtrl
->SetFocus();
2013 m_cSpline
->SetSpline(m_pVariable
->GetSpline(true), TRUE
);
2017 m_cColorSpline
->SetSpline(m_pVariable
->GetSpline(true), TRUE
);
2019 if (m_pVariable
&& m_pVariable
->GetFlags() & IVariable::UI_HIGHLIGHT_EDITED
)
2020 CheckControlActiveColor();
2023 //////////////////////////////////////////////////////////////////////////
2024 bool CPropertyItem::HasDefaultValue(bool bChildren
) const
2026 if (m_pVariable
&& !m_pVariable
->HasDefaultValue())
2031 // Evaluate children.
2032 for (int i
= 0; i
< m_childs
.size(); i
++)
2034 if (!m_childs
[i
]->HasDefaultValue(true))
2042 //////////////////////////////////////////////////////////////////////////
2043 void CPropertyItem::CheckControlActiveColor()
2047 COLORREF clrStaticText
= XTPColorManager()->LightColor(GetXtremeColor(COLOR_3DFACE
), GetXtremeColor(COLOR_BTNTEXT
), 30);
2048 COLORREF nTextColor
= HasDefaultValue(true) ? clrStaticText
: GetXtremeColor(COLOR_HIGHLIGHT
);
2049 if (m_pStaticText
->GetTextColor() != nTextColor
)
2050 m_pStaticText
->SetTextColor(nTextColor
);
2053 if (m_cExpandButton
)
2055 static COLORREF nDefColor
= ::GetSysColor(COLOR_BTNFACE
);
2056 static COLORREF nDefTextColor
= ::GetSysColor(COLOR_BTNTEXT
);
2057 static COLORREF nNondefColor
= GetXtremeColor(COLOR_HIGHLIGHT
);
2058 static COLORREF nNondefTextColor
= GetXtremeColor(COLOR_HIGHLIGHTTEXT
);
2059 bool bDefault
= HasDefaultValue(true);
2060 COLORREF nColor
= bDefault
? nDefColor
: nNondefColor
;
2062 if (m_cExpandButton
->GetColor() != nColor
)
2064 m_cExpandButton
->SetColor(nColor
);
2065 m_cExpandButton
->SetTextColor(bDefault
? nDefTextColor
: nNondefTextColor
);
2070 //////////////////////////////////////////////////////////////////////////
2071 void CPropertyItem::OnComboSelection()
2073 ReceiveFromControl();
2077 //////////////////////////////////////////////////////////////////////////
2078 void CPropertyItem::DrawValue(CDC
* dc
, CRect rect
)
2081 dc
->SetBkMode(TRANSPARENT
);
2083 CString val
= GetDrawValue();
2085 if (m_type
== ePropertyBool
)
2087 int sz
= rect
.bottom
- rect
.top
- 1;
2088 int borderwidth
= (int)(sz
* 0.13f
); //white frame border
2089 int borderoffset
= (int)(sz
* 0.1f
); //offset from the frameborder
2090 CPoint
p1(rect
.left
, rect
.top
+ 1); // box
2091 CPoint
p2(rect
.left
+ borderwidth
, rect
.top
+ 1 + borderwidth
); //check-mark
2093 const bool bPropertyCtrlIsDisabled
= m_propertyCtrl
->IsReadOnly() || m_propertyCtrl
->IsGrayed() || (m_propertyCtrl
->IsWindowEnabled() != TRUE
);
2094 const bool bShowInactiveFrame
= IsDisabled() || bPropertyCtrlIsDisabled
;
2096 CRect
rc(p1
.x
, p1
.y
, p1
.x
+ sz
, p1
.y
+ sz
);
2097 dc
->DrawFrameControl(rc
, DFC_BUTTON
, DFCS_BUTTON3STATE
| (bShowInactiveFrame
? DFCS_INACTIVE
: 0));
2100 COLORREF color
= StringToColor(val
);
2101 if (bShowInactiveFrame
)
2103 color
= (COLORREF
)ColorB::ComputeAvgCol_Fast(RGB(255, 255, 255), color
);
2105 CPen
pen(PS_SOLID
, 1, color
);
2106 CPen
* pPen
= dc
->SelectObject(&pen
);
2108 //Draw bold check-mark
2109 int number_of_lines
= sz
/ 8;
2110 number_of_lines
+= 1;
2111 for (int i
= 0; i
< number_of_lines
; i
++)
2113 CPoint start
= p2
+ CPoint(i
, 0);
2114 start
.y
+= ((sz
- borderwidth
* 2) / 2);
2115 start
.x
+= borderoffset
;
2117 CPoint middle
= p2
+ CPoint(i
, 0);
2118 middle
.y
+= sz
- borderwidth
* 2;
2119 middle
.x
+= (sz
- borderwidth
- number_of_lines
) / 2;
2120 middle
.y
-= borderoffset
;
2122 CPoint end
= p2
+ CPoint(i
, 0);
2123 end
.x
+= sz
- borderwidth
* 2 - number_of_lines
;
2124 end
.x
-= borderoffset
;
2125 end
.y
+= borderoffset
;
2133 //offset text with scaling
2134 rect
.left
+= (int)(sz
* 1.25f
);
2136 else if (m_type
== ePropertyFile
|| m_type
== ePropertyTexture
|| m_type
== ePropertyModel
)
2139 // Check if file name fits into the designated rectangle.
2140 CSize textSize
= dc
->GetTextExtent(val
, val
.GetLength());
2141 if (textSize
.cx
> rect
.Width())
2144 if (strcmp(PathUtil::GetExt(val
), "") != 0)
2145 val
= CString("...\\") + PathUtil::GetFile(val
);
2148 else if (m_type
== ePropertyColor
)
2150 //CRect rc( CPoint(rect.right-BUTTON_WIDTH,rect.top),CSize(BUTTON_WIDTH,rect.bottom-rect.top) );
2151 CRect
rc(CPoint(rect
.left
, rect
.top
+ 1), CSize(BUTTON_WIDTH
+ 2, rect
.bottom
- rect
.top
- 2));
2152 //CPen pen( PS_SOLID,1,RGB(128,128,128));
2153 CPen
pen(PS_SOLID
, 1, RGB(0, 0, 0));
2154 CBrush
brush(StringToColor(val
));
2155 CPen
* pOldPen
= dc
->SelectObject(&pen
);
2156 CBrush
* pOldBrush
= dc
->SelectObject(&brush
);
2158 //COLORREF col = StringToColor(m_value);
2159 //rc.DeflateRect( 1,1 );
2160 //dc->FillSolidRect( rc,col );
2161 dc
->SelectObject(pOldPen
);
2162 dc
->SelectObject(pOldBrush
);
2163 rect
.left
= rect
.left
+ BUTTON_WIDTH
+ 2 + 4;
2165 else if (m_pVariable
!= 0 && m_pVariable
->GetSpline(false) && m_pVariable
->GetSpline(false)->GetKeyCount() > 0)
2167 // Draw mini-curve or gradient.
2170 ISplineInterpolator
* pSpline
= m_pVariable
->GetSpline(true);
2171 int width
= min(rect
.Width() - 1, 128);
2172 for (int x
= 0; x
< width
; x
++)
2174 float time
= float(x
) / (width
- 1);
2175 ISplineInterpolator::ValueType val
;
2176 pSpline
->Interpolate(time
, val
);
2178 if (m_type
== ePropertyColorCurve
)
2180 COLORREF col
= RGB(pos_round(val
[0] * 255), pos_round(val
[1] * 255), pos_round(val
[2] * 255));
2181 CPen
pen(PS_SOLID
, 1, col
);
2183 pOldPen
= dc
->SelectObject(&pen
);
2185 dc
->SelectObject(&pen
);
2186 dc
->MoveTo(CPoint(rect
.left
+ x
, rect
.bottom
));
2187 dc
->LineTo(CPoint(rect
.left
+ x
, rect
.top
));
2189 else if (m_type
== ePropertyFloatCurve
)
2192 point
.x
= rect
.left
+ x
;
2193 point
.y
= int_round((rect
.bottom
- 1) * (1.f
- val
[0]) + (rect
.top
+ 1) * val
[0]);
2201 dc
->SelectObject(pOldPen
);
2209 //////////////////////////////////////////////////////////////////////////
2210 // Draw filled bar like in CFillSliderCtrl.
2211 //////////////////////////////////////////////////////////////////////////
2212 if (m_type == ePropertyFloat || m_type == ePropertyInt || m_type == ePropertyAngle)
2215 rc.left += NUMBER_CTRL_WIDTH;
2219 float value = atof(m_value);
2220 float min = m_rangeMin/m_valueMultiplier;
2221 float max = m_rangeMax/m_valueMultiplier;
2224 float pos = (value-min) / fabs(max-min);
2225 int splitPos = rc.left + pos * rc.Width();
2227 // Paint filled rect.
2229 fillRc.right = splitPos;
2230 dc->FillRect(fillRc,CBrush::FromHandle((HBRUSH)GetStockObject(LTGRAY_BRUSH)) );
2232 // Paint empty rect.
2234 emptyRc.left = splitPos+1;
2235 emptyRc.IntersectRect(emptyRc,rc);
2236 dc->FillRect(emptyRc,CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)) );
2242 ::DrawTextEx(dc
->GetSafeHdc(), val
.GetBuffer(), val
.GetLength(), textRc
, DT_END_ELLIPSIS
| DT_LEFT
| DT_SINGLELINE
| DT_VCENTER
, NULL
);
2245 COLORREF
CPropertyItem::StringToColor(const CString
& value
)
2250 res
= sscanf(value
, "%f,%f,%f", &r
, &g
, &b
);
2252 res
= sscanf(value
, "R:%f,G:%f,B:%f", &r
, &g
, &b
);
2254 res
= sscanf(value
, "R:%f G:%f B:%f", &r
, &g
, &b
);
2256 res
= sscanf(value
, "%f %f %f", &r
, &g
, &b
);
2259 sscanf(value
, "%f", &r
);
2266 return RGB(ir
, ig
, ib
);
2269 bool CPropertyItem::GetBoolValue()
2271 if (stricmp(m_value
, "true") == 0 || atoi(m_value
) != 0)
2277 //////////////////////////////////////////////////////////////////////////
2278 const char* CPropertyItem::GetValue() const
2283 //////////////////////////////////////////////////////////////////////////
2284 void CPropertyItem::SetValue(const char* sValue
, bool bRecordUndo
, bool bForceModified
)
2286 if (bRecordUndo
&& IsDisabled())
2289 _smart_ptr
<CPropertyItem
> holder
= this; // Make sure we are not released during this function.
2291 CString value
= sValue
;
2295 case ePropertyAiTerritory
:
2296 #ifdef USE_SIMPLIFIED_AI_TERRITORY_SHAPE
2297 if ((value
== "<None>") || m_value
.Compare(value
))
2299 if ((value
== "<Auto>") || (value
== "<None>") || m_value
.Compare(value
))
2302 CPropertyItem
* pPropertyItem
= GetParent()->FindItemByFullName("::AITerritoryAndWave::Wave");
2305 pPropertyItem
->SetValue("<None>");
2311 if (stricmp(value
, "true") == 0 || atof(value
) != 0)
2317 case ePropertyVector2
:
2318 if (value
.Find(',') < 0)
2319 value
= value
+ ", " + value
;
2322 case ePropertyVector4
:
2323 if (value
.Find(',') < 0)
2324 value
= value
+ ", " + value
+ ", " + value
+ ", " + value
;
2327 case ePropertyVector
:
2328 if (value
.Find(',') < 0)
2329 value
= value
+ ", " + value
+ ", " + value
;
2332 case ePropertyTexture
:
2333 case ePropertyModel
:
2334 case ePropertyMaterial
:
2335 value
.Replace('\\', '/');
2339 // correct the length of value
2342 case ePropertyTexture
:
2343 case ePropertyModel
:
2344 case ePropertyMaterial
:
2346 if (value
.GetLength() >= MAX_PATH
)
2347 value
= value
.Left(MAX_PATH
);
2351 bool bModified
= m_bForceModified
|| bForceModified
|| m_value
.Compare(value
) != 0;
2352 bool bStoreUndo
= (m_value
.Compare(value
) != 0 || bForceModified
) && bRecordUndo
;
2354 std::unique_ptr
<CUndo
> undo
;
2355 if (bStoreUndo
&& !CUndo::IsRecording())
2357 if (!m_propertyCtrl
->CallUndoFunc(this))
2358 undo
.reset(new CUndo(GetName() + " Modified"));
2367 if (m_propertyCtrl
->IsStoreUndoByItems() && bStoreUndo
&& CUndo::IsRecording())
2368 CUndo::Record(new CUndoVariableChange(m_pVariable
, "PropertyChange"));
2370 if (m_bForceModified
|| bForceModified
)
2371 m_pVariable
->SetForceModified(true);
2377 //////////////////////////////////////////////////////////////////////////
2378 // DEPRICATED (For XmlNode).
2379 //////////////////////////////////////////////////////////////////////////
2381 m_node
->setAttr(VALUE_ATTR
, m_value
);
2382 //CString xml = m_node->getXML();
2389 if (m_bEditChildren
)
2391 // Extract child components.
2393 for (int i
= 0; i
< m_childs
.size(); i
++)
2395 CString elem
= m_value
.Tokenize(", ", pos
);
2396 m_childs
[i
]->m_value
= elem
;
2397 m_childs
[i
]->SendToControl();
2402 m_parent
->OnChildChanged(this);
2403 // If Value changed mark document modified.
2404 // Notify parent that this Item have been modified.
2405 m_propertyCtrl
->OnItemChange(this);
2410 //////////////////////////////////////////////////////////////////////////
2411 void CPropertyItem::VarToValue()
2413 assert(m_pVariable
!= 0);
2415 if (m_type
== ePropertyColor
)
2417 if (m_pVariable
->GetType() == IVariable::VECTOR
)
2420 m_pVariable
->Get(v
);
2421 COLORREF col
= CMFCUtils::ColorLinearToGamma(ColorF(v
.x
, v
.y
, v
.z
));
2422 m_value
.Format("%d,%d,%d", GetRValue(col
), GetGValue(col
), GetBValue(col
));
2427 m_pVariable
->Get(col
);
2428 m_value
.Format("%d,%d,%d", GetRValue((uint32
)col
), GetGValue((uint32
)col
), GetBValue((uint32
)col
));
2433 if (m_type
== ePropertyFloat
)
2436 m_pVariable
->Get(value
);
2438 PropertyItem_Private::FormatFloatForUICString(m_value
, FLOAT_NUM_DIGITS
, value
);
2442 m_value
= m_pVariable
->GetDisplayValue();
2445 if (m_type
== ePropertySOHelper
|| m_type
== ePropertySONavHelper
|| m_type
== ePropertySOAnimHelper
)
2447 // hide smart object class part
2448 int f
= m_value
.Find(':');
2450 m_value
.Delete(0, f
+ 1);
2454 CString
CPropertyItem::GetDrawValue()
2456 CString value
= m_value
;
2459 value
= m_pEnumDBItem
->ValueToName(value
);
2461 if (m_valueMultiplier
!= 1.f
)
2463 float f
= atof(m_value
) * m_valueMultiplier
;
2464 if (m_type
== ePropertyInt
)
2465 value
.Format("%d", int_round(f
));
2467 value
.Format("%g", f
);
2468 if (m_valueMultiplier
== 100)
2471 else if (m_type
== ePropertyBool
)
2475 else if (m_type
== ePropertyFloatCurve
|| m_type
== ePropertyColorCurve
)
2477 // Don't display actual values in field.
2478 if (!value
.IsEmpty())
2481 else if (m_type
== ePropertySequenceId
)
2483 uint32 id
= (uint32
)atoi(value
);
2484 IAnimSequence
* pSeq
= GetIEditor()->GetMovieSystem()->FindSequenceById(id
);
2485 if (pSeq
) // Show its human-readable name instead of its ID.
2486 return pSeq
->GetName();
2492 //////////////////////////////////////////////////////////////////////////
2493 void CPropertyItem::ValueToVar()
2495 assert(m_pVariable
!= NULL
);
2497 _smart_ptr
<CPropertyItem
> holder
= this; // Make sure we are not released during the call to variable Set.
2499 if (m_type
== ePropertyColor
)
2501 COLORREF col
= StringToColor(m_value
);
2502 if (m_pVariable
->GetType() == IVariable::VECTOR
)
2504 ColorF colLin
= CMFCUtils::ColorGammaToLinear(col
);
2505 m_pVariable
->Set(Vec3(colLin
.r
, colLin
.g
, colLin
.b
));
2508 m_pVariable
->Set((int)col
);
2510 else if (m_type
== ePropertySOHelper
|| m_type
== ePropertySONavHelper
|| m_type
== ePropertySOAnimHelper
)
2512 // keep smart object class part
2515 m_pVariable
->Get(oldValue
);
2516 int f
= oldValue
.Find(':');
2518 oldValue
.Truncate(f
+ 1);
2520 CString
newValue(m_value
);
2521 f
= newValue
.Find(':');
2523 newValue
.Delete(0, f
+ 1);
2525 m_pVariable
->Set(oldValue
+ newValue
);
2527 else if (m_type
!= ePropertyInvalid
)
2529 m_pVariable
->SetDisplayValue(m_value
);
2533 //////////////////////////////////////////////////////////////////////////
2534 void CPropertyItem::OnVariableChange(IVariable
* pVar
)
2536 assert(pVar
!= 0 && pVar
== m_pVariable
);
2538 // When variable changes, invalidate UI.
2544 if (m_type
== ePropertySelection
)
2545 m_enumList
= m_pVariable
->GetEnumList();
2549 if (m_bEditChildren
)
2553 case ePropertyAiPFPropertiesList
:
2554 AddChildrenForPFProperties();
2557 case ePropertyAiEntityClasses
:
2558 AddChildrenForAIEntityClasses();
2563 // Parse comma-separated values, set children.
2564 bool bPrevIgnore
= m_bIgnoreChildsUpdate
;
2565 m_bIgnoreChildsUpdate
= true;
2568 for (int i
= 0; i
< m_childs
.size(); i
++)
2570 CString sElem
= pos
>= 0 ? m_value
.Tokenize(", ", pos
) : CString();
2571 m_childs
[i
]->SetValue(sElem
, false);
2573 m_bIgnoreChildsUpdate
= bPrevIgnore
;
2579 m_parent
->OnChildChanged(this);
2581 // If Value changed mark document modified.
2582 // Notify parent that this Item have been modified.
2583 // This may delete this control...
2584 m_propertyCtrl
->OnItemChange(this);
2586 //////////////////////////////////////////////////////////////////////////
2587 CPropertyItem::TDValues
* CPropertyItem::GetEnumValues(const char* strPropertyName
)
2589 TDValuesContainer::iterator itIterator
;
2590 TDValuesContainer
& cEnumContainer
= CUIEnumerations::GetUIEnumerationsInstance().GetStandardNameContainer();
2592 itIterator
= cEnumContainer
.find(strPropertyName
);
2593 if (itIterator
== cEnumContainer
.end())
2598 return &itIterator
->second
;
2601 //////////////////////////////////////////////////////////////////////////
2602 void CPropertyItem::OnMouseWheel(UINT nFlags
, short zDelta
, CPoint point
)
2604 if (m_propertyCtrl
->IsReadOnly())
2609 int sel
= m_cCombo
->GetCurSel();
2613 if (m_cCombo
->SetCurSel(sel
) == CB_ERR
)
2614 m_cCombo
->SetCurSel(0);
2619 if (m_cCombo
->SetCurSel(sel
) == CB_ERR
)
2620 m_cCombo
->SetCurSel(m_cCombo
->GetCount() - 1);
2627 m_cNumber
->SetValue(m_cNumber
->GetValue() + m_cNumber
->GetStep());
2631 m_cNumber
->SetValue(m_cNumber
->GetValue() - m_cNumber
->GetStep());
2633 ReceiveFromControl();
2637 //////////////////////////////////////////////////////////////////////////
2638 void CPropertyItem::OnLButtonDblClk(UINT nFlags
, CPoint point
)
2640 if (m_propertyCtrl
->IsReadOnly())
2646 if (m_type
== ePropertyBool
)
2648 // Swap boolean value.
2656 // Simulate button click.
2662 //////////////////////////////////////////////////////////////////////////
2663 void CPropertyItem::OnLButtonDown(UINT nFlags
, CPoint point
)
2665 if (m_propertyCtrl
->IsReadOnly())
2668 if (m_type
== ePropertyBool
)
2671 m_propertyCtrl
->GetItemRect(this, rect
);
2672 rect
= m_propertyCtrl
->GetItemValueRect(rect
);
2674 CPoint
p(rect
.left
- 2, rect
.top
+ 1);
2675 int sz
= rect
.bottom
- rect
.top
;
2676 rect
= CRect(p
.x
, p
.y
, p
.x
+ sz
, p
.y
+ sz
);
2678 if (rect
.PtInRect(point
))
2680 // Swap boolean value.
2689 //////////////////////////////////////////////////////////////////////////
2690 void CPropertyItem::OnCheckBoxButton()
2693 if (m_cCheckBox
->GetChecked() == BST_CHECKED
)
2699 //////////////////////////////////////////////////////////////////////////
2700 void CPropertyItem::OnColorBrowseButton()
2703 COLORREF clr = StringToColor(m_value);
2704 if (GetIEditor()->SelectColor(clr,m_propertyCtrl))
2710 //val.Format( "R:%d G:%d B:%d",r,g,b );
2712 val.Format( "%d,%d,%d",r,g,b );
2714 m_propertyCtrl->Invalidate();
2715 //RedrawWindow( OwnerProperties->hWnd,NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN );
2721 COLORREF orginalColor
= StringToColor(m_value
);
2722 COLORREF clr
= orginalColor
;
2723 CCustomColorDialog
dlg(orginalColor
, CC_FULLOPEN
, m_propertyCtrl
);
2724 dlg
.SetColorChangeCallback(functor(*this, &CPropertyItem::OnColorChange
));
2725 if (dlg
.DoModal() == IDOK
)
2727 clr
= dlg
.GetColor();
2728 if (clr
!= orginalColor
)
2732 r
= GetRValue(orginalColor
);
2733 g
= GetGValue(orginalColor
);
2734 b
= GetBValue(orginalColor
);
2735 val
.Format("%d,%d,%d", r
, g
, b
);
2736 SetValue(val
, false);
2741 val
.Format("%d,%d,%d", r
, g
, b
);
2743 m_propertyCtrl
->InvalidateCtrl();
2748 if (StringToColor(m_value
) != orginalColor
)
2755 val
.Format("%d,%d,%d", r
, g
, b
);
2757 m_propertyCtrl
->InvalidateCtrl();
2761 m_cButton
->Invalidate();
2764 //////////////////////////////////////////////////////////////////////////
2765 void CPropertyItem::OnColorChange(COLORREF clr
)
2767 GetIEditor()->GetIUndoManager()->Suspend();
2772 //val.Format( "R:%d G:%d B:%d",r,g,b );
2774 val
.Format("%d,%d,%d", r
, g
, b
);
2776 GetIEditor()->UpdateViews(eRedrawViewports
);
2777 //GetIEditor()->Notify( eNotify_OnIdleUpdate );
2778 m_propertyCtrl
->InvalidateCtrl();
2779 GetIEditor()->GetIUndoManager()->Resume();
2782 m_cButton
->Invalidate();
2785 //////////////////////////////////////////////////////////////////////////
2786 void CPropertyItem::OnFileBrowseButton()
2788 CString
tempValue("");
2790 if (m_value
.IsEmpty() == false)
2792 if (strcmp(PathUtil::GetExt(m_value
), "") == 0)
2798 tempValue
= m_value
;
2802 CString startPath
= PathUtil::GetPathWithoutFilename(tempValue
);
2804 m_propertyCtrl
->HideBitmapTooltip();
2806 if (m_type
== ePropertyTexture
)
2808 dll_string newValue
= GetIEditor()->GetResourceSelectorHost()->SelectResource("Texture", tempValue
);
2809 SetValue(newValue
.c_str(), true, false);
2811 else if (m_type
== ePropertyGeomCache
)
2813 dll_string newValue
= GetIEditor()->GetResourceSelectorHost()->SelectResource("GeometryCache", tempValue
);
2814 SetValue(newValue
.c_str(), true, true);
2818 CString relativeFilename
= tempValue
;
2819 if (CFileUtil::SelectSingleFile(EFILE_TYPE_ANY
, relativeFilename
, "", startPath
))
2821 SetValue(relativeFilename
, true, false);
2826 //////////////////////////////////////////////////////////////////////////
2827 void CPropertyItem::OnResourceSelectorButton()
2829 m_propertyCtrl
->HideBitmapTooltip();
2831 dll_string newValue
= GetIEditor()->GetResourceSelectorHost()->SelectResource(PropertyTypeToResourceType(m_type
), GetValue(), nullptr, m_pVariable
->GetUserData());
2832 if (strcmp(GetValue(), newValue
.c_str()) != 0)
2834 SetValue(newValue
.c_str());
2838 //////////////////////////////////////////////////////////////////////////
2839 void CPropertyItem::OnTextureEditButton()
2841 CFileUtil::EditTextureFile(m_value
, true);
2843 //////////////////////////////////////////////////////////////////////////
2844 void CPropertyItem::OnPsdEditButton()
2846 CString dccFilename
;
2847 if (CFileUtil::CalculateDccFilename(m_value
, dccFilename
))
2849 CFileUtil::EditTextureFile(dccFilename
, true);
2854 cry_sprintf(buff
, "Failed to find psd file for texture: '%s'", m_value
);
2855 CQuestionDialog::SCritical("Error", buff
);
2859 //////////////////////////////////////////////////////////////////////////
2860 void CPropertyItem::OnAnimationApplyButton()
2862 CUIEnumerations
& roGeneralProxy
= CUIEnumerations::GetUIEnumerationsInstance();
2863 std::vector
<string
> cSelectedAnimations
;
2864 size_t nTotalAnimations(0);
2865 size_t nCurrentAnimation(0);
2867 string combinedString
= GetIEditor()->GetResourceSelectorHost()->GetGlobalSelection("animation");
2868 SplitString(combinedString
, cSelectedAnimations
, ',');
2870 nTotalAnimations
= cSelectedAnimations
.size();
2871 for (nCurrentAnimation
= 0; nCurrentAnimation
< nTotalAnimations
; ++nCurrentAnimation
)
2873 string
& rstrCurrentAnimAction
= cSelectedAnimations
[nCurrentAnimation
];
2874 if (rstrCurrentAnimAction
.GetLength())
2876 m_pVariable
->Set(rstrCurrentAnimAction
);
2882 //////////////////////////////////////////////////////////////////////////
2883 void CPropertyItem::ReloadValues()
2887 ParseXmlNode(false);
2889 SetVariable(m_pVariable
);
2890 for (int i
= 0; i
< GetChildCount(); i
++)
2892 GetChild(i
)->ReloadValues();
2897 //////////////////////////////////////////////////////////////////////////
2898 CString
CPropertyItem::GetTip() const
2900 if (!m_tip
.IsEmpty() || m_name
.Left(1) == "_")
2904 for (int i
= 0; i
< NumPropertyTypes
; i
++)
2906 if (m_type
== s_propertyTypeNames
[i
].type
)
2908 type
= s_propertyTypeNames
[i
].name
;
2913 CString tip
= CString("[") + type
+ "] " + m_name
+ " = " + m_value
;
2915 if (HasScriptDefault())
2917 tip
+= " [Script Default: ";
2918 if (m_strScriptDefault
.IsEmpty())
2921 tip
+= m_strScriptDefault
;
2927 CString description
= m_pVariable
->GetDescription();
2928 if (!description
.IsEmpty())
2930 tip
+= CString(" ") + description
;
2936 //////////////////////////////////////////////////////////////////////////
2937 void CPropertyItem::OnEditChanged()
2939 ReceiveFromControl();
2942 //////////////////////////////////////////////////////////////////////////
2943 void CPropertyItem::OnNumberCtrlUpdate(CNumberCtrl
* ctrl
)
2945 ReceiveFromControl();
2948 //////////////////////////////////////////////////////////////////////////
2949 void CPropertyItem::OnFillSliderCtrlUpdate(CSliderCtrlEx
* ctrl
)
2953 float fValue
= m_cFillSlider
->GetValue();
2957 // Round to next power of 10 below step.
2958 float fRound
= pow(10.f
, floor(log(m_step
) / log(10.f
))) / m_valueMultiplier
;
2959 fValue
= int_round(fValue
/ fRound
) * fRound
;
2961 fValue
= clamp_tpl(fValue
, m_rangeMin
, m_rangeMax
);
2964 val
.Format("%g", fValue
);
2965 SetValue(val
, true, true);
2969 //////////////////////////////////////////////////////////////////////////
2970 void CPropertyItem::OnEditDeprecatedProperty()
2973 if (GetIEditor()->EditDeprecatedProperty(m_type
, m_value
.GetString(), new_value
))
2975 SetValue(new_value
);
2979 //////////////////////////////////////////////////////////////////////////
2980 void CPropertyItem::OnMaterialBrowseButton()
2982 // Open material browser dialog.
2983 CString name
= GetValue();
2984 IDataBaseItem
* pItem
= GetIEditor()->GetDBItemManager(EDB_TYPE_MATERIAL
)->FindItemByName(name
.GetBuffer());
2985 GetIEditor()->OpenAndFocusDataBase(EDB_TYPE_MATERIAL
, pItem
);
2988 //////////////////////////////////////////////////////////////////////////
2989 void CPropertyItem::OnMaterialPickSelectedButton()
2991 // Open material browser dialog.
2992 IDataBaseItem
* pItem
= GetIEditor()->GetDBItemManager(EDB_TYPE_MATERIAL
)->GetSelectedItem();
2994 SetValue(pItem
->GetName());
2999 //////////////////////////////////////////////////////////////////////////
3000 void CPropertyItem::OnSequenceBrowseButton()
3002 CSelectSequenceDialog
gtDlg(m_propertyCtrl
);
3003 gtDlg
.PreSelectItem(GetValue());
3004 if (gtDlg
.DoModal() == IDOK
)
3005 SetValue(gtDlg
.GetSelectedItem());
3008 //////////////////////////////////////////////////////////////////////////
3009 void CPropertyItem::OnSequenceIdBrowseButton()
3011 CSelectSequenceDialog
gtDlg(m_propertyCtrl
);
3012 uint32 id
= (uint32
)atoi(GetValue());
3013 IAnimSequence
* pSeq
= GetIEditor()->GetMovieSystem()->FindSequenceById(id
);
3015 gtDlg
.PreSelectItem(pSeq
->GetName());
3016 if (gtDlg
.DoModal() == IDOK
)
3018 pSeq
= GetIEditor()->GetMovieSystem()->FindSequence(gtDlg
.GetSelectedItem());
3020 if (pSeq
->GetId() > 0) // This sequence is a new one with a valid ID.
3023 buf
.Format("%d", pSeq
->GetId());
3026 else // This sequence is an old one without an ID.
3028 CQuestionDialog::SCritical(QObject::tr(""), QObject::tr("This is an old sequence without an ID.\nSo it cannot be used with the new ID-based linking."));
3033 void CPropertyItem::OnMissionObjButton()
3035 CSelectMissionObjectiveDialog
gtDlg(m_propertyCtrl
);
3036 gtDlg
.PreSelectItem(GetValue());
3037 if (gtDlg
.DoModal() == IDOK
)
3038 SetValue(gtDlg
.GetSelectedItem());
3041 //////////////////////////////////////////////////////////////////////////
3042 void CPropertyItem::OnUserBrowseButton()
3044 IVariable::IGetCustomItems
* pGetCustomItems
= static_cast<IVariable::IGetCustomItems
*>(m_pVariable
->GetUserData());
3045 if (pGetCustomItems
!= 0)
3047 std::vector
<IVariable::IGetCustomItems::SItem
> items
;
3049 // call the user supplied callback to fill-in items and get dialog title
3050 bool bShowIt
= pGetCustomItems
->GetItems(m_pVariable
, items
, dlgTitle
);
3051 if (bShowIt
) // if func didn't veto, show the dialog
3053 CGenericSelectItemDialog
gtDlg(m_propertyCtrl
);
3054 if (pGetCustomItems
->UseTree())
3056 gtDlg
.SetMode(CGenericSelectItemDialog::eMODE_TREE
);
3057 const char* szSep
= pGetCustomItems
->GetTreeSeparator();
3061 gtDlg
.SetTreeSeparator(sep
);
3064 gtDlg
.SetItems(items
);
3065 if (dlgTitle
.IsEmpty() == false)
3066 gtDlg
.SetTitle(CString(dlgTitle
.GetString()));
3067 gtDlg
.PreSelectItem(GetValue());
3068 if (gtDlg
.DoModal() == IDOK
)
3070 CString selectedItemStr
= gtDlg
.GetSelectedItem();
3072 if (selectedItemStr
.IsEmpty() == false)
3074 SetValue(selectedItemStr
);
3081 //////////////////////////////////////////////////////////////////////////
3082 void CPropertyItem::OnLocalStringBrowseButton()
3084 std::vector
<IVariable::IGetCustomItems::SItem
> items
;
3085 ILocalizationManager
* pMgr
= gEnv
->pSystem
->GetLocalizationManager();
3088 int nCount
= pMgr
->GetLocalizedStringCount();
3091 items
.reserve(nCount
);
3092 IVariable::IGetCustomItems::SItem item
;
3093 SLocalizedInfoEditor sInfo
;
3094 for (int i
= 0; i
< nCount
; ++i
)
3096 if (pMgr
->GetLocalizedInfoByIndex(i
, sInfo
))
3098 item
.desc
= _T("English Text:\r\n");
3099 item
.desc
+= Unicode::Convert
<wstring
>(sInfo
.sUtf8TranslatedText
).c_str();
3100 item
.name
= sInfo
.sKey
;
3101 items
.push_back(item
);
3105 CGenericSelectItemDialog
gtDlg(m_propertyCtrl
);
3106 const bool bUseTree
= true;
3109 gtDlg
.SetMode(CGenericSelectItemDialog::eMODE_TREE
);
3110 gtDlg
.SetTreeSeparator("/");
3112 gtDlg
.SetItems(items
);
3113 gtDlg
.SetTitle(_T("Choose Localized String"));
3114 CString preselect
= GetValue();
3115 if (!preselect
.IsEmpty() && preselect
.GetAt(0) == '@')
3116 preselect
= preselect
.Mid(1);
3117 gtDlg
.PreSelectItem(preselect
);
3118 if (gtDlg
.DoModal() == IDOK
)
3121 preselect
+= gtDlg
.GetSelectedItem();
3122 SetValue(preselect
);
3126 //////////////////////////////////////////////////////////////////////////
3127 void CPropertyItem::OnExpandButton()
3129 m_propertyCtrl
->Expand(this, !IsExpanded(), true);
3132 //////////////////////////////////////////////////////////////////////////
3133 int CPropertyItem::GetHeight()
3135 if (m_propertyCtrl
->IsExtenedUI())
3140 case ePropertyFloatCurve
:
3144 case ePropertyColorCurve
:
3153 //////////////////////////////////////////////////////////////////////////
3154 void CPropertyItem::AddChildrenForPFProperties()
3156 assert(m_type
== ePropertyAiPFPropertiesList
);
3158 for (Childs::iterator it
= m_childs
.begin(); it
!= m_childs
.end(); ++it
)
3159 m_propertyCtrl
->DestroyControls(*it
);
3161 RemoveAllChildren();
3162 m_propertyCtrl
->InvalidateCtrl();
3164 std::set
<CString
> setSelectedPathTypeNames
;
3168 while (!(token
= m_value
.Tokenize(" ,", index
)).IsEmpty())
3169 setSelectedPathTypeNames
.insert(token
);
3172 char propertyN
[100];
3173 for (std::set
<CString
>::iterator it
= setSelectedPathTypeNames
.begin(); it
!= setSelectedPathTypeNames
.end(); ++it
)
3175 IVariable
* pVar
= new CVariable
<CString
>;
3176 cry_sprintf(propertyN
, "AgentType %d", N
++);
3177 pVar
->SetName(propertyN
);
3180 CPropertyItemPtr pItem
= new CPropertyItem(m_propertyCtrl
);
3181 pItem
->SetVariable(pVar
);
3186 //////////////////////////////////////////////////////////////////////////
3187 void CPropertyItem::AddChildrenForAIEntityClasses()
3189 assert(m_type
== ePropertyAiEntityClasses
);
3191 for (Childs::iterator it
= m_childs
.begin(); it
!= m_childs
.end(); ++it
)
3193 m_propertyCtrl
->DestroyControls(*it
);
3196 RemoveAllChildren();
3197 m_propertyCtrl
->InvalidateCtrl();
3199 std::set
<CString
> setSelectedAIEntityClasses
;
3203 while (!(token
= m_value
.Tokenize(" ,", index
)).IsEmpty())
3204 setSelectedAIEntityClasses
.insert(token
);
3207 char propertyN
[100];
3208 for (std::set
<CString
>::iterator it
= setSelectedAIEntityClasses
.begin(); it
!= setSelectedAIEntityClasses
.end(); ++it
)
3210 IVariable
* pVar
= new CVariable
<CString
>;
3211 cry_sprintf(propertyN
, "Entity Class %d", N
++);
3212 pVar
->SetName(propertyN
);
3215 CPropertyItemPtr pItem
= new CPropertyItem(m_propertyCtrl
);
3216 pItem
->SetVariable(pVar
);
3221 static inline bool AlphabeticalBaseObjectLess(const CBaseObject
* p1
, const CBaseObject
* p2
)
3223 return p1
->GetName() < p2
->GetName();
3226 //////////////////////////////////////////////////////////////////////////
3228 void CPropertyItem::PopulateAITerritoriesList()
3230 CVariableEnum<string>* pVariable = static_cast<CVariableEnum<string>*>(&*m_pVariable);
3232 pVariable->SetEnumList(0);
3233 #ifndef USE_SIMPLIFIED_AI_TERRITORY_SHAPE
3234 pVariable->AddEnumItem("<Auto>", "<Auto>");
3236 pVariable->AddEnumItem("<None>", "<None>");
3238 std::vector<CBaseObject*> vTerritories;
3239 GetIEditor()->GetObjectManager()->FindObjectsOfType(RUNTIME_CLASS(CAITerritoryObject), vTerritories);
3240 std::sort(vTerritories.begin(), vTerritories.end(), AlphabeticalBaseObjectLess);
3242 for (std::vector<CBaseObject*>::iterator it = vTerritories.begin(); it != vTerritories.end(); ++it)
3244 const string& name = (*it)->GetName();
3245 pVariable->AddEnumItem(name, name);
3248 m_enumList = pVariable->GetEnumList();
3251 //////////////////////////////////////////////////////////////////////////
3253 void CPropertyItem::PopulateAIWavesList()
3255 CVariableEnum<string>* pVariable = static_cast<CVariableEnum<string>*>(&*m_pVariable);
3257 pVariable->SetEnumList(0);
3258 pVariable->AddEnumItem("<None>", "<None>");
3260 CPropertyItem* pPropertyItem = GetParent()->FindItemByFullName("::AITerritoryAndWave::Territory");
3263 CString sTerritoryName = pPropertyItem->GetValue();
3264 #ifdef USE_SIMPLIFIED_AI_TERRITORY_SHAPE
3265 if (sTerritoryName != "<None>")
3267 if ((sTerritoryName != "<Auto>") && (sTerritoryName != "<None>"))
3270 std::vector<CAIWaveObject*> vLinkedAIWaves;
3272 CBaseObject* pBaseObject = GetIEditor()->GetObjectManager()->FindObject(sTerritoryName);
3273 if (pBaseObject && pBaseObject->IsKindOf(RUNTIME_CLASS(CAITerritoryObject)))
3275 CAITerritoryObject* pTerritory = static_cast<CAITerritoryObject*>(pBaseObject);
3276 pTerritory->GetLinkedWaves(vLinkedAIWaves);
3279 std::sort(vLinkedAIWaves.begin(), vLinkedAIWaves.end(), AlphabeticalBaseObjectLess);
3281 for (std::vector<CAIWaveObject*>::iterator it = vLinkedAIWaves.begin(); it != vLinkedAIWaves.end(); ++it)
3283 const string& name = (*it)->GetName();
3284 pVariable->AddEnumItem(name, name);
3289 m_enumList = pVariable->GetEnumList();
3292 //////////////////////////////////////////////////////////////////////////
3293 void CPropertyItem::RepositionWindow(CWnd
* pWnd
, CRect rc
)
3297 pWnd
->MoveWindow(rc
, FALSE
);
3301 s_HDWP
= DeferWindowPos(s_HDWP
, pWnd
->GetSafeHwnd(), 0, rc
.left
, rc
.top
, rc
.Width(), rc
.Height(), SWP_NOACTIVATE
| SWP_NOZORDER
);
3305 //////////////////////////////////////////////////////////////////////////
3306 void CPropertyItem::RegisterCtrl(CWnd
* pCtrl
)
3310 m_controls
.push_back(pCtrl
);
3314 //////////////////////////////////////////////////////////////////////////
3315 void CPropertyItem::EnableControls(bool bEnable
)
3317 for (int i
= 0, num
= m_controls
.size(); i
< num
; i
++)
3319 CWnd
* pWnd
= m_controls
[i
];
3320 if (pWnd
&& pWnd
->GetSafeHwnd())
3322 pWnd
->EnableWindow((bEnable
) ? TRUE
: FALSE
);
3327 //////////////////////////////////////////////////////////////////////////
3328 void CPropertyItem::EnableNotifyWithoutValueChange(bool bFlag
)
3330 for (int i
= 0; i
< GetChildCount(); ++i
)
3332 CPropertyItem
* item
= GetChild(i
);
3333 item
->EnableNotifyWithoutValueChange(bFlag
);
3335 m_bForceModified
= bFlag
;
3337 m_pVariable
->EnableNotifyWithoutValueChange(m_bForceModified
);
3339 m_cEdit
->EnableUpdateOnKillFocus(!m_bForceModified
);