forked from Mirrors/openclonk
Qt Editor: Add property delegate type "object"
parent
9e4f036fe2
commit
2f22a3a8fe
|
@ -32,6 +32,7 @@ IDS_BTN_YES=Ja
|
|||
IDS_CHAT_NOTCONNECTED=nicht verbunden
|
||||
IDS_CHAT_SERVER=Server
|
||||
IDS_CNS_ACTION=Aktivität:
|
||||
IDS_CNS_ALLOBJECTS=Alle Objekte
|
||||
IDS_CNS_ARRAYADD=Element hinzufügen
|
||||
IDS_CNS_ARRAYREMOVE=Element entfernen
|
||||
IDS_CNS_ARRAYSHORT=[%1 Elemente]
|
||||
|
@ -62,6 +63,7 @@ IDS_CNS_MAPSIZE=Breite
|
|||
IDS_CNS_MAPZOOM=Zoom
|
||||
IDS_CNS_MORE=...
|
||||
IDS_CNS_MULTIPLEOBJECTS=%i Objekte ausgewählt.
|
||||
IDS_CNS_NEARBYOBJECTS=Nahe Objekte
|
||||
IDS_CNS_NEWPLRVIEWPORT=Neu für %s
|
||||
IDS_CNS_NEWSCENARIO=Neues Szenario
|
||||
IDS_CNS_NOCHILDSAVE=%s befindet sich in einem Rundenordner. Szenarien können nicht in geschlossenen Gruppendateien gespeichert werden.
|
||||
|
|
|
@ -32,6 +32,7 @@ IDS_BTN_YES=Yes
|
|||
IDS_CHAT_NOTCONNECTED=not connected
|
||||
IDS_CHAT_SERVER=Server
|
||||
IDS_CNS_ACTION=Action:
|
||||
IDS_CNS_ALLOBJECTS=All objects
|
||||
IDS_CNS_ARRAYADD=Add item
|
||||
IDS_CNS_ARRAYREMOVE=Remove item
|
||||
IDS_CNS_ARRAYSHORT=[%1 items]
|
||||
|
@ -62,6 +63,7 @@ IDS_CNS_MAPSIZE=Map size
|
|||
IDS_CNS_MAPZOOM=Zoom
|
||||
IDS_CNS_MORE=...
|
||||
IDS_CNS_MULTIPLEOBJECTS=%i selected objects.
|
||||
IDS_CNS_NEARBYOBJECTS=Nearby objects
|
||||
IDS_CNS_NEWPLRVIEWPORT=New for %s
|
||||
IDS_CNS_NEWSCENARIO=New Scenario
|
||||
IDS_CNS_NOCHILDSAVE=%s is located in a group folder. Scenarios cannot be saved in closed group folders.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "editor/C4ConsoleQtState.h"
|
||||
#include "editor/C4Console.h"
|
||||
#include "object/C4Object.h"
|
||||
#include "object/C4GameObjects.h"
|
||||
#include "object/C4DefList.h"
|
||||
#include "object/C4Def.h"
|
||||
#include "script/C4Effect.h"
|
||||
|
@ -634,6 +635,11 @@ QStandardItemModel *C4PropertyDelegateEnum::CreateOptionModel() const
|
|||
return model.release();
|
||||
}
|
||||
|
||||
void C4PropertyDelegateEnum::ClearOptions()
|
||||
{
|
||||
options.clear();
|
||||
}
|
||||
|
||||
void C4PropertyDelegateEnum::ReserveOptions(int32_t num)
|
||||
{
|
||||
options.reserve(num);
|
||||
|
@ -951,6 +957,85 @@ void C4PropertyDelegateDef::AddDefinitions(C4ConsoleQtDefinitionListModel *def_l
|
|||
}
|
||||
}
|
||||
|
||||
C4PropertyDelegateObject::C4PropertyDelegateObject(const C4PropertyDelegateFactory *factory, C4PropList *props)
|
||||
: C4PropertyDelegateEnum(factory, props), max_nearby_objects(20)
|
||||
{
|
||||
// Settings
|
||||
if (props)
|
||||
{
|
||||
filter = props->GetPropertyStr(P_Filter);
|
||||
}
|
||||
// Actual object list is created/updated when the editor is created
|
||||
}
|
||||
|
||||
C4RefCntPointer<C4String> C4PropertyDelegateObject::GetObjectEntryString(C4Object *obj) const
|
||||
{
|
||||
// Compose object display string from containment(*), name, position (@x,y) and object number (#n)
|
||||
return ::Strings.RegString(FormatString("%s%s @%d,%d (#%d)", obj->Contained ? "*" : "", obj->GetName(), (int)obj->GetX(), (int)obj->GetY(), (int)obj->Number));
|
||||
}
|
||||
|
||||
void C4PropertyDelegateObject::UpdateObjectList()
|
||||
{
|
||||
// Re-create object list from current position
|
||||
ClearOptions();
|
||||
// Get matching objects first
|
||||
std::vector<C4Object *> objects;
|
||||
for (C4Object *obj : ::Objects) if (obj->Status)
|
||||
{
|
||||
C4Value filter_val;
|
||||
if (filter)
|
||||
{
|
||||
if (!obj->GetPropertyByS(filter, &filter_val)) continue;
|
||||
if (!filter_val) continue;
|
||||
}
|
||||
objects.push_back(obj);
|
||||
}
|
||||
// Get list sorted by distance from selected object
|
||||
std::vector<C4Object *> objects_by_distance;
|
||||
int32_t cx=0, cy=0;
|
||||
if (::Console.EditCursor.GetCurrentSelectionPosition(&cx, &cy))
|
||||
{
|
||||
objects_by_distance = objects;
|
||||
auto ObjDist = [cx, cy](C4Object *o) { return (o->GetX() - cx)*(o->GetX() - cx) + (o->GetY() - cy)*(o->GetY() - cy); };
|
||||
std::stable_sort(objects_by_distance.begin(), objects_by_distance.end(), [&ObjDist](C4Object *a, C4Object *b) { return ObjDist(a) < ObjDist(b); });
|
||||
}
|
||||
size_t num_nearby = objects_by_distance.size();
|
||||
bool has_all_objects_list = (num_nearby > max_nearby_objects);
|
||||
if (has_all_objects_list) num_nearby = max_nearby_objects;
|
||||
// Add actual objects
|
||||
ReserveOptions(1 + num_nearby + !!num_nearby + (has_all_objects_list ? objects.size() : 0));
|
||||
AddConstOption(::Strings.RegString("nil"), C4VNull); // nil is always an option
|
||||
if (num_nearby)
|
||||
{
|
||||
// TODO: "Select object" entry
|
||||
//AddCallbackOption(LoadResStr("IDS_CNS_SELECTOBJECT"));
|
||||
// Nearby list
|
||||
C4RefCntPointer<C4String> nearby_group;
|
||||
// If there are main objects, Create a subgroup. Otherwise, just put all elements into the main group.
|
||||
if (has_all_objects_list) nearby_group = ::Strings.RegString(LoadResStr("IDS_CNS_NEARBYOBJECTS"));
|
||||
for (int32_t i = 0; i < num_nearby; ++i)
|
||||
{
|
||||
C4Object *obj = objects_by_distance[i];
|
||||
AddConstOption(GetObjectEntryString(obj).Get(), C4VObj(obj), nearby_group.Get());
|
||||
}
|
||||
// All objects
|
||||
if (has_all_objects_list)
|
||||
{
|
||||
C4RefCntPointer<C4String> all_group = ::Strings.RegString(LoadResStr("IDS_CNS_ALLOBJECTS"));
|
||||
for (C4Object *obj : objects) AddConstOption(GetObjectEntryString(obj).Get(), C4VObj(obj), all_group.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QWidget *C4PropertyDelegateObject::CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const
|
||||
{
|
||||
// Update object list for created editor
|
||||
// (This should be safe since the object delegate cannot contain nested delegates)
|
||||
const_cast<C4PropertyDelegateObject *>(this)->UpdateObjectList();
|
||||
return C4PropertyDelegateEnum::CreateEditor(parent_delegate, parent, option, by_selection);
|
||||
}
|
||||
|
||||
|
||||
C4PropertyDelegateBool::C4PropertyDelegateBool(const C4PropertyDelegateFactory *factory, C4PropList *props)
|
||||
: C4PropertyDelegateEnum(factory, props)
|
||||
{
|
||||
|
@ -1137,6 +1222,7 @@ C4PropertyDelegate *C4PropertyDelegateFactory::CreateDelegateByPropList(C4PropLi
|
|||
if (str->GetData() == "proplist") return new C4PropertyDelegatePropList(this, props);
|
||||
if (str->GetData() == "color") return new C4PropertyDelegateColor(this, props);
|
||||
if (str->GetData() == "def") return new C4PropertyDelegateDef(this, props);
|
||||
if (str->GetData() == "object") return new C4PropertyDelegateObject(this, props);
|
||||
if (str->GetData() == "enum") return new C4PropertyDelegateEnum(this, props);
|
||||
if (str->GetData() == "bool") return new C4PropertyDelegateBool(this, props);
|
||||
if (str->GetData() == "has_effect") return new C4PropertyDelegateHasEffect(this, props);
|
||||
|
|
|
@ -266,6 +266,7 @@ private:
|
|||
std::vector<Option> options;
|
||||
|
||||
protected:
|
||||
void ClearOptions();
|
||||
void ReserveOptions(int32_t num);
|
||||
QStandardItemModel *CreateOptionModel() const;
|
||||
public:
|
||||
|
@ -300,6 +301,21 @@ private:
|
|||
void AddDefinitions(class C4ConsoleQtDefinitionListModel *def_list_model, QModelIndex parent, C4String *group);
|
||||
};
|
||||
|
||||
// Select an object
|
||||
class C4PropertyDelegateObject : public C4PropertyDelegateEnum
|
||||
{
|
||||
private:
|
||||
C4RefCntPointer<C4String> filter;
|
||||
size_t max_nearby_objects; // maximum number of objects shown in "nearby" list
|
||||
|
||||
C4RefCntPointer<C4String> GetObjectEntryString(C4Object *obj) const;
|
||||
void UpdateObjectList();
|
||||
public:
|
||||
C4PropertyDelegateObject(const C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
|
||||
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const override;
|
||||
};
|
||||
|
||||
// true or false
|
||||
class C4PropertyDelegateBool : public C4PropertyDelegateEnum
|
||||
{
|
||||
|
|
|
@ -1294,3 +1294,12 @@ void C4EditCursor::DoContextObjCommand(C4Object * obj, const char *cmd)
|
|||
if (!obj || !cmd) return;
|
||||
In(FormatString("Object(%d)->%s", obj->Number, cmd).getData());
|
||||
}
|
||||
|
||||
bool C4EditCursor::GetCurrentSelectionPosition(int32_t *x, int32_t *y)
|
||||
{
|
||||
C4Object *obj = selection.GetObject();
|
||||
if (!obj || !obj->Status) return false;
|
||||
*x = obj->GetX();
|
||||
*y = obj->GetY();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -156,6 +156,7 @@ public:
|
|||
void InvalidateSelection() { selection_invalid = true; }
|
||||
void ValidateSelection() { selection_invalid = false; }
|
||||
bool IsSelectionInvalidated() const { return selection_invalid; }
|
||||
bool GetCurrentSelectionPosition(int32_t *x, int32_t *y); // return center of first selected object
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue