Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 51 additions & 6 deletions dev/core_generator/lib/src/definition.dart
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ class Definition {
property.type.snakeRuntimeCoreName +
'.hpp');
}
if (properties.any((p) => p.isAtomic)) {
includes.add('<atomic>');
}

var sortedIncludes = includes.toList()..sort();
for (final include in sortedIncludes) {
Expand Down Expand Up @@ -229,12 +232,24 @@ class Definition {
var initialize = property.initialValueRuntime ??
property.initialValue ??
property.type.defaultValue;
String fieldLine =
'${property.type.cppName} m_${property.capitalizedName}';
if (initialize != null) {
var converted = property.type.convertCpp(initialize);
if (converted != null) {
fieldLine += ' = $converted';
String fieldLine;
if (property.isAtomic) {
fieldLine =
'std::atomic<${property.type.cppName}> m_${property.capitalizedName}';
if (initialize != null) {
var converted = property.type.convertCpp(initialize);
if (converted != null) {
fieldLine += '{$converted}';
}
}
} else {
fieldLine =
'${property.type.cppName} m_${property.capitalizedName}';
if (initialize != null) {
var converted = property.type.convertCpp(initialize);
if (converted != null) {
fieldLine += ' = $converted';
}
}
}
code.writeln('$fieldLine;');
Expand Down Expand Up @@ -287,6 +302,27 @@ class Definition {
'set${property.capitalizedName}(value);'
'${property.name}Changed();'
'}');
} else if (property.isAtomic) {
code.writeln('inline'
' ${property.type.cppGetterName} ${property.name}() const ' +
(property.isGetOverride ? 'override' : '') +
'{ return m_${property.capitalizedName}'
'.load(std::memory_order_relaxed); }');
code.writeln(
'void ${property.name}(${property.type.cppName} value) ' +
(property.isSetOverride ? 'override' : '') +
'{'
'if(m_${property.capitalizedName}'
'.load(std::memory_order_relaxed) == value)'
'{return;}'
'm_${property.capitalizedName}'
'.store(value, std::memory_order_relaxed);'
'${property.name}Changed();'
'}');
code.writeln(
'std::atomic<${property.type.cppName}>* '
'atomic${property.capitalizedName}() '
'{ return &m_${property.capitalizedName}; }');
} else {
code.writeln(((property.isVirtual || property.isPureVirtual)
? 'virtual'
Expand Down Expand Up @@ -329,6 +365,11 @@ class Definition {
}
if (property.isEncoded) {
code.writeln('copy${property.capitalizedName}(object);');
} else if (property.isAtomic) {
code.writeln('m_${property.capitalizedName}.store('
'object.m_${property.capitalizedName}'
'.load(std::memory_order_relaxed), '
'std::memory_order_relaxed);');
} else {
code.writeln('m_${property.capitalizedName} = '
'object.m_${property.capitalizedName};');
Expand Down Expand Up @@ -357,6 +398,10 @@ class Definition {
if (property.isEncoded) {
code.writeln('decode${property.capitalizedName}'
'(${property.type.runtimeCoreType}::deserialize(reader));');
} else if (property.isAtomic) {
code.writeln('m_${property.capitalizedName}.store('
'${property.type.runtimeCoreType}::deserialize(reader), '
'std::memory_order_relaxed);');
} else {
code.writeln('m_${property.capitalizedName} = '
'${property.type.runtimeCoreType}::deserialize(reader);');
Expand Down
5 changes: 5 additions & 0 deletions dev/core_generator/lib/src/property.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Property {
bool isBindable = false;
bool isPassthrough = false;
bool isPureVirtual = false;
bool isAtomic = false;
FieldType? typeRuntime;

static Property? make(
Expand Down Expand Up @@ -113,6 +114,10 @@ class Property {
if (pv is bool) {
isPureVirtual = pv;
}
dynamic at = data['atomic'];
if (at is bool) {
isAtomic = at;
}
key = Key.fromJSON(data['key']) ?? Key.forProperty(this);
}

Expand Down
3 changes: 2 additions & 1 deletion dev/defs/viewmodel/viewmodel_instance_number.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"int": 575,
"string": "propertyvalue"
},
"description": "The number value."
"description": "The number value.",
"atomic": true
},
"playbackValue": {
"type": "double",
Expand Down
49 changes: 48 additions & 1 deletion include/rive/command_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
#include "rive/math/vec2d.hpp"
#include "rive/viewmodel/runtime/viewmodel_runtime.hpp"

#include <atomic>
#include <condition_variable>
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
Expand Down Expand Up @@ -59,6 +61,21 @@ struct ViewModelEnum
std::vector<std::string> enumerants;
};

struct NumberReader
{
std::atomic<std::atomic<float>*> ptr{nullptr};

float value() const
{
auto p = ptr.load(std::memory_order_acquire);
return p ? p->load(std::memory_order_relaxed) : 0.0f;
}
bool isReady() const
{
return ptr.load(std::memory_order_acquire) != nullptr;
}
};

// Client-side recorder for commands that will be executed by a
// CommandServer.
class CommandQueue : public RefCnt<CommandQueue>
Expand Down Expand Up @@ -269,6 +286,12 @@ class CommandQueue : public RefCnt<CommandQueue>
std::string path,
size_t size)
{}

virtual void onViewModelInstanceNameReceived(
const ViewModelInstanceHandle,
uint64_t requestId,
std::string name)
{}
};

class StateMachineListener
Expand Down Expand Up @@ -631,11 +654,23 @@ class CommandQueue : public RefCnt<CommandQueue>
std::string path,
uint64_t requestId = 0);

void requestViewModelInstanceName(ViewModelInstanceHandle,
uint64_t requestId = 0);

void requestStateMachineNames(ArtboardHandle, uint64_t requestId = 0);
void requestDefaultViewModelInfo(ArtboardHandle,
FileHandle,
uint64_t requestId = 0);

std::shared_ptr<NumberReader> createNumberReader(
ViewModelInstanceHandle,
std::string path,
uint64_t requestId = 0);

void releaseNumberReader(ViewModelInstanceHandle,
std::string path,
uint64_t requestId = 0);

// Consume all messages received from the server.
void processMessages();

Expand Down Expand Up @@ -668,6 +703,11 @@ class CommandQueue : public RefCnt<CommandQueue>
m_globalFontListener = listener;
}

void setMessageAvailableCallback(std::function<void()> callback)
{
m_messageAvailableCallback = std::move(callback);
}

private:
void registerListener(FileHandle handle, FileListener* listener)
{
Expand Down Expand Up @@ -826,7 +866,10 @@ class CommandQueue : public RefCnt<CommandQueue>
listViewModelInstanceNames,
listViewModelProperties,
listViewModelPropertyValue,
getViewModelListSize
getViewModelListSize,
getViewModelInstanceName,
createNumberReader,
releaseNumberReader
};

enum class Message
Expand All @@ -842,6 +885,7 @@ class CommandQueue : public RefCnt<CommandQueue>
viewModelPropertiesListed,
viewModelPropertyValueReceived,
viewModelListSizeReceived,
viewModelInstanceNameReceived,
fileLoaded,
fileDeleted,
imageDecoded,
Expand Down Expand Up @@ -886,6 +930,7 @@ class CommandQueue : public RefCnt<CommandQueue>
ObjectStream<std::string> m_names;
ObjectStream<CommandServerCallback> m_callbacks;
ObjectStream<CommandServerDrawCallback> m_drawCallbacks;
ObjectStream<std::shared_ptr<NumberReader>> m_numberReaderPtrs;

// Messages streams
std::mutex m_messageMutex;
Expand All @@ -912,6 +957,8 @@ class CommandQueue : public RefCnt<CommandQueue>
m_viewModelListeners;
std::unordered_map<StateMachineHandle, StateMachineListener*>
m_stateMachineListeners;

std::function<void()> m_messageAvailableCallback;
};

}; // namespace rive
11 changes: 11 additions & 0 deletions include/rive/command_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "rive/command_queue.hpp"
#include <iostream>
#include <memory>
#include <sstream>
#include <thread>
#include <unordered_map>
Expand Down Expand Up @@ -126,6 +127,7 @@ class CommandServer
};

void checkPropertySubscriptions();
void notifyMessageAvailable();

Vec2D cursorPosForPointerEvent(StateMachineInstance*,
const CommandQueue::PointerEvent&);
Expand Down Expand Up @@ -174,6 +176,15 @@ class CommandServer
// because we iterate through the entire vector every frame anyway.
std::vector<Subscription> m_propertySubscriptions;

struct NumberReaderEntry
{
std::shared_ptr<NumberReader> reader;
ViewModelInstanceHandle viewModelHandle;
std::string propertyPath;
rcp<ViewModelInstanceValue> valueRef;
};
std::vector<NumberReaderEntry> m_numberReaders;

// Dependencies
// When a file gets deleted artboards and statemachine become invalid. Here
// we hold a reference to the artboard only because that artboard has a
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#ifndef _RIVE_VIEW_MODEL_INSTANCE_NUMBER_BASE_HPP_
#define _RIVE_VIEW_MODEL_INSTANCE_NUMBER_BASE_HPP_
#include <atomic>
#include "rive/core/field_types/core_double_type.hpp"
#include "rive/viewmodel/viewmodel_instance_value.hpp"
namespace rive
Expand Down Expand Up @@ -31,24 +32,30 @@ class ViewModelInstanceNumberBase : public ViewModelInstanceValue
static const uint16_t propertyValuePropertyKey = 575;

protected:
float m_PropertyValue = 0.0f;
std::atomic<float> m_PropertyValue{0.0f};

public:
inline float propertyValue() const { return m_PropertyValue; }
inline float propertyValue() const
{
return m_PropertyValue.load(std::memory_order_relaxed);
}
void propertyValue(float value)
{
if (m_PropertyValue == value)
if (m_PropertyValue.load(std::memory_order_relaxed) == value)
{
return;
}
m_PropertyValue = value;
m_PropertyValue.store(value, std::memory_order_relaxed);
propertyValueChanged();
}
std::atomic<float>* atomicPropertyValue() { return &m_PropertyValue; }

Core* clone() const override;
void copy(const ViewModelInstanceNumberBase& object)
{
m_PropertyValue = object.m_PropertyValue;
m_PropertyValue.store(
object.m_PropertyValue.load(std::memory_order_relaxed),
std::memory_order_relaxed);
ViewModelInstanceValue::copy(object);
}

Expand All @@ -57,7 +64,8 @@ class ViewModelInstanceNumberBase : public ViewModelInstanceValue
switch (propertyKey)
{
case propertyValuePropertyKey:
m_PropertyValue = CoreDoubleType::deserialize(reader);
m_PropertyValue.store(CoreDoubleType::deserialize(reader),
std::memory_order_relaxed);
return true;
}
return ViewModelInstanceValue::deserialize(propertyKey, reader);
Expand All @@ -68,4 +76,4 @@ class ViewModelInstanceNumberBase : public ViewModelInstanceValue
};
} // namespace rive

#endif
#endif
Loading