Skip to content

Commit

Permalink
Data models: Allow dirtying an arbitrary address (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikke89 committed Aug 16, 2024
1 parent ef2117b commit 0b7e006
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 16 deletions.
2 changes: 2 additions & 0 deletions Include/RmlUi/Core/DataTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ using DirtyVariables = SmallUnorderedSet<String>;
struct DataAddressEntry {
DataAddressEntry(String name) : name(std::move(name)), index(-1) {}
DataAddressEntry(int index) : index(index) {}
bool operator==(const DataAddressEntry& other) const { return name == other.name && index == other.index; }
bool operator!=(const DataAddressEntry& other) const { return !(*this == other); }
String name;
int index;
};
Expand Down
22 changes: 14 additions & 8 deletions Samples/basic/player_list/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,23 @@ class PlayerList final : public Rml::EventListener {

RMLUI_ZoneScoped;

for (PlayerEntry& player : data)
{
player.score = (uint32_t)Rml::Math::RandomInteger(100);
player.latency = (uint16_t)Rml::Math::RandomInteger(500);
}
// for (PlayerEntry& player : data)
//{
// player.score = (uint32_t)Rml::Math::RandomInteger(100);
// player.latency = (uint16_t)Rml::Math::RandomInteger(500);
// }

data[5].score = (uint32_t)Rml::Math::RandomInteger(100);

// Filter();
// Sort();
//

Filter();
Sort();
entries = data;

RMLUI_ASSERT(data_model);
data_model.DirtyVariable("players");
data_model.DirtyVariable("players[5].score");
// data_model.DirtyVariable("players");

last_update = t;
}
Expand Down
22 changes: 22 additions & 0 deletions Source/Core/DataExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,28 @@ StringList DataExpression::GetVariableNameList() const
return list;
}

bool DataExpression::HasAddressDependency(const DataAddress& match_address) const
{
for (const DataAddress& address : addresses)
{
if (match_address.size() > address.size())
continue;

bool match = true;
for (size_t i = 0; i < match_address.size(); i++)
{
if (match_address[i] != address[i])
{
match = false;
break;
}
}
if (match)
return true;
}
return false;
}

DataExpressionInterface::DataExpressionInterface(DataModel* data_model, Element* element, Event* event) :
data_model(data_model), element(element), event(event)
{}
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/DataExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class DataExpression {

// Available after Parse()
StringList GetVariableNameList() const;
// Available after Parse()
bool HasAddressDependency(const DataAddress& match_address) const;

private:
String expression;
Expand Down
6 changes: 3 additions & 3 deletions Source/Core/DataModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ void DataModel::CopyAliases(Element* from_element, Element* to_element)
{
// Need to create a copy to prevent errors during concurrent modification for 3rd party containers
auto copy = existing_map->second;
for (auto const& it : copy)
for (const auto& it : copy)
aliases[to_element][it.first] = std::move(it.second);
}
}
Expand Down Expand Up @@ -348,8 +348,8 @@ bool DataModel::GetVariableInto(const DataAddress& address, Variant& out_value)

void DataModel::DirtyVariable(const String& variable_name)
{
RMLUI_ASSERTMSG(LegalVariableName(variable_name) == nullptr, "Illegal variable name provided. Only top-level variables can be dirtied.");
RMLUI_ASSERTMSG(variables.count(variable_name) == 1, "In DirtyVariable: Variable name not found among added variables.");
// RMLUI_ASSERTMSG(LegalVariableName(variable_name) == nullptr, "Illegal variable name provided. Only top-level variables can be dirtied.");
// RMLUI_ASSERTMSG(variables.count(variable_name) == 1, "In DirtyVariable: Variable name not found among added variables.");
dirty_variables.emplace(variable_name);
}

Expand Down
20 changes: 16 additions & 4 deletions Source/Core/DataView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

#include "DataView.h"
#include "../../Include/RmlUi/Core/Element.h"
#include "../../Include/RmlUi/Core/Profiling.h"
#include "DataModel.h"
#include <algorithm>

namespace Rml {
Expand Down Expand Up @@ -120,9 +120,21 @@ bool DataViews::Update(DataModel& model, const DirtyVariables& dirty_variables)

for (const String& variable_name : dirty_variables)
{
auto pair = name_view_map.equal_range(variable_name);
for (auto it = pair.first; it != pair.second; ++it)
dirty_views.push_back(it->second);
DataAddress address = model.ResolveAddress(variable_name, nullptr);
if (address.size() > 1)
{
for (const DataViewPtr& view : views)
{
if (view->HasAddressDependency(address))
dirty_views.push_back(view.get());
}
}
else
{
auto pair = name_view_map.equal_range(variable_name);
for (auto it = pair.first; it != pair.second; ++it)
dirty_views.push_back(it->second);
}
}

// Remove duplicate entries
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/DataView.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ class DataView : public Releasable {
// Returns the list of data variable name(s) which can modify this view.
virtual StringList GetVariableNameList() const = 0;

// Returns true if the variable at the given data address can modify this view.
virtual bool HasAddressDependency(const DataAddress& address) const = 0;

// Returns the attached element if it still exists.
Element* GetElement() const;

Expand Down
40 changes: 39 additions & 1 deletion Source/Core/DataViewDefault.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ StringList DataViewCommon::GetVariableNameList() const
return expression->GetVariableNameList();
}

bool DataViewCommon::HasAddressDependency(const DataAddress& address) const
{
RMLUI_ASSERT(expression);
return expression->HasAddressDependency(address);
}

const String& DataViewCommon::GetModifier() const
{
return modifier;
Expand Down Expand Up @@ -423,6 +429,17 @@ StringList DataViewText::GetVariableNameList() const
return full_list;
}

bool DataViewText::HasAddressDependency(const DataAddress& address) const
{
for (const DataEntry& entry : data_entries)
{
RMLUI_ASSERT(entry.data_expression);
if (entry.data_expression->HasAddressDependency(address))
return true;
}
return false;
}

void DataViewText::Release()
{
delete this;
Expand Down Expand Up @@ -503,7 +520,8 @@ bool DataViewFor::Initialize(DataModel& model, Element* element, const String& i

element->SetProperty(PropertyId::Display, Property(Style::Display::None));

// Copy over the attributes, but remove the 'data-for' which would otherwise recreate the data-for loop on all constructed children recursively.
// Copy over the attributes, but remove the 'data-for' which would otherwise recreate the data-for loop on all constructed children
// recursively.
attributes = element->GetAttributes();
for (auto it = attributes.begin(); it != attributes.end(); ++it)
{
Expand Down Expand Up @@ -571,6 +589,20 @@ StringList DataViewFor::GetVariableNameList() const
return StringList{container_address.front().name};
}

bool DataViewFor::HasAddressDependency(const DataAddress& address) const
{
if (address.empty())
return false;

for (size_t i = 0; i < Math::Min(address.size(), container_address.size()); i++)
{
if (container_address[i] != address[i])
return false;
}

return true;
}

void DataViewFor::Release()
{
delete this;
Expand Down Expand Up @@ -599,6 +631,12 @@ bool DataViewAlias::Initialize(DataModel& model, Element* element, const String&
return true;
}

bool DataViewAlias::HasAddressDependency(const DataAddress& /*address*/) const
{
// TODO
return true;
}

void DataViewAlias::Release()
{
delete this;
Expand Down
8 changes: 8 additions & 0 deletions Source/Core/DataViewDefault.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class DataViewCommon : public DataView {

StringList GetVariableNameList() const override;

bool HasAddressDependency(const DataAddress& address) const override;

protected:
const String& GetModifier() const;
DataExpression& GetExpression();
Expand Down Expand Up @@ -134,6 +136,8 @@ class DataViewText final : public DataView {
bool Update(DataModel& model) override;
StringList GetVariableNameList() const override;

bool HasAddressDependency(const DataAddress& address) const override;

protected:
void Release() override;

Expand All @@ -160,6 +164,8 @@ class DataViewFor final : public DataView {

StringList GetVariableNameList() const override;

bool HasAddressDependency(const DataAddress& address) const override;

protected:
void Release() override;

Expand All @@ -180,6 +186,8 @@ class DataViewAlias final : public DataView {
bool Update(DataModel& model) override;
bool Initialize(DataModel& model, Element* element, const String& expression, const String& modifier) override;

bool HasAddressDependency(const DataAddress& address) const override;

protected:
void Release() override;

Expand Down

0 comments on commit 0b7e006

Please sign in to comment.