mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
feat(CommandQueue)File asset loader (#9799) 77172ea62b
* added file asset loader * tests for asset loader * made asset loader rcp * addressed pr comments feat(CommandQueue) Added request Ids associated with jobs (#9796) 5aedcdc61f * added request ids that are associated with callbacks for the command queue * modified tests to check for request id feat: TextInput - refactor shapes for runtime text input (#9836) 455374455c * chore: updating runtime defs * chore: refactor TextStyle into TextStylePaint * chore: missed hpp files * chore: missed cpp files * chore: fix clone of text_style_paint * feat: more text input at runtime * chore: cleanup * chore: add typed child iterator * chore: missed files * chore: running runtime input in editor * feat: completing integration with editor * chore: missed file * chore: fix builds with text disabled * chore: use child for test * tests: adding more tests for text input * chore: missed test file * chore: more coverage for child iterator * chore: using clipping on text input * chore: test text input selected text * chore: dry up iterator Co-authored-by: Jonathon Copeland <jcopela4@gmail.com> Co-authored-by: Luigi Rosso <luigi-rosso@users.noreply.github.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
c62bdb256e8befe78d86e41b001545a9948d36c9
|
||||
77172ea62bd8aa498352078e8e6c91ea92f875bd
|
||||
|
||||
41
dev/defs/text/text_input.json
Normal file
41
dev/defs/text/text_input.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "TextInput",
|
||||
"key": {
|
||||
"int": 569,
|
||||
"string": "textinput"
|
||||
},
|
||||
"extends": "drawable.json",
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "String",
|
||||
"initialValue": "''",
|
||||
"key": {
|
||||
"int": 817,
|
||||
"string": "text"
|
||||
},
|
||||
"bindable": true
|
||||
},
|
||||
"selectionRadius": {
|
||||
"type": "double",
|
||||
"initialValue": "5.0",
|
||||
"animates": true,
|
||||
"key": {
|
||||
"int": 818,
|
||||
"string": "selectionradius"
|
||||
},
|
||||
"description": "Selection radius applied to the selection geometry",
|
||||
"bindable": true
|
||||
},
|
||||
"fieldHeight": {
|
||||
"type": "double",
|
||||
"initialValue": "98.0",
|
||||
"key": {
|
||||
"int": 819,
|
||||
"string": "fieldheight"
|
||||
},
|
||||
"description": "An edit time property used to track the height of the field in the inspector",
|
||||
"runtime": false,
|
||||
"coop": false
|
||||
}
|
||||
}
|
||||
}
|
||||
8
dev/defs/text/text_input_cursor.json
Normal file
8
dev/defs/text/text_input_cursor.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "TextInputCursor",
|
||||
"key": {
|
||||
"int": 571,
|
||||
"string": "textinputcursor"
|
||||
},
|
||||
"extends": "text/text_input_drawable.json"
|
||||
}
|
||||
9
dev/defs/text/text_input_drawable.json
Normal file
9
dev/defs/text/text_input_drawable.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "TextInputDrawable",
|
||||
"key": {
|
||||
"int": 570,
|
||||
"string": "textinputdrawable"
|
||||
},
|
||||
"abstract": true,
|
||||
"extends": "drawable.json"
|
||||
}
|
||||
8
dev/defs/text/text_input_selected_text.json
Normal file
8
dev/defs/text/text_input_selected_text.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "TextInputSelectedText",
|
||||
"key": {
|
||||
"int": 575,
|
||||
"string": "textinputselectedtext"
|
||||
},
|
||||
"extends": "text/text_input_drawable.json"
|
||||
}
|
||||
8
dev/defs/text/text_input_selection.json
Normal file
8
dev/defs/text/text_input_selection.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "TextInputSelection",
|
||||
"key": {
|
||||
"int": 574,
|
||||
"string": "textinputselection"
|
||||
},
|
||||
"extends": "text/text_input_drawable.json"
|
||||
}
|
||||
8
dev/defs/text/text_input_text.json
Normal file
8
dev/defs/text/text_input_text.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "TextInputText",
|
||||
"key": {
|
||||
"int": 572,
|
||||
"string": "textinputtext"
|
||||
},
|
||||
"extends": "text/text_input_drawable.json"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "TextStyle",
|
||||
"key": {
|
||||
"int": 137,
|
||||
"int": 573,
|
||||
"string": "textstyle"
|
||||
},
|
||||
"extends": "container_component.json",
|
||||
|
||||
8
dev/defs/text/text_style_paint.json
Normal file
8
dev/defs/text/text_style_paint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "TextStylePaint",
|
||||
"key": {
|
||||
"int": 137,
|
||||
"string": "textstylepaint"
|
||||
},
|
||||
"extends": "text/text_style.json"
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "rive/event.hpp"
|
||||
#include "rive/audio/audio_engine.hpp"
|
||||
#include "rive/math/raw_path.hpp"
|
||||
#include "rive/typed_children.hpp"
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
@@ -191,6 +192,12 @@ public:
|
||||
#endif
|
||||
|
||||
const std::vector<Core*>& objects() const { return m_Objects; }
|
||||
template <typename T> TypedChildren<T> objects()
|
||||
{
|
||||
return TypedChildren<T>(
|
||||
Span<Core*>(m_Objects.data(), m_Objects.size()));
|
||||
}
|
||||
|
||||
const std::vector<NestedArtboard*> nestedArtboards() const
|
||||
{
|
||||
return m_NestedArtboards;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "file_asset_loader.hpp"
|
||||
|
||||
// Macros for defining and working with command buffer handles.
|
||||
#if INTPTR_MAX == INT64_MAX
|
||||
@@ -42,6 +43,8 @@ RIVE_DEFINE_HANDLE(ArtboardHandle);
|
||||
RIVE_DEFINE_HANDLE(StateMachineHandle);
|
||||
RIVE_DEFINE_HANDLE(DrawKey);
|
||||
|
||||
using RequestId = uint64_t;
|
||||
|
||||
// Function poimter that gets called back from the server thread.
|
||||
using CommandServerCallback = std::function<void(CommandServer*)>;
|
||||
using CommandServerDrawCallback = std::function<void(DrawKey, CommandServer*)>;
|
||||
@@ -90,9 +93,10 @@ public:
|
||||
: public CommandQueue::ListenerBase<FileListener, FileHandle>
|
||||
{
|
||||
public:
|
||||
virtual void onFileDeleted(const FileHandle) {}
|
||||
virtual void onFileDeleted(const FileHandle, RequestId) {}
|
||||
|
||||
virtual void onArtboardsListed(const FileHandle,
|
||||
RequestId,
|
||||
std::vector<std::string> artboardNames)
|
||||
{}
|
||||
};
|
||||
@@ -101,10 +105,11 @@ public:
|
||||
: public CommandQueue::ListenerBase<ArtboardListener, ArtboardHandle>
|
||||
{
|
||||
public:
|
||||
virtual void onArtboardDeleted(const ArtboardHandle) {}
|
||||
virtual void onArtboardDeleted(const ArtboardHandle, RequestId) {}
|
||||
|
||||
virtual void onStateMachinesListed(
|
||||
const ArtboardHandle,
|
||||
RequestId,
|
||||
std::vector<std::string> artboardNames)
|
||||
{}
|
||||
};
|
||||
@@ -114,42 +119,59 @@ public:
|
||||
StateMachineHandle>
|
||||
{
|
||||
public:
|
||||
virtual void onStateMachineDeleted(const StateMachineHandle) {}
|
||||
virtual void onStateMachineDeleted(const StateMachineHandle, RequestId)
|
||||
{}
|
||||
};
|
||||
|
||||
CommandQueue();
|
||||
~CommandQueue();
|
||||
|
||||
FileHandle loadFile(std::vector<uint8_t> rivBytes,
|
||||
FileListener* listener = nullptr);
|
||||
rcp<FileAssetLoader>,
|
||||
FileListener* listener = nullptr,
|
||||
RequestId* outId = nullptr);
|
||||
|
||||
void deleteFile(FileHandle);
|
||||
FileHandle loadFile(std::vector<uint8_t> rivBytes,
|
||||
FileListener* listener = nullptr,
|
||||
RequestId* outId = nullptr)
|
||||
{
|
||||
return loadFile(std::move(rivBytes), nullptr, listener, outId);
|
||||
}
|
||||
|
||||
RequestId deleteFile(FileHandle);
|
||||
|
||||
ArtboardHandle instantiateArtboardNamed(
|
||||
FileHandle,
|
||||
std::string name,
|
||||
ArtboardListener* listener = nullptr);
|
||||
ArtboardListener* listener = nullptr,
|
||||
RequestId* outId = nullptr);
|
||||
ArtboardHandle instantiateDefaultArtboard(
|
||||
FileHandle fileHandle,
|
||||
ArtboardListener* listener = nullptr)
|
||||
ArtboardListener* listener = nullptr,
|
||||
RequestId* outId = nullptr)
|
||||
{
|
||||
return instantiateArtboardNamed(fileHandle, "", listener);
|
||||
return instantiateArtboardNamed(fileHandle, "", listener, outId);
|
||||
}
|
||||
|
||||
void deleteArtboard(ArtboardHandle);
|
||||
RequestId deleteArtboard(ArtboardHandle);
|
||||
|
||||
StateMachineHandle instantiateStateMachineNamed(
|
||||
ArtboardHandle,
|
||||
std::string name,
|
||||
StateMachineListener* listener = nullptr);
|
||||
StateMachineListener* listener = nullptr,
|
||||
RequestId* outId = nullptr);
|
||||
StateMachineHandle instantiateDefaultStateMachine(
|
||||
ArtboardHandle artboardHandle,
|
||||
StateMachineListener* listener = nullptr)
|
||||
StateMachineListener* listener = nullptr,
|
||||
RequestId* outId = nullptr)
|
||||
{
|
||||
return instantiateStateMachineNamed(artboardHandle, "", listener);
|
||||
return instantiateStateMachineNamed(artboardHandle,
|
||||
"",
|
||||
listener,
|
||||
outId);
|
||||
}
|
||||
|
||||
void deleteStateMachine(StateMachineHandle);
|
||||
RequestId deleteStateMachine(StateMachineHandle);
|
||||
|
||||
// Create unique draw key for draw.
|
||||
DrawKey createDrawKey();
|
||||
@@ -177,8 +199,8 @@ public:
|
||||
|
||||
void disconnect();
|
||||
|
||||
void requestArtboardNames(FileHandle);
|
||||
void requestStateMachineNames(ArtboardHandle);
|
||||
RequestId requestArtboardNames(FileHandle);
|
||||
RequestId requestStateMachineNames(ArtboardHandle);
|
||||
|
||||
// Consume all messages received from the server.
|
||||
void processMessages();
|
||||
@@ -263,6 +285,7 @@ private:
|
||||
uint64_t m_currentFileHandleIdx = 0;
|
||||
uint64_t m_currentArtboardHandleIdx = 0;
|
||||
uint64_t m_currentStateMachineHandleIdx = 0;
|
||||
uint64_t m_currentRequestIdIdx = 0;
|
||||
uint64_t m_currentDrawKeyIdx = 0;
|
||||
|
||||
std::mutex m_commandMutex;
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
#ifndef _RIVE_CONTAINER_COMPONENT_HPP_
|
||||
#define _RIVE_CONTAINER_COMPONENT_HPP_
|
||||
#include "rive/generated/container_component_base.hpp"
|
||||
#include "rive/typed_children.hpp"
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace rive
|
||||
{
|
||||
|
||||
class ContainerComponent : public ContainerComponentBase
|
||||
{
|
||||
public:
|
||||
template <typename T> TypedChildren<T> children()
|
||||
{
|
||||
return TypedChildren<T>(
|
||||
Span<Core*>((Core**)m_children.data(), m_children.size()));
|
||||
}
|
||||
|
||||
const std::vector<Component*>& children() const { return m_children; }
|
||||
virtual void addChild(Component* component);
|
||||
bool collapse(bool value) override;
|
||||
@@ -17,7 +25,8 @@ public:
|
||||
bool forAll(std::function<bool(Component*)> predicate);
|
||||
|
||||
// Recursively descend onto all the children in the hierarchy tree.
|
||||
// If predicate returns false, it won't recurse down a particular branch.
|
||||
// If predicate returns false, it won't recurse down a particular
|
||||
// branch.
|
||||
void forEachChild(std::function<bool(Component*)> predicate);
|
||||
|
||||
private:
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
/// Minor version number supported by the runtime.
|
||||
static const int minorVersion = 0;
|
||||
|
||||
File(Factory*, FileAssetLoader*);
|
||||
File(Factory*, rcp<FileAssetLoader>);
|
||||
|
||||
public:
|
||||
~File();
|
||||
@@ -64,9 +64,17 @@ public:
|
||||
/// cannot be found in-band.
|
||||
/// @returns a pointer to the file, or null on failure.
|
||||
static std::unique_ptr<File> import(Span<const uint8_t> data,
|
||||
Factory*,
|
||||
Factory* factory,
|
||||
ImportResult* result = nullptr,
|
||||
FileAssetLoader* assetLoader = nullptr);
|
||||
FileAssetLoader* assetLoader = nullptr)
|
||||
{
|
||||
return import(data, factory, result, ref_rcp(assetLoader));
|
||||
}
|
||||
|
||||
static std::unique_ptr<File> import(Span<const uint8_t> data,
|
||||
Factory*,
|
||||
ImportResult* result,
|
||||
rcp<FileAssetLoader> assetLoader);
|
||||
|
||||
/// @returns the file's backboard. All files have exactly one backboard.
|
||||
Backboard* backboard() const { return m_backboard; }
|
||||
@@ -156,6 +164,13 @@ public:
|
||||
ImportResult* result = nullptr);
|
||||
#endif
|
||||
|
||||
#ifdef TESTING
|
||||
FileAssetLoader* testing_getAssetLoader() const
|
||||
{
|
||||
return m_assetLoader.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
ImportResult read(BinaryReader&, const RuntimeHeader&);
|
||||
|
||||
@@ -191,7 +206,7 @@ private:
|
||||
|
||||
/// The helper used to load assets when they're not provided in-band
|
||||
/// with the file.
|
||||
FileAssetLoader* m_assetLoader;
|
||||
rcp<FileAssetLoader> m_assetLoader;
|
||||
|
||||
rcp<ViewModelInstance> copyViewModelInstance(
|
||||
ViewModelInstance* viewModelInstance,
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "rive/span.hpp"
|
||||
#include "rive/refcnt.hpp"
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class Factory;
|
||||
class FileAsset;
|
||||
class FileAssetLoader
|
||||
class FileAssetLoader : public RefCnt<FileAssetLoader>
|
||||
{
|
||||
public:
|
||||
virtual ~FileAssetLoader() {}
|
||||
|
||||
@@ -219,6 +219,12 @@
|
||||
#include "rive/solo.hpp"
|
||||
#include "rive/text/text.hpp"
|
||||
#include "rive/text/text_follow_path_modifier.hpp"
|
||||
#include "rive/text/text_input.hpp"
|
||||
#include "rive/text/text_input_cursor.hpp"
|
||||
#include "rive/text/text_input_drawable.hpp"
|
||||
#include "rive/text/text_input_selected_text.hpp"
|
||||
#include "rive/text/text_input_selection.hpp"
|
||||
#include "rive/text/text_input_text.hpp"
|
||||
#include "rive/text/text_modifier.hpp"
|
||||
#include "rive/text/text_modifier_group.hpp"
|
||||
#include "rive/text/text_modifier_range.hpp"
|
||||
@@ -226,6 +232,7 @@
|
||||
#include "rive/text/text_style.hpp"
|
||||
#include "rive/text/text_style_axis.hpp"
|
||||
#include "rive/text/text_style_feature.hpp"
|
||||
#include "rive/text/text_style_paint.hpp"
|
||||
#include "rive/text/text_target_modifier.hpp"
|
||||
#include "rive/text/text_value_run.hpp"
|
||||
#include "rive/text/text_variation_modifier.hpp"
|
||||
@@ -312,12 +319,18 @@ public:
|
||||
return new DataEnumSystem();
|
||||
case ViewModelPropertyViewModelBase::typeKey:
|
||||
return new ViewModelPropertyViewModel();
|
||||
case ViewModelInstanceBase::typeKey:
|
||||
return new ViewModelInstance();
|
||||
case ViewModelPropertyBooleanBase::typeKey:
|
||||
return new ViewModelPropertyBoolean();
|
||||
case DataEnumValueBase::typeKey:
|
||||
return new DataEnumValue();
|
||||
case ViewModelPropertyTriggerBase::typeKey:
|
||||
return new ViewModelPropertyTrigger();
|
||||
case ViewModelPropertyStringBase::typeKey:
|
||||
return new ViewModelPropertyString();
|
||||
case ViewModelPropertyColorBase::typeKey:
|
||||
return new ViewModelPropertyColor();
|
||||
case ViewModelPropertyBooleanBase::typeKey:
|
||||
return new ViewModelPropertyBoolean();
|
||||
case ViewModelInstanceBase::typeKey:
|
||||
return new ViewModelInstance();
|
||||
case ViewModelPropertyAssetImageBase::typeKey:
|
||||
return new ViewModelPropertyAssetImage();
|
||||
case ViewModelInstanceBooleanBase::typeKey:
|
||||
@@ -330,18 +343,12 @@ public:
|
||||
return new ViewModelInstanceTrigger();
|
||||
case ViewModelInstanceSymbolListIndexBase::typeKey:
|
||||
return new ViewModelInstanceSymbolListIndex();
|
||||
case ViewModelPropertyStringBase::typeKey:
|
||||
return new ViewModelPropertyString();
|
||||
case ViewModelInstanceViewModelBase::typeKey:
|
||||
return new ViewModelInstanceViewModel();
|
||||
case ViewModelPropertyTriggerBase::typeKey:
|
||||
return new ViewModelPropertyTrigger();
|
||||
case ViewModelInstanceAssetBase::typeKey:
|
||||
return new ViewModelInstanceAsset();
|
||||
case ViewModelInstanceAssetImageBase::typeKey:
|
||||
return new ViewModelInstanceAssetImage();
|
||||
case DataEnumValueBase::typeKey:
|
||||
return new DataEnumValue();
|
||||
case DrawTargetBase::typeKey:
|
||||
return new DrawTarget();
|
||||
case CustomPropertyNumberBase::typeKey:
|
||||
@@ -670,6 +677,10 @@ public:
|
||||
return new TextModifierRange();
|
||||
case TextFollowPathModifierBase::typeKey:
|
||||
return new TextFollowPathModifier();
|
||||
case TextInputCursorBase::typeKey:
|
||||
return new TextInputCursor();
|
||||
case TextInputTextBase::typeKey:
|
||||
return new TextInputText();
|
||||
case TextStyleFeatureBase::typeKey:
|
||||
return new TextStyleFeature();
|
||||
case TextVariationModifierBase::typeKey:
|
||||
@@ -678,8 +689,16 @@ public:
|
||||
return new TextModifierGroup();
|
||||
case TextStyleBase::typeKey:
|
||||
return new TextStyle();
|
||||
case TextStylePaintBase::typeKey:
|
||||
return new TextStylePaint();
|
||||
case TextInputSelectedTextBase::typeKey:
|
||||
return new TextInputSelectedText();
|
||||
case TextInputBase::typeKey:
|
||||
return new TextInput();
|
||||
case TextStyleAxisBase::typeKey:
|
||||
return new TextStyleAxis();
|
||||
case TextInputSelectionBase::typeKey:
|
||||
return new TextInputSelection();
|
||||
case TextBase::typeKey:
|
||||
return new Text();
|
||||
case TextValueRunBase::typeKey:
|
||||
@@ -1383,15 +1402,15 @@ public:
|
||||
case ViewModelInstanceStringBase::propertyValuePropertyKey:
|
||||
object->as<ViewModelInstanceStringBase>()->propertyValue(value);
|
||||
break;
|
||||
case ComponentBase::namePropertyKey:
|
||||
object->as<ComponentBase>()->name(value);
|
||||
break;
|
||||
case DataEnumValueBase::keyPropertyKey:
|
||||
object->as<DataEnumValueBase>()->key(value);
|
||||
break;
|
||||
case DataEnumValueBase::valuePropertyKey:
|
||||
object->as<DataEnumValueBase>()->value(value);
|
||||
break;
|
||||
case ComponentBase::namePropertyKey:
|
||||
object->as<ComponentBase>()->name(value);
|
||||
break;
|
||||
case AnimationBase::namePropertyKey:
|
||||
object->as<AnimationBase>()->name(value);
|
||||
break;
|
||||
@@ -1419,6 +1438,9 @@ public:
|
||||
case BindablePropertyStringBase::propertyValuePropertyKey:
|
||||
object->as<BindablePropertyStringBase>()->propertyValue(value);
|
||||
break;
|
||||
case TextInputBase::textPropertyKey:
|
||||
object->as<TextInputBase>()->text(value);
|
||||
break;
|
||||
case TextValueRunBase::textPropertyKey:
|
||||
object->as<TextValueRunBase>()->text(value);
|
||||
break;
|
||||
@@ -2169,6 +2191,9 @@ public:
|
||||
case TextStyleBase::letterSpacingPropertyKey:
|
||||
object->as<TextStyleBase>()->letterSpacing(value);
|
||||
break;
|
||||
case TextInputBase::selectionRadiusPropertyKey:
|
||||
object->as<TextInputBase>()->selectionRadius(value);
|
||||
break;
|
||||
case TextStyleAxisBase::axisValuePropertyKey:
|
||||
object->as<TextStyleAxisBase>()->axisValue(value);
|
||||
break;
|
||||
@@ -2705,12 +2730,12 @@ public:
|
||||
case ViewModelInstanceStringBase::propertyValuePropertyKey:
|
||||
return object->as<ViewModelInstanceStringBase>()
|
||||
->propertyValue();
|
||||
case ComponentBase::namePropertyKey:
|
||||
return object->as<ComponentBase>()->name();
|
||||
case DataEnumValueBase::keyPropertyKey:
|
||||
return object->as<DataEnumValueBase>()->key();
|
||||
case DataEnumValueBase::valuePropertyKey:
|
||||
return object->as<DataEnumValueBase>()->value();
|
||||
case ComponentBase::namePropertyKey:
|
||||
return object->as<ComponentBase>()->name();
|
||||
case AnimationBase::namePropertyKey:
|
||||
return object->as<AnimationBase>()->name();
|
||||
case StateMachineComponentBase::namePropertyKey:
|
||||
@@ -2731,6 +2756,8 @@ public:
|
||||
case BindablePropertyStringBase::propertyValuePropertyKey:
|
||||
return object->as<BindablePropertyStringBase>()
|
||||
->propertyValue();
|
||||
case TextInputBase::textPropertyKey:
|
||||
return object->as<TextInputBase>()->text();
|
||||
case TextValueRunBase::textPropertyKey:
|
||||
return object->as<TextValueRunBase>()->text();
|
||||
case CustomPropertyStringBase::propertyValuePropertyKey:
|
||||
@@ -3250,6 +3277,8 @@ public:
|
||||
return object->as<TextStyleBase>()->lineHeight();
|
||||
case TextStyleBase::letterSpacingPropertyKey:
|
||||
return object->as<TextStyleBase>()->letterSpacing();
|
||||
case TextInputBase::selectionRadiusPropertyKey:
|
||||
return object->as<TextInputBase>()->selectionRadius();
|
||||
case TextStyleAxisBase::axisValuePropertyKey:
|
||||
return object->as<TextStyleAxisBase>()->axisValue();
|
||||
case TextBase::widthPropertyKey:
|
||||
@@ -3482,9 +3511,9 @@ public:
|
||||
case ViewModelComponentBase::namePropertyKey:
|
||||
case DataEnumCustomBase::namePropertyKey:
|
||||
case ViewModelInstanceStringBase::propertyValuePropertyKey:
|
||||
case ComponentBase::namePropertyKey:
|
||||
case DataEnumValueBase::keyPropertyKey:
|
||||
case DataEnumValueBase::valuePropertyKey:
|
||||
case ComponentBase::namePropertyKey:
|
||||
case AnimationBase::namePropertyKey:
|
||||
case StateMachineComponentBase::namePropertyKey:
|
||||
case KeyFrameStringBase::valuePropertyKey:
|
||||
@@ -3494,6 +3523,7 @@ public:
|
||||
case DataConverterStringPadBase::textPropertyKey:
|
||||
case DataConverterToStringBase::colorFormatPropertyKey:
|
||||
case BindablePropertyStringBase::propertyValuePropertyKey:
|
||||
case TextInputBase::textPropertyKey:
|
||||
case TextValueRunBase::textPropertyKey:
|
||||
case CustomPropertyStringBase::propertyValuePropertyKey:
|
||||
case AssetBase::namePropertyKey:
|
||||
@@ -3740,6 +3770,7 @@ public:
|
||||
case TextStyleBase::fontSizePropertyKey:
|
||||
case TextStyleBase::lineHeightPropertyKey:
|
||||
case TextStyleBase::letterSpacingPropertyKey:
|
||||
case TextInputBase::selectionRadiusPropertyKey:
|
||||
case TextStyleAxisBase::axisValuePropertyKey:
|
||||
case TextBase::widthPropertyKey:
|
||||
case TextBase::heightPropertyKey:
|
||||
@@ -4184,12 +4215,12 @@ public:
|
||||
return object->is<DataEnumCustomBase>();
|
||||
case ViewModelInstanceStringBase::propertyValuePropertyKey:
|
||||
return object->is<ViewModelInstanceStringBase>();
|
||||
case ComponentBase::namePropertyKey:
|
||||
return object->is<ComponentBase>();
|
||||
case DataEnumValueBase::keyPropertyKey:
|
||||
return object->is<DataEnumValueBase>();
|
||||
case DataEnumValueBase::valuePropertyKey:
|
||||
return object->is<DataEnumValueBase>();
|
||||
case ComponentBase::namePropertyKey:
|
||||
return object->is<ComponentBase>();
|
||||
case AnimationBase::namePropertyKey:
|
||||
return object->is<AnimationBase>();
|
||||
case StateMachineComponentBase::namePropertyKey:
|
||||
@@ -4208,6 +4239,8 @@ public:
|
||||
return object->is<DataConverterToStringBase>();
|
||||
case BindablePropertyStringBase::propertyValuePropertyKey:
|
||||
return object->is<BindablePropertyStringBase>();
|
||||
case TextInputBase::textPropertyKey:
|
||||
return object->is<TextInputBase>();
|
||||
case TextValueRunBase::textPropertyKey:
|
||||
return object->is<TextValueRunBase>();
|
||||
case CustomPropertyStringBase::propertyValuePropertyKey:
|
||||
@@ -4694,6 +4727,8 @@ public:
|
||||
return object->is<TextStyleBase>();
|
||||
case TextStyleBase::letterSpacingPropertyKey:
|
||||
return object->is<TextStyleBase>();
|
||||
case TextInputBase::selectionRadiusPropertyKey:
|
||||
return object->is<TextInputBase>();
|
||||
case TextStyleAxisBase::axisValuePropertyKey:
|
||||
return object->is<TextStyleAxisBase>();
|
||||
case TextBase::widthPropertyKey:
|
||||
|
||||
96
include/rive/generated/text/text_input_base.hpp
Normal file
96
include/rive/generated/text/text_input_base.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_BASE_HPP_
|
||||
#define _RIVE_TEXT_INPUT_BASE_HPP_
|
||||
#include <string>
|
||||
#include "rive/core/field_types/core_double_type.hpp"
|
||||
#include "rive/core/field_types/core_string_type.hpp"
|
||||
#include "rive/drawable.hpp"
|
||||
namespace rive
|
||||
{
|
||||
class TextInputBase : public Drawable
|
||||
{
|
||||
protected:
|
||||
typedef Drawable Super;
|
||||
|
||||
public:
|
||||
static const uint16_t typeKey = 569;
|
||||
|
||||
/// Helper to quickly determine if a core object extends another without
|
||||
/// RTTI at runtime.
|
||||
bool isTypeOf(uint16_t typeKey) const override
|
||||
{
|
||||
switch (typeKey)
|
||||
{
|
||||
case TextInputBase::typeKey:
|
||||
case DrawableBase::typeKey:
|
||||
case NodeBase::typeKey:
|
||||
case TransformComponentBase::typeKey:
|
||||
case WorldTransformComponentBase::typeKey:
|
||||
case ContainerComponentBase::typeKey:
|
||||
case ComponentBase::typeKey:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t coreType() const override { return typeKey; }
|
||||
|
||||
static const uint16_t textPropertyKey = 817;
|
||||
static const uint16_t selectionRadiusPropertyKey = 818;
|
||||
|
||||
protected:
|
||||
std::string m_Text = "";
|
||||
float m_SelectionRadius = 5.0f;
|
||||
|
||||
public:
|
||||
inline const std::string& text() const { return m_Text; }
|
||||
void text(std::string value)
|
||||
{
|
||||
if (m_Text == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_Text = value;
|
||||
textChanged();
|
||||
}
|
||||
|
||||
inline float selectionRadius() const { return m_SelectionRadius; }
|
||||
void selectionRadius(float value)
|
||||
{
|
||||
if (m_SelectionRadius == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_SelectionRadius = value;
|
||||
selectionRadiusChanged();
|
||||
}
|
||||
|
||||
Core* clone() const override;
|
||||
void copy(const TextInputBase& object)
|
||||
{
|
||||
m_Text = object.m_Text;
|
||||
m_SelectionRadius = object.m_SelectionRadius;
|
||||
Drawable::copy(object);
|
||||
}
|
||||
|
||||
bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
|
||||
{
|
||||
switch (propertyKey)
|
||||
{
|
||||
case textPropertyKey:
|
||||
m_Text = CoreStringType::deserialize(reader);
|
||||
return true;
|
||||
case selectionRadiusPropertyKey:
|
||||
m_SelectionRadius = CoreDoubleType::deserialize(reader);
|
||||
return true;
|
||||
}
|
||||
return Drawable::deserialize(propertyKey, reader);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void textChanged() {}
|
||||
virtual void selectionRadiusChanged() {}
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
42
include/rive/generated/text/text_input_cursor_base.hpp
Normal file
42
include/rive/generated/text/text_input_cursor_base.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_CURSOR_BASE_HPP_
|
||||
#define _RIVE_TEXT_INPUT_CURSOR_BASE_HPP_
|
||||
#include "rive/text/text_input_drawable.hpp"
|
||||
namespace rive
|
||||
{
|
||||
class TextInputCursorBase : public TextInputDrawable
|
||||
{
|
||||
protected:
|
||||
typedef TextInputDrawable Super;
|
||||
|
||||
public:
|
||||
static const uint16_t typeKey = 571;
|
||||
|
||||
/// Helper to quickly determine if a core object extends another without
|
||||
/// RTTI at runtime.
|
||||
bool isTypeOf(uint16_t typeKey) const override
|
||||
{
|
||||
switch (typeKey)
|
||||
{
|
||||
case TextInputCursorBase::typeKey:
|
||||
case TextInputDrawableBase::typeKey:
|
||||
case DrawableBase::typeKey:
|
||||
case NodeBase::typeKey:
|
||||
case TransformComponentBase::typeKey:
|
||||
case WorldTransformComponentBase::typeKey:
|
||||
case ContainerComponentBase::typeKey:
|
||||
case ComponentBase::typeKey:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t coreType() const override { return typeKey; }
|
||||
|
||||
Core* clone() const override;
|
||||
|
||||
protected:
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
39
include/rive/generated/text/text_input_drawable_base.hpp
Normal file
39
include/rive/generated/text/text_input_drawable_base.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_DRAWABLE_BASE_HPP_
|
||||
#define _RIVE_TEXT_INPUT_DRAWABLE_BASE_HPP_
|
||||
#include "rive/drawable.hpp"
|
||||
namespace rive
|
||||
{
|
||||
class TextInputDrawableBase : public Drawable
|
||||
{
|
||||
protected:
|
||||
typedef Drawable Super;
|
||||
|
||||
public:
|
||||
static const uint16_t typeKey = 570;
|
||||
|
||||
/// Helper to quickly determine if a core object extends another without
|
||||
/// RTTI at runtime.
|
||||
bool isTypeOf(uint16_t typeKey) const override
|
||||
{
|
||||
switch (typeKey)
|
||||
{
|
||||
case TextInputDrawableBase::typeKey:
|
||||
case DrawableBase::typeKey:
|
||||
case NodeBase::typeKey:
|
||||
case TransformComponentBase::typeKey:
|
||||
case WorldTransformComponentBase::typeKey:
|
||||
case ContainerComponentBase::typeKey:
|
||||
case ComponentBase::typeKey:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t coreType() const override { return typeKey; }
|
||||
|
||||
protected:
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_SELECTED_TEXT_BASE_HPP_
|
||||
#define _RIVE_TEXT_INPUT_SELECTED_TEXT_BASE_HPP_
|
||||
#include "rive/text/text_input_drawable.hpp"
|
||||
namespace rive
|
||||
{
|
||||
class TextInputSelectedTextBase : public TextInputDrawable
|
||||
{
|
||||
protected:
|
||||
typedef TextInputDrawable Super;
|
||||
|
||||
public:
|
||||
static const uint16_t typeKey = 575;
|
||||
|
||||
/// Helper to quickly determine if a core object extends another without
|
||||
/// RTTI at runtime.
|
||||
bool isTypeOf(uint16_t typeKey) const override
|
||||
{
|
||||
switch (typeKey)
|
||||
{
|
||||
case TextInputSelectedTextBase::typeKey:
|
||||
case TextInputDrawableBase::typeKey:
|
||||
case DrawableBase::typeKey:
|
||||
case NodeBase::typeKey:
|
||||
case TransformComponentBase::typeKey:
|
||||
case WorldTransformComponentBase::typeKey:
|
||||
case ContainerComponentBase::typeKey:
|
||||
case ComponentBase::typeKey:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t coreType() const override { return typeKey; }
|
||||
|
||||
Core* clone() const override;
|
||||
|
||||
protected:
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
42
include/rive/generated/text/text_input_selection_base.hpp
Normal file
42
include/rive/generated/text/text_input_selection_base.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_SELECTION_BASE_HPP_
|
||||
#define _RIVE_TEXT_INPUT_SELECTION_BASE_HPP_
|
||||
#include "rive/text/text_input_drawable.hpp"
|
||||
namespace rive
|
||||
{
|
||||
class TextInputSelectionBase : public TextInputDrawable
|
||||
{
|
||||
protected:
|
||||
typedef TextInputDrawable Super;
|
||||
|
||||
public:
|
||||
static const uint16_t typeKey = 574;
|
||||
|
||||
/// Helper to quickly determine if a core object extends another without
|
||||
/// RTTI at runtime.
|
||||
bool isTypeOf(uint16_t typeKey) const override
|
||||
{
|
||||
switch (typeKey)
|
||||
{
|
||||
case TextInputSelectionBase::typeKey:
|
||||
case TextInputDrawableBase::typeKey:
|
||||
case DrawableBase::typeKey:
|
||||
case NodeBase::typeKey:
|
||||
case TransformComponentBase::typeKey:
|
||||
case WorldTransformComponentBase::typeKey:
|
||||
case ContainerComponentBase::typeKey:
|
||||
case ComponentBase::typeKey:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t coreType() const override { return typeKey; }
|
||||
|
||||
Core* clone() const override;
|
||||
|
||||
protected:
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
42
include/rive/generated/text/text_input_text_base.hpp
Normal file
42
include/rive/generated/text/text_input_text_base.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_TEXT_BASE_HPP_
|
||||
#define _RIVE_TEXT_INPUT_TEXT_BASE_HPP_
|
||||
#include "rive/text/text_input_drawable.hpp"
|
||||
namespace rive
|
||||
{
|
||||
class TextInputTextBase : public TextInputDrawable
|
||||
{
|
||||
protected:
|
||||
typedef TextInputDrawable Super;
|
||||
|
||||
public:
|
||||
static const uint16_t typeKey = 572;
|
||||
|
||||
/// Helper to quickly determine if a core object extends another without
|
||||
/// RTTI at runtime.
|
||||
bool isTypeOf(uint16_t typeKey) const override
|
||||
{
|
||||
switch (typeKey)
|
||||
{
|
||||
case TextInputTextBase::typeKey:
|
||||
case TextInputDrawableBase::typeKey:
|
||||
case DrawableBase::typeKey:
|
||||
case NodeBase::typeKey:
|
||||
case TransformComponentBase::typeKey:
|
||||
case WorldTransformComponentBase::typeKey:
|
||||
case ContainerComponentBase::typeKey:
|
||||
case ComponentBase::typeKey:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t coreType() const override { return typeKey; }
|
||||
|
||||
Core* clone() const override;
|
||||
|
||||
protected:
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@ protected:
|
||||
typedef ContainerComponent Super;
|
||||
|
||||
public:
|
||||
static const uint16_t typeKey = 137;
|
||||
static const uint16_t typeKey = 573;
|
||||
|
||||
/// Helper to quickly determine if a core object extends another without
|
||||
/// RTTI at runtime.
|
||||
|
||||
40
include/rive/generated/text/text_style_paint_base.hpp
Normal file
40
include/rive/generated/text/text_style_paint_base.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef _RIVE_TEXT_STYLE_PAINT_BASE_HPP_
|
||||
#define _RIVE_TEXT_STYLE_PAINT_BASE_HPP_
|
||||
|
||||
#include "rive/text/text_style.hpp"
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class TextStylePaintBase : public TextStyle
|
||||
{
|
||||
protected:
|
||||
typedef TextStyle Super;
|
||||
|
||||
public:
|
||||
static const uint16_t typeKey = 137;
|
||||
|
||||
/// Helper to quickly determine if a core object extends another without
|
||||
/// RTTI at runtime.
|
||||
bool isTypeOf(uint16_t typeKey) const override
|
||||
{
|
||||
switch (typeKey)
|
||||
{
|
||||
case TextStylePaintBase::typeKey:
|
||||
case TextStyleBase::typeKey:
|
||||
case ContainerComponentBase::typeKey:
|
||||
case ComponentBase::typeKey:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t coreType() const override { return typeKey; }
|
||||
|
||||
Core* clone() const override;
|
||||
|
||||
protected:
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef _RIVE_FILE_ASSET_IMPORTER_HPP_
|
||||
#define _RIVE_FILE_ASSET_IMPORTER_HPP_
|
||||
|
||||
#include "rive/refcnt.hpp"
|
||||
#include "rive/importers/import_stack.hpp"
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -16,13 +17,13 @@ class FileAssetImporter : public ImportStackObject
|
||||
{
|
||||
private:
|
||||
FileAsset* m_FileAsset;
|
||||
FileAssetLoader* m_FileAssetLoader;
|
||||
rcp<FileAssetLoader> m_FileAssetLoader;
|
||||
Factory* m_Factory;
|
||||
// we will delete this when we go out of scope
|
||||
std::unique_ptr<FileAssetContents> m_Content;
|
||||
|
||||
public:
|
||||
FileAssetImporter(FileAsset*, FileAssetLoader*, Factory*);
|
||||
FileAssetImporter(FileAsset*, rcp<FileAssetLoader>, Factory*);
|
||||
void onFileAssetContents(std::unique_ptr<FileAssetContents> contents);
|
||||
StatusCode resolve() override;
|
||||
};
|
||||
|
||||
@@ -45,6 +45,10 @@ protected:
|
||||
void computedWorldYChanged() override {}
|
||||
void computedWidthChanged() override {}
|
||||
void computedHeightChanged() override {}
|
||||
|
||||
#ifdef WITH_RIVE_LAYOUT
|
||||
void markLayoutNodeDirty();
|
||||
#endif
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rive/refcnt.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
|
||||
@@ -63,6 +65,19 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T> PODStream& operator<<(rcp<T> obj)
|
||||
{
|
||||
return *this << obj.release();
|
||||
}
|
||||
|
||||
template <typename T> PODStream& operator>>(rcp<T>& obj)
|
||||
{
|
||||
T* raw;
|
||||
*this >> raw;
|
||||
obj = rcp<T>(raw);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::deque<char> m_byteStream;
|
||||
};
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
|
||||
/// Returns the bounds of the text object (helpful for aligning multiple
|
||||
/// text objects/procredurally drawn shapes).
|
||||
AABB bounds();
|
||||
AABB bounds() const;
|
||||
CursorVisualPosition cursorVisualPosition(CursorPosition position)
|
||||
{
|
||||
return position.visualPosition(m_shape);
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
#include "rive/text_engine.hpp"
|
||||
#include "rive/shapes/shape_paint_path.hpp"
|
||||
#include "rive/simple_array.hpp"
|
||||
#include "rive/text/glyph_lookup.hpp"
|
||||
#include "rive/text/text_interface.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "rive/text/glyph_lookup.hpp"
|
||||
|
||||
namespace rive
|
||||
{
|
||||
|
||||
@@ -53,17 +56,21 @@ enum class LineIter : uint8_t
|
||||
yOutOfBounds
|
||||
};
|
||||
|
||||
class TextStyle;
|
||||
class Text : public TextBase
|
||||
class TextStylePaint;
|
||||
class Text : public TextBase, public TextInterface
|
||||
{
|
||||
public:
|
||||
// Implements TextInterface
|
||||
void markShapeDirty() override;
|
||||
void markPaintDirty() override;
|
||||
|
||||
void draw(Renderer* renderer) override;
|
||||
Core* hitTest(HitInfo*, const Mat2D&) override;
|
||||
void addRun(TextValueRun* run);
|
||||
void addModifierGroup(TextModifierGroup* group);
|
||||
void markShapeDirty(bool sendToLayout = true);
|
||||
void markShapeDirty(bool sendToLayout);
|
||||
void modifierShapeDirty();
|
||||
void markPaintDirty();
|
||||
|
||||
void update(ComponentDirt value) override;
|
||||
void onDirty(ComponentDirt value) override;
|
||||
Mat2D m_transform;
|
||||
@@ -82,7 +89,7 @@ public:
|
||||
TextAlign align() const;
|
||||
void overflow(TextOverflow value) { return overflowValue((uint32_t)value); }
|
||||
void buildRenderStyles();
|
||||
const TextStyle* styleFromShaperId(uint16_t id) const;
|
||||
const TextStylePaint* styleFromShaperId(uint16_t id) const;
|
||||
bool modifierRangesNeedShape() const;
|
||||
AABB localBounds() const override;
|
||||
void originXChanged() override;
|
||||
@@ -115,10 +122,6 @@ public:
|
||||
TextWrap wrap);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_RIVE_LAYOUT
|
||||
void markLayoutNodeDirty();
|
||||
#endif
|
||||
|
||||
bool haveModifiers() const
|
||||
{
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
@@ -157,7 +160,7 @@ private:
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
void updateOriginWorldTransform();
|
||||
std::vector<TextValueRun*> m_runs;
|
||||
std::vector<TextStyle*> m_renderStyles;
|
||||
std::vector<TextStylePaint*> m_renderStyles;
|
||||
SimpleArray<Paragraph> m_shape;
|
||||
SimpleArray<Paragraph> m_modifierShape;
|
||||
SimpleArray<SimpleArray<GlyphLine>> m_lines;
|
||||
|
||||
50
include/rive/text/text_input.hpp
Normal file
50
include/rive/text/text_input.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_HPP_
|
||||
#define _RIVE_TEXT_INPUT_HPP_
|
||||
|
||||
#include "rive/generated/text/text_input_base.hpp"
|
||||
#include "rive/text/raw_text_input.hpp"
|
||||
#include "rive/text/text_interface.hpp"
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class TextStyle;
|
||||
class TextInput : public TextInputBase, public TextInterface
|
||||
{
|
||||
public:
|
||||
void draw(Renderer* renderer) override;
|
||||
Core* hitTest(HitInfo*, const Mat2D&) override;
|
||||
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
RawTextInput* rawTextInput() { return &m_rawTextInput; }
|
||||
#endif
|
||||
|
||||
void markPaintDirty() override;
|
||||
void markShapeDirty() override;
|
||||
StatusCode onAddedClean(CoreContext* context) override;
|
||||
|
||||
AABB localBounds() const override;
|
||||
void update(ComponentDirt value) override;
|
||||
|
||||
Vec2D measureLayout(float width,
|
||||
LayoutMeasureMode widthMode,
|
||||
float height,
|
||||
LayoutMeasureMode heightMode) override;
|
||||
void controlSize(Vec2D size,
|
||||
LayoutScaleType widthScaleType,
|
||||
LayoutScaleType heightScaleType,
|
||||
LayoutDirection direction) override;
|
||||
|
||||
protected:
|
||||
void textChanged() override;
|
||||
void selectionRadiusChanged() override;
|
||||
|
||||
private:
|
||||
AABB m_worldBounds;
|
||||
TextStyle* m_textStyle = nullptr;
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
RawTextInput m_rawTextInput;
|
||||
#endif
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
15
include/rive/text/text_input_cursor.hpp
Normal file
15
include/rive/text/text_input_cursor.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_CURSOR_HPP_
|
||||
#define _RIVE_TEXT_INPUT_CURSOR_HPP_
|
||||
#include "rive/generated/text/text_input_cursor_base.hpp"
|
||||
#include <stdio.h>
|
||||
namespace rive
|
||||
{
|
||||
class TextInputCursor : public TextInputCursorBase
|
||||
{
|
||||
public:
|
||||
Core* hitTest(HitInfo*, const Mat2D&) override;
|
||||
ShapePaintPath* localClockwisePath() override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
27
include/rive/text/text_input_drawable.hpp
Normal file
27
include/rive/text/text_input_drawable.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_DRAWABLE_HPP_
|
||||
#define _RIVE_TEXT_INPUT_DRAWABLE_HPP_
|
||||
|
||||
#include "rive/generated/text/text_input_drawable_base.hpp"
|
||||
#include "rive/shapes/shape_paint_container.hpp"
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class TextInput;
|
||||
class TextInputDrawable : public TextInputDrawableBase,
|
||||
public ShapePaintContainer
|
||||
{
|
||||
private:
|
||||
Artboard* getArtboard() override { return artboard(); }
|
||||
|
||||
public:
|
||||
ShapePaintPath* worldPath() override;
|
||||
const Mat2D& shapeWorldTransform() const override;
|
||||
ShapePaintPath* localPath() override { return localClockwisePath(); }
|
||||
StatusCode onAddedClean(CoreContext* context) override;
|
||||
TextInput* textInput() const;
|
||||
Component* pathBuilder() override { return parent(); }
|
||||
void draw(Renderer* renderer) override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
15
include/rive/text/text_input_selected_text.hpp
Normal file
15
include/rive/text/text_input_selected_text.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_SELECTED_TEXT_HPP_
|
||||
#define _RIVE_TEXT_INPUT_SELECTED_TEXT_HPP_
|
||||
#include "rive/generated/text/text_input_selected_text_base.hpp"
|
||||
#include <stdio.h>
|
||||
namespace rive
|
||||
{
|
||||
class TextInputSelectedText : public TextInputSelectedTextBase
|
||||
{
|
||||
public:
|
||||
Core* hitTest(HitInfo*, const Mat2D&) override;
|
||||
ShapePaintPath* localClockwisePath() override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
15
include/rive/text/text_input_selection.hpp
Normal file
15
include/rive/text/text_input_selection.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_SELECTION_HPP_
|
||||
#define _RIVE_TEXT_INPUT_SELECTION_HPP_
|
||||
#include "rive/generated/text/text_input_selection_base.hpp"
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class TextInputSelection : public TextInputSelectionBase
|
||||
{
|
||||
public:
|
||||
Core* hitTest(HitInfo*, const Mat2D&) override;
|
||||
ShapePaintPath* localClockwisePath() override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
15
include/rive/text/text_input_text.hpp
Normal file
15
include/rive/text/text_input_text.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _RIVE_TEXT_INPUT_TEXT_HPP_
|
||||
#define _RIVE_TEXT_INPUT_TEXT_HPP_
|
||||
#include "rive/generated/text/text_input_text_base.hpp"
|
||||
#include <stdio.h>
|
||||
namespace rive
|
||||
{
|
||||
class TextInputText : public TextInputTextBase
|
||||
{
|
||||
public:
|
||||
Core* hitTest(HitInfo*, const Mat2D&) override;
|
||||
ShapePaintPath* localClockwisePath() override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
22
include/rive/text/text_interface.hpp
Normal file
22
include/rive/text/text_interface.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef _RIVE_TEXT_INTERFACE_HPP_
|
||||
#define _RIVE_TEXT_INTERFACE_HPP_
|
||||
|
||||
#include "rive/math/aabb.hpp"
|
||||
#include "rive/math/vec2d.hpp"
|
||||
#include "rive/math/mat2d.hpp"
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class Core;
|
||||
|
||||
class TextInterface
|
||||
{
|
||||
public:
|
||||
static TextInterface* from(Core* component);
|
||||
virtual void markPaintDirty() = 0;
|
||||
virtual void markShapeDirty() = 0;
|
||||
virtual AABB localBounds() const = 0;
|
||||
};
|
||||
|
||||
} // namespace rive
|
||||
#endif
|
||||
@@ -1,12 +1,10 @@
|
||||
#ifndef _RIVE_TEXT_STYLE_HPP_
|
||||
#define _RIVE_TEXT_STYLE_HPP_
|
||||
#include "rive/generated/text/text_style_base.hpp"
|
||||
#include "rive/shapes/shape_paint_container.hpp"
|
||||
#include "rive/shapes/shape_paint_path.hpp"
|
||||
#include "rive/assets/file_asset_referencer.hpp"
|
||||
#include "rive/assets/file_asset.hpp"
|
||||
#include "rive/assets/font_asset.hpp"
|
||||
#include <unordered_map>
|
||||
#include "rive/text/text_interface.hpp"
|
||||
|
||||
namespace rive
|
||||
{
|
||||
@@ -20,13 +18,10 @@ class RenderPaint;
|
||||
class TextVariationHelper;
|
||||
class TextStyleAxis;
|
||||
class TextStyleFeature;
|
||||
class TextStyle : public TextStyleBase,
|
||||
public ShapePaintContainer,
|
||||
public FileAssetReferencer
|
||||
{
|
||||
private:
|
||||
Artboard* getArtboard() override { return artboard(); }
|
||||
class TextInterface;
|
||||
|
||||
class TextStyle : public TextStyleBase, public FileAssetReferencer
|
||||
{
|
||||
public:
|
||||
TextStyle();
|
||||
void buildDependencies() override;
|
||||
@@ -37,19 +32,13 @@ public:
|
||||
|
||||
FontAsset* fontAsset() const { return (FontAsset*)m_fileAsset; }
|
||||
|
||||
bool addPath(const RawPath& rawPath, float opacity);
|
||||
void rewindPath();
|
||||
void draw(Renderer* renderer, const Mat2D& worldTransform);
|
||||
Core* clone() const override;
|
||||
void addVariation(TextStyleAxis* axis);
|
||||
void addFeature(TextStyleFeature* feature);
|
||||
void updateVariableFont();
|
||||
StatusCode onAddedClean(CoreContext* context) override;
|
||||
void onDirty(ComponentDirt dirt) override;
|
||||
// Implemented for ShapePaintContainer.
|
||||
const Mat2D& shapeWorldTransform() const override;
|
||||
|
||||
Component* pathBuilder() override;
|
||||
bool validate(CoreContext* context) override;
|
||||
|
||||
protected:
|
||||
void fontSizeChanged() override;
|
||||
@@ -58,19 +47,13 @@ protected:
|
||||
|
||||
private:
|
||||
std::unique_ptr<TextVariationHelper> m_variationHelper;
|
||||
std::unordered_map<float, ShapePaintPath> m_opacityPaths;
|
||||
rcp<Font> m_variableFont;
|
||||
ShapePaintPath m_path;
|
||||
bool m_hasContents = false;
|
||||
|
||||
std::vector<Font::Coord> m_coords;
|
||||
std::vector<TextStyleAxis*> m_variations;
|
||||
std::vector<rcp<RenderPaint>> m_paintPool;
|
||||
std::vector<TextStyleFeature*> m_styleFeatures;
|
||||
std::vector<Font::Feature> m_features;
|
||||
|
||||
public:
|
||||
ShapePaintPath* localPath() override { return &m_path; }
|
||||
ShapePaintPath* localClockwisePath() override { return &m_path; }
|
||||
TextInterface* m_text;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
|
||||
34
include/rive/text/text_style_paint.hpp
Normal file
34
include/rive/text/text_style_paint.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef _RIVE_TEXT_STYLE_PAINT_HPP_
|
||||
#define _RIVE_TEXT_STYLE_PAINT_HPP_
|
||||
#include "rive/generated/text/text_style_paint_base.hpp"
|
||||
#include "rive/shapes/shape_paint_container.hpp"
|
||||
#include "rive/shapes/shape_paint_path.hpp"
|
||||
#include <unordered_map>
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class TextStylePaint : public TextStylePaintBase, public ShapePaintContainer
|
||||
{
|
||||
public:
|
||||
TextStylePaint();
|
||||
bool addPath(const RawPath& rawPath, float opacity);
|
||||
void rewindPath();
|
||||
void draw(Renderer* renderer, const Mat2D& worldTransform);
|
||||
|
||||
// Implemented for ShapePaintContainer.
|
||||
const Mat2D& shapeWorldTransform() const override;
|
||||
Component* pathBuilder() override;
|
||||
ShapePaintPath* localPath() override { return &m_path; }
|
||||
ShapePaintPath* localClockwisePath() override { return &m_path; }
|
||||
Core* clone() const override;
|
||||
|
||||
private:
|
||||
Artboard* getArtboard() override { return artboard(); }
|
||||
std::unordered_map<float, ShapePaintPath> m_opacityPaths;
|
||||
std::vector<rcp<RenderPaint>> m_paintPool;
|
||||
ShapePaintPath m_path;
|
||||
bool m_hasContents = false;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class TextStyle;
|
||||
class TextStylePaint;
|
||||
class Text;
|
||||
class TextValueRun : public TextValueRunBase, public Hittable
|
||||
{
|
||||
@@ -16,7 +16,7 @@ class TextValueRun : public TextValueRunBase, public Hittable
|
||||
public:
|
||||
StatusCode onAddedClean(CoreContext* context) override;
|
||||
StatusCode onAddedDirty(CoreContext* context) override;
|
||||
TextStyle* style() { return m_style; }
|
||||
TextStylePaint* style() { return m_style; }
|
||||
Text* textComponent() const;
|
||||
uint32_t length()
|
||||
{
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
AABB m_localBounds;
|
||||
bool m_isHitTarget = false;
|
||||
std::vector<AABB> m_glyphHitRects;
|
||||
TextStyle* m_style = nullptr;
|
||||
TextStylePaint* m_style = nullptr;
|
||||
uint32_t m_length = -1;
|
||||
bool canHitTest() const;
|
||||
};
|
||||
|
||||
21
include/rive/text/text_variation_helper.hpp
Normal file
21
include/rive/text/text_variation_helper.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef _RIVE_TEXT_VARIATION_HELPER_HPP_
|
||||
#define _RIVE_TEXT_VARIATION_HELPER_HPP_
|
||||
|
||||
#include "rive/component.hpp"
|
||||
namespace rive
|
||||
{
|
||||
class TextStyle;
|
||||
class TextVariationHelper : public Component
|
||||
{
|
||||
public:
|
||||
TextVariationHelper(TextStyle* style) : m_textStyle(style) {}
|
||||
TextStyle* style() const { return m_textStyle; }
|
||||
void buildDependencies() override;
|
||||
void update(ComponentDirt value) override;
|
||||
|
||||
private:
|
||||
TextStyle* m_textStyle;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
84
include/rive/typed_children.hpp
Normal file
84
include/rive/typed_children.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef _RIVE_TYPED_CHILDREN_HPP_
|
||||
#define _RIVE_TYPED_CHILDREN_HPP_
|
||||
|
||||
#include "rive/core.hpp"
|
||||
#include "rive/span.hpp"
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class Core;
|
||||
template <typename T> class TypedChild
|
||||
{
|
||||
public:
|
||||
TypedChild(Core** child, Core** end) : m_child(child), m_end(end) {}
|
||||
|
||||
T* operator*() const { return (*m_child)->template as<T>(); }
|
||||
TypedChild& operator++()
|
||||
{
|
||||
m_child++;
|
||||
while (m_child != m_end && (*m_child) != nullptr &&
|
||||
!(*m_child)->template is<T>())
|
||||
{
|
||||
m_child++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const TypedChild& o) const { return m_child == o.m_child; }
|
||||
|
||||
bool operator!=(const TypedChild& o) const { return m_child != o.m_child; }
|
||||
|
||||
private:
|
||||
Core** m_child;
|
||||
Core** m_end;
|
||||
};
|
||||
|
||||
template <typename T> class TypedChildren
|
||||
{
|
||||
public:
|
||||
TypedChildren(Span<Core*> children) : m_children(children) {}
|
||||
|
||||
TypedChild<T> begin() const
|
||||
{
|
||||
size_t size = m_children.size();
|
||||
size_t index = 0;
|
||||
while (index < size && !m_children[index]->template is<T>())
|
||||
{
|
||||
index++;
|
||||
}
|
||||
return TypedChild<T>(m_children.data() + index,
|
||||
m_children.data() + size);
|
||||
}
|
||||
|
||||
TypedChild<T> end() const
|
||||
{
|
||||
auto ptr = m_children.data() + m_children.size();
|
||||
return TypedChild<T>(ptr, ptr);
|
||||
}
|
||||
|
||||
T* first() const
|
||||
{
|
||||
auto start = begin();
|
||||
if (start == end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return *start;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
size_t count = 0;
|
||||
auto last = end();
|
||||
for (auto itr = begin(); itr != last; ++itr)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
Span<Core*> m_children;
|
||||
};
|
||||
} // namespace rive
|
||||
#endif
|
||||
@@ -36,8 +36,11 @@ CommandQueue::CommandQueue() {}
|
||||
CommandQueue::~CommandQueue() {}
|
||||
|
||||
FileHandle CommandQueue::loadFile(std::vector<uint8_t> rivBytes,
|
||||
FileListener* listener)
|
||||
rcp<FileAssetLoader> loader,
|
||||
FileListener* listener,
|
||||
RequestId* outId)
|
||||
{
|
||||
auto requestId = ++m_currentRequestIdIdx;
|
||||
auto handle = reinterpret_cast<FileHandle>(++m_currentFileHandleIdx);
|
||||
|
||||
if (listener)
|
||||
@@ -47,26 +50,40 @@ FileHandle CommandQueue::loadFile(std::vector<uint8_t> rivBytes,
|
||||
registerListener(handle, listener);
|
||||
}
|
||||
|
||||
if (outId)
|
||||
{
|
||||
*outId = requestId;
|
||||
}
|
||||
|
||||
AutoLockAndNotify lock(m_commandMutex, m_commandConditionVariable);
|
||||
m_commandStream << Command::loadFile;
|
||||
m_commandStream << handle;
|
||||
m_commandStream << requestId;
|
||||
m_commandStream << loader;
|
||||
m_byteVectors << std::move(rivBytes);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void CommandQueue::deleteFile(FileHandle fileHandle)
|
||||
RequestId CommandQueue::deleteFile(FileHandle fileHandle)
|
||||
{
|
||||
auto requestId = ++m_currentRequestIdIdx;
|
||||
|
||||
AutoLockAndNotify lock(m_commandMutex, m_commandConditionVariable);
|
||||
m_commandStream << Command::deleteFile;
|
||||
m_commandStream << fileHandle;
|
||||
m_commandStream << requestId;
|
||||
|
||||
return requestId;
|
||||
}
|
||||
|
||||
ArtboardHandle CommandQueue::instantiateArtboardNamed(
|
||||
FileHandle fileHandle,
|
||||
std::string name,
|
||||
ArtboardListener* listener)
|
||||
ArtboardListener* listener,
|
||||
RequestId* outId)
|
||||
{
|
||||
auto requestId = ++m_currentRequestIdIdx;
|
||||
auto handle =
|
||||
reinterpret_cast<ArtboardHandle>(++m_currentArtboardHandleIdx);
|
||||
|
||||
@@ -77,27 +94,40 @@ ArtboardHandle CommandQueue::instantiateArtboardNamed(
|
||||
registerListener(handle, listener);
|
||||
}
|
||||
|
||||
if (outId)
|
||||
{
|
||||
*outId = requestId;
|
||||
}
|
||||
|
||||
AutoLockAndNotify lock(m_commandMutex, m_commandConditionVariable);
|
||||
m_commandStream << Command::instantiateArtboard;
|
||||
m_commandStream << handle;
|
||||
m_commandStream << fileHandle;
|
||||
m_commandStream << requestId;
|
||||
m_names << std::move(name);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void CommandQueue::deleteArtboard(ArtboardHandle artboardHandle)
|
||||
RequestId CommandQueue::deleteArtboard(ArtboardHandle artboardHandle)
|
||||
{
|
||||
auto requestId = ++m_currentRequestIdIdx;
|
||||
|
||||
AutoLockAndNotify lock(m_commandMutex, m_commandConditionVariable);
|
||||
m_commandStream << Command::deleteArtboard;
|
||||
m_commandStream << artboardHandle;
|
||||
m_commandStream << requestId;
|
||||
|
||||
return requestId;
|
||||
}
|
||||
|
||||
StateMachineHandle CommandQueue::instantiateStateMachineNamed(
|
||||
ArtboardHandle artboardHandle,
|
||||
std::string name,
|
||||
StateMachineListener* listener)
|
||||
StateMachineListener* listener,
|
||||
RequestId* outId)
|
||||
{
|
||||
auto requestId = ++m_currentRequestIdIdx;
|
||||
auto handle =
|
||||
reinterpret_cast<StateMachineHandle>(++m_currentStateMachineHandleIdx);
|
||||
|
||||
@@ -108,20 +138,32 @@ StateMachineHandle CommandQueue::instantiateStateMachineNamed(
|
||||
registerListener(handle, listener);
|
||||
}
|
||||
|
||||
if (outId)
|
||||
{
|
||||
*outId = requestId;
|
||||
}
|
||||
|
||||
AutoLockAndNotify lock(m_commandMutex, m_commandConditionVariable);
|
||||
m_commandStream << Command::instantiateStateMachine;
|
||||
m_commandStream << handle;
|
||||
m_commandStream << artboardHandle;
|
||||
m_commandStream << requestId;
|
||||
m_names << std::move(name);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void CommandQueue::deleteStateMachine(StateMachineHandle stateMachineHandle)
|
||||
RequestId CommandQueue::deleteStateMachine(
|
||||
StateMachineHandle stateMachineHandle)
|
||||
{
|
||||
auto requestId = ++m_currentRequestIdIdx;
|
||||
|
||||
AutoLockAndNotify lock(m_commandMutex, m_commandConditionVariable);
|
||||
m_commandStream << Command::deleteStateMachine;
|
||||
m_commandStream << stateMachineHandle;
|
||||
m_commandStream << requestId;
|
||||
|
||||
return requestId;
|
||||
}
|
||||
|
||||
DrawKey CommandQueue::createDrawKey()
|
||||
@@ -187,18 +229,28 @@ void CommandQueue::disconnect()
|
||||
m_commandStream << Command::disconnect;
|
||||
}
|
||||
|
||||
void CommandQueue::requestArtboardNames(FileHandle fileHandle)
|
||||
RequestId CommandQueue::requestArtboardNames(FileHandle fileHandle)
|
||||
{
|
||||
auto requestId = ++m_currentRequestIdIdx;
|
||||
|
||||
AutoLockAndNotify lock(m_commandMutex, m_commandConditionVariable);
|
||||
m_commandStream << Command::listArtboards;
|
||||
m_commandStream << fileHandle;
|
||||
m_commandStream << requestId;
|
||||
|
||||
return requestId;
|
||||
}
|
||||
|
||||
void CommandQueue::requestStateMachineNames(ArtboardHandle artboardHandle)
|
||||
RequestId CommandQueue::requestStateMachineNames(ArtboardHandle artboardHandle)
|
||||
{
|
||||
auto requestId = ++m_currentRequestIdIdx;
|
||||
|
||||
AutoLockAndNotify lock(m_commandMutex, m_commandConditionVariable);
|
||||
m_commandStream << Command::listStateMachines;
|
||||
m_commandStream << artboardHandle;
|
||||
m_commandStream << requestId;
|
||||
|
||||
return requestId;
|
||||
}
|
||||
|
||||
void CommandQueue::processMessages()
|
||||
@@ -226,7 +278,9 @@ void CommandQueue::processMessages()
|
||||
{
|
||||
size_t numArtboards;
|
||||
FileHandle handle;
|
||||
RequestId requestId;
|
||||
m_messageStream >> handle;
|
||||
m_messageStream >> requestId;
|
||||
m_messageStream >> numArtboards;
|
||||
std::vector<std::string> artboardNames(numArtboards);
|
||||
for (auto& name : artboardNames)
|
||||
@@ -239,6 +293,7 @@ void CommandQueue::processMessages()
|
||||
if (itr != m_fileListeners.end())
|
||||
{
|
||||
itr->second->onArtboardsListed(itr->first,
|
||||
requestId,
|
||||
std::move(artboardNames));
|
||||
}
|
||||
break;
|
||||
@@ -247,7 +302,9 @@ void CommandQueue::processMessages()
|
||||
{
|
||||
size_t numStateMachines;
|
||||
ArtboardHandle handle;
|
||||
RequestId requestId;
|
||||
m_messageStream >> handle;
|
||||
m_messageStream >> requestId;
|
||||
m_messageStream >> numStateMachines;
|
||||
std::vector<std::string> stateMachineNames(numStateMachines);
|
||||
for (auto& name : stateMachineNames)
|
||||
@@ -261,6 +318,7 @@ void CommandQueue::processMessages()
|
||||
{
|
||||
itr->second->onStateMachinesListed(
|
||||
itr->first,
|
||||
requestId,
|
||||
std::move(stateMachineNames));
|
||||
}
|
||||
|
||||
@@ -269,12 +327,14 @@ void CommandQueue::processMessages()
|
||||
case Message::fileDeleted:
|
||||
{
|
||||
FileHandle handle;
|
||||
RequestId requestId;
|
||||
m_messageStream >> handle;
|
||||
m_messageStream >> requestId;
|
||||
lock.unlock();
|
||||
auto itr = m_fileListeners.find(handle);
|
||||
if (itr != m_fileListeners.end())
|
||||
{
|
||||
itr->second->onFileDeleted(handle);
|
||||
itr->second->onFileDeleted(handle, requestId);
|
||||
m_fileListeners.erase(itr);
|
||||
}
|
||||
break;
|
||||
@@ -282,12 +342,14 @@ void CommandQueue::processMessages()
|
||||
case Message::artboardDeleted:
|
||||
{
|
||||
ArtboardHandle handle;
|
||||
RequestId requestId;
|
||||
m_messageStream >> handle;
|
||||
m_messageStream >> requestId;
|
||||
lock.unlock();
|
||||
auto itr = m_artboardListeners.find(handle);
|
||||
if (itr != m_artboardListeners.end())
|
||||
{
|
||||
itr->second->onArtboardDeleted(handle);
|
||||
itr->second->onArtboardDeleted(handle, requestId);
|
||||
m_artboardListeners.erase(itr);
|
||||
}
|
||||
break;
|
||||
@@ -295,12 +357,14 @@ void CommandQueue::processMessages()
|
||||
case Message::stateMachineDeleted:
|
||||
{
|
||||
StateMachineHandle handle;
|
||||
RequestId requestId;
|
||||
m_messageStream >> handle;
|
||||
m_messageStream >> requestId;
|
||||
lock.unlock();
|
||||
auto itr = m_stateMachineListeners.find(handle);
|
||||
if (itr != m_stateMachineListeners.end())
|
||||
{
|
||||
itr->second->onStateMachineDeleted(handle);
|
||||
itr->second->onStateMachineDeleted(handle, requestId);
|
||||
m_stateMachineListeners.erase(itr);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -94,12 +94,19 @@ bool CommandServer::processCommands()
|
||||
case CommandQueue::Command::loadFile:
|
||||
{
|
||||
FileHandle handle;
|
||||
RequestId requestId;
|
||||
std::vector<uint8_t> rivBytes;
|
||||
rcp<FileAssetLoader> loader;
|
||||
commandStream >> handle;
|
||||
commandStream >> requestId;
|
||||
commandStream >> loader;
|
||||
m_commandQueue->m_byteVectors >> rivBytes;
|
||||
lock.unlock();
|
||||
std::unique_ptr<rive::File> file =
|
||||
rive::File::import(rivBytes, m_factory);
|
||||
rive::File::import(rivBytes,
|
||||
m_factory,
|
||||
nullptr,
|
||||
std::move(loader));
|
||||
if (file != nullptr)
|
||||
{
|
||||
m_files[handle] = std::move(file);
|
||||
@@ -114,7 +121,9 @@ bool CommandServer::processCommands()
|
||||
case CommandQueue::Command::deleteFile:
|
||||
{
|
||||
FileHandle handle;
|
||||
RequestId requestId;
|
||||
commandStream >> handle;
|
||||
commandStream >> requestId;
|
||||
lock.unlock();
|
||||
m_files.erase(handle);
|
||||
std::unique_lock<std::mutex> messageLock(
|
||||
@@ -122,6 +131,7 @@ bool CommandServer::processCommands()
|
||||
m_commandQueue->m_messageStream
|
||||
<< CommandQueue::Message::fileDeleted;
|
||||
m_commandQueue->m_messageStream << handle;
|
||||
m_commandQueue->m_messageStream << requestId;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -129,9 +139,11 @@ bool CommandServer::processCommands()
|
||||
{
|
||||
ArtboardHandle handle;
|
||||
FileHandle fileHandle;
|
||||
RequestId requestId;
|
||||
std::string name;
|
||||
commandStream >> handle;
|
||||
commandStream >> fileHandle;
|
||||
commandStream >> requestId;
|
||||
m_commandQueue->m_names >> name;
|
||||
lock.unlock();
|
||||
if (rive::File* file = getFile(fileHandle))
|
||||
@@ -155,7 +167,9 @@ bool CommandServer::processCommands()
|
||||
case CommandQueue::Command::deleteArtboard:
|
||||
{
|
||||
ArtboardHandle handle;
|
||||
RequestId requestId;
|
||||
commandStream >> handle;
|
||||
commandStream >> requestId;
|
||||
lock.unlock();
|
||||
m_artboards.erase(handle);
|
||||
std::unique_lock<std::mutex> messageLock(
|
||||
@@ -163,6 +177,7 @@ bool CommandServer::processCommands()
|
||||
m_commandQueue->m_messageStream
|
||||
<< CommandQueue::Message::artboardDeleted;
|
||||
m_commandQueue->m_messageStream << handle;
|
||||
m_commandQueue->m_messageStream << requestId;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -170,9 +185,11 @@ bool CommandServer::processCommands()
|
||||
{
|
||||
StateMachineHandle handle;
|
||||
ArtboardHandle artboardHandle;
|
||||
RequestId requestId;
|
||||
std::string name;
|
||||
commandStream >> handle;
|
||||
commandStream >> artboardHandle;
|
||||
commandStream >> requestId;
|
||||
m_commandQueue->m_names >> name;
|
||||
lock.unlock();
|
||||
if (rive::ArtboardInstance* artboard =
|
||||
@@ -197,7 +214,9 @@ bool CommandServer::processCommands()
|
||||
case CommandQueue::Command::deleteStateMachine:
|
||||
{
|
||||
StateMachineHandle handle;
|
||||
RequestId requestId;
|
||||
commandStream >> handle;
|
||||
commandStream >> requestId;
|
||||
lock.unlock();
|
||||
m_stateMachines.erase(handle);
|
||||
std::unique_lock<std::mutex> messageLock(
|
||||
@@ -205,6 +224,7 @@ bool CommandServer::processCommands()
|
||||
m_commandQueue->m_messageStream
|
||||
<< CommandQueue::Message::stateMachineDeleted;
|
||||
m_commandQueue->m_messageStream << handle;
|
||||
m_commandQueue->m_messageStream << requestId;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -238,7 +258,9 @@ bool CommandServer::processCommands()
|
||||
case CommandQueue::Command::listArtboards:
|
||||
{
|
||||
FileHandle handle;
|
||||
RequestId requestId;
|
||||
commandStream >> handle;
|
||||
commandStream >> requestId;
|
||||
lock.unlock();
|
||||
auto file = getFile(handle);
|
||||
if (file)
|
||||
@@ -250,6 +272,7 @@ bool CommandServer::processCommands()
|
||||
m_commandQueue->m_messageStream
|
||||
<< CommandQueue::Message::artboardsListed;
|
||||
m_commandQueue->m_messageStream << handle;
|
||||
m_commandQueue->m_messageStream << requestId;
|
||||
m_commandQueue->m_messageStream << artboards.size();
|
||||
for (auto artboard : artboards)
|
||||
{
|
||||
@@ -263,7 +286,9 @@ bool CommandServer::processCommands()
|
||||
case CommandQueue::Command::listStateMachines:
|
||||
{
|
||||
ArtboardHandle handle;
|
||||
RequestId requestId;
|
||||
commandStream >> handle;
|
||||
commandStream >> requestId;
|
||||
lock.unlock();
|
||||
auto artboard = getArtboardInstance(handle);
|
||||
if (artboard)
|
||||
@@ -274,6 +299,7 @@ bool CommandServer::processCommands()
|
||||
m_commandQueue->m_messageStream
|
||||
<< CommandQueue::Message::stateMachinesListed;
|
||||
m_commandQueue->m_messageStream << handle;
|
||||
m_commandQueue->m_messageStream << requestId;
|
||||
m_commandQueue->m_messageStream << numStateMachines;
|
||||
for (int i = 0; i < numStateMachines; ++i)
|
||||
{
|
||||
|
||||
@@ -163,8 +163,8 @@ static Core* readRuntimeObject(BinaryReader& reader,
|
||||
return object;
|
||||
}
|
||||
|
||||
File::File(Factory* factory, FileAssetLoader* assetLoader) :
|
||||
m_factory(factory), m_assetLoader(assetLoader)
|
||||
File::File(Factory* factory, rcp<FileAssetLoader> assetLoader) :
|
||||
m_factory(factory), m_assetLoader(std::move(assetLoader))
|
||||
{
|
||||
assert(factory);
|
||||
}
|
||||
@@ -214,7 +214,7 @@ File::~File()
|
||||
std::unique_ptr<File> File::import(Span<const uint8_t> bytes,
|
||||
Factory* factory,
|
||||
ImportResult* result,
|
||||
FileAssetLoader* assetLoader)
|
||||
rcp<FileAssetLoader> assetLoader)
|
||||
{
|
||||
BinaryReader reader(bytes);
|
||||
RuntimeHeader header;
|
||||
@@ -241,7 +241,7 @@ std::unique_ptr<File> File::import(Span<const uint8_t> bytes,
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
auto file = rivestd::make_unique<File>(factory, assetLoader);
|
||||
auto file = rivestd::make_unique<File>(factory, std::move(assetLoader));
|
||||
|
||||
auto readResult = file->read(reader, header);
|
||||
if (result)
|
||||
|
||||
11
src/generated/text/text_input_base.cpp
Normal file
11
src/generated/text/text_input_base.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "rive/generated/text/text_input_base.hpp"
|
||||
#include "rive/text/text_input.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextInputBase::clone() const
|
||||
{
|
||||
auto cloned = new TextInput();
|
||||
cloned->copy(*this);
|
||||
return cloned;
|
||||
}
|
||||
11
src/generated/text/text_input_cursor_base.cpp
Normal file
11
src/generated/text/text_input_cursor_base.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "rive/generated/text/text_input_cursor_base.hpp"
|
||||
#include "rive/text/text_input_cursor.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextInputCursorBase::clone() const
|
||||
{
|
||||
auto cloned = new TextInputCursor();
|
||||
cloned->copy(*this);
|
||||
return cloned;
|
||||
}
|
||||
11
src/generated/text/text_input_selected_text_base.cpp
Normal file
11
src/generated/text/text_input_selected_text_base.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "rive/generated/text/text_input_selected_text_base.hpp"
|
||||
#include "rive/text/text_input_selected_text.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextInputSelectedTextBase::clone() const
|
||||
{
|
||||
auto cloned = new TextInputSelectedText();
|
||||
cloned->copy(*this);
|
||||
return cloned;
|
||||
}
|
||||
11
src/generated/text/text_input_selection_base.cpp
Normal file
11
src/generated/text/text_input_selection_base.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "rive/generated/text/text_input_selection_base.hpp"
|
||||
#include "rive/text/text_input_selection.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextInputSelectionBase::clone() const
|
||||
{
|
||||
auto cloned = new TextInputSelection();
|
||||
cloned->copy(*this);
|
||||
return cloned;
|
||||
}
|
||||
11
src/generated/text/text_input_text_base.cpp
Normal file
11
src/generated/text/text_input_text_base.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "rive/generated/text/text_input_text_base.hpp"
|
||||
#include "rive/text/text_input_text.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextInputTextBase::clone() const
|
||||
{
|
||||
auto cloned = new TextInputText();
|
||||
cloned->copy(*this);
|
||||
return cloned;
|
||||
}
|
||||
12
src/generated/text/text_style_paint_base.cpp
Normal file
12
src/generated/text/text_style_paint_base.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "rive/generated/text/text_style_paint_base.hpp"
|
||||
#include "rive/text/text_style_paint.hpp"
|
||||
#include "rive/text/text_variation_helper.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextStylePaintBase::clone() const
|
||||
{
|
||||
auto cloned = new TextStylePaint();
|
||||
cloned->copy(*this);
|
||||
return cloned;
|
||||
}
|
||||
@@ -8,9 +8,11 @@
|
||||
using namespace rive;
|
||||
|
||||
FileAssetImporter::FileAssetImporter(FileAsset* fileAsset,
|
||||
FileAssetLoader* assetLoader,
|
||||
rcp<FileAssetLoader> assetLoader,
|
||||
Factory* factory) :
|
||||
m_FileAsset(fileAsset), m_FileAssetLoader(assetLoader), m_Factory(factory)
|
||||
m_FileAsset(fileAsset),
|
||||
m_FileAssetLoader(std::move(assetLoader)),
|
||||
m_Factory(factory)
|
||||
{}
|
||||
|
||||
// if file asset contents are found when importing a rive file, store those for
|
||||
|
||||
16
src/node.cpp
16
src/node.cpp
@@ -1,5 +1,6 @@
|
||||
#include "rive/node.hpp"
|
||||
#include "rive/world_transform_component.hpp"
|
||||
#include "rive/layout_component.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
@@ -25,4 +26,17 @@ Mat2D Node::localTransform()
|
||||
m_LocalTransform = Mat2D();
|
||||
}
|
||||
return m_LocalTransform;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_RIVE_LAYOUT
|
||||
void Node::markLayoutNodeDirty()
|
||||
{
|
||||
for (ContainerComponent* p = parent(); p != nullptr; p = p->parent())
|
||||
{
|
||||
if (p->is<LayoutComponent>())
|
||||
{
|
||||
p->as<LayoutComponent>()->markLayoutNodeDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "rive/shapes/paint/fill.hpp"
|
||||
#include "rive/shapes/shape.hpp"
|
||||
#include "rive/artboard.hpp"
|
||||
#include "rive/factory.hpp"
|
||||
|
||||
#include "rive/core_context.hpp"
|
||||
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
#include "rive/foreground_layout_drawable.hpp"
|
||||
#include "rive/shapes/paint/stroke.hpp"
|
||||
#include "rive/shapes/shape.hpp"
|
||||
#include "rive/text/text_style.hpp"
|
||||
#include "rive/text/text_style_paint.hpp"
|
||||
#include "rive/text/text_input_selected_text.hpp"
|
||||
#include "rive/text/text_input_cursor.hpp"
|
||||
#include "rive/text/text_input_selection.hpp"
|
||||
#include "rive/text/text_input_text.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
@@ -20,10 +24,18 @@ ShapePaintContainer* ShapePaintContainer::from(Component* component)
|
||||
return component->as<LayoutComponent>();
|
||||
case Shape::typeKey:
|
||||
return component->as<Shape>();
|
||||
case TextStyle::typeKey:
|
||||
return component->as<TextStyle>();
|
||||
case TextStylePaint::typeKey:
|
||||
return component->as<TextStylePaint>();
|
||||
case ForegroundLayoutDrawable::typeKey:
|
||||
return component->as<ForegroundLayoutDrawable>();
|
||||
case TextInputCursor::typeKey:
|
||||
return component->as<TextInputCursor>();
|
||||
case TextInputSelection::typeKey:
|
||||
return component->as<TextInputSelection>();
|
||||
case TextInputText::typeKey:
|
||||
return component->as<TextInputText>();
|
||||
case TextInputSelectedText::typeKey:
|
||||
return component->as<TextInputSelectedText>();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ void RawTextInput::buildTextPaths(Factory* factory)
|
||||
}
|
||||
}
|
||||
|
||||
AABB RawTextInput::bounds() { return m_shape.bounds(); }
|
||||
AABB RawTextInput::bounds() const { return m_shape.bounds(); }
|
||||
|
||||
void RawTextInput::paragraphSpacing(float value)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ using namespace rive;
|
||||
#include "rive/component_dirt.hpp"
|
||||
#include "rive/math/rectangles_to_contour.hpp"
|
||||
#include "rive/math/transform_components.hpp"
|
||||
#include "rive/text/text_style.hpp"
|
||||
#include "rive/text/text_style_paint.hpp"
|
||||
#include "rive/text/text_value_run.hpp"
|
||||
#include "rive/text/text_modifier_group.hpp"
|
||||
#include "rive/shapes/paint/shape_paint.hpp"
|
||||
@@ -59,7 +59,7 @@ TextSizing Text::effectiveSizing() const
|
||||
|
||||
void Text::clearRenderStyles()
|
||||
{
|
||||
for (TextStyle* style : m_renderStyles)
|
||||
for (TextStylePaint* style : m_renderStyles)
|
||||
{
|
||||
style->rewindPath();
|
||||
}
|
||||
@@ -389,7 +389,7 @@ void Text::buildRenderStyles()
|
||||
|
||||
assert(run->styleId < m_runs.size());
|
||||
TextValueRun* textValueRun = m_runs[run->styleId];
|
||||
TextStyle* style = textValueRun->style();
|
||||
TextStylePaint* style = textValueRun->style();
|
||||
// TextValueRun::onAddedDirty botches loading if it cannot
|
||||
// resolve a style, so we're confident we have a style here.
|
||||
assert(style != nullptr);
|
||||
@@ -495,7 +495,7 @@ skipLines:
|
||||
}
|
||||
}
|
||||
|
||||
const TextStyle* Text::styleFromShaperId(uint16_t id) const
|
||||
const TextStylePaint* Text::styleFromShaperId(uint16_t id) const
|
||||
{
|
||||
assert(id < m_runs.size());
|
||||
return m_runs[id]->style();
|
||||
@@ -536,6 +536,8 @@ void Text::addModifierGroup(TextModifierGroup* group)
|
||||
m_modifierGroups.push_back(group);
|
||||
}
|
||||
|
||||
void Text::markShapeDirty() { markShapeDirty(true); }
|
||||
|
||||
void Text::markShapeDirty(bool sendToLayout)
|
||||
{
|
||||
addDirt(ComponentDirt::Path);
|
||||
@@ -552,19 +554,6 @@ void Text::markShapeDirty(bool sendToLayout)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_RIVE_LAYOUT
|
||||
void Text::markLayoutNodeDirty()
|
||||
{
|
||||
for (ContainerComponent* p = parent(); p != nullptr; p = p->parent())
|
||||
{
|
||||
if (p->is<LayoutComponent>())
|
||||
{
|
||||
p->as<LayoutComponent>()->markLayoutNodeDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Text::modifierShapeDirty() { addDirt(ComponentDirt::Path); }
|
||||
|
||||
void Text::markPaintDirty() { addDirt(ComponentDirt::Paint); }
|
||||
@@ -717,7 +706,7 @@ void Text::onDirty(ComponentDirt value)
|
||||
}
|
||||
if (hasDirt(value, ComponentDirt::Path | ComponentDirt::Paint))
|
||||
{
|
||||
for (TextStyle* style : m_renderStyles)
|
||||
for (TextStylePaint* style : m_renderStyles)
|
||||
{
|
||||
style->invalidateStrokeEffects();
|
||||
}
|
||||
@@ -808,7 +797,7 @@ void Text::update(ComponentDirt value)
|
||||
{
|
||||
// Note that buildRenderStyles does this too, which is why we can get
|
||||
// away doing this in the else.
|
||||
for (TextStyle* style : m_renderStyles)
|
||||
for (TextStylePaint* style : m_renderStyles)
|
||||
{
|
||||
style->propagateOpacity(renderOpacity());
|
||||
}
|
||||
@@ -963,6 +952,7 @@ Core* Text::hitTest(HitInfo*, const Mat2D&) { return nullptr; }
|
||||
void Text::addRun(TextValueRun* run) {}
|
||||
void Text::addModifierGroup(TextModifierGroup* group) {}
|
||||
void Text::markShapeDirty(bool sendToLayout) {}
|
||||
void Text::markShapeDirty() {}
|
||||
void Text::update(ComponentDirt value) {}
|
||||
void Text::onDirty(ComponentDirt value) {}
|
||||
void Text::alignValueChanged() {}
|
||||
@@ -973,7 +963,10 @@ void Text::heightChanged() {}
|
||||
void Text::markPaintDirty() {}
|
||||
void Text::modifierShapeDirty() {}
|
||||
bool Text::modifierRangesNeedShape() const { return false; }
|
||||
const TextStyle* Text::styleFromShaperId(uint16_t id) const { return nullptr; }
|
||||
const TextStylePaint* Text::styleFromShaperId(uint16_t id) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
void Text::paragraphSpacingChanged() {}
|
||||
AABB Text::localBounds() const { return AABB(); }
|
||||
void Text::originValueChanged() {}
|
||||
|
||||
112
src/text/text_input.cpp
Normal file
112
src/text/text_input.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "rive/text/text_input.hpp"
|
||||
#include "rive/text/text_style.hpp"
|
||||
#include "rive/text/text_input_drawable.hpp"
|
||||
#include "rive/math/mat2d.hpp"
|
||||
#include "rive/artboard.hpp"
|
||||
#include "rive/factory.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
void TextInput::draw(Renderer* renderer) {}
|
||||
|
||||
Core* TextInput::hitTest(HitInfo*, const Mat2D&) { return nullptr; }
|
||||
|
||||
void TextInput::textChanged()
|
||||
{
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
m_rawTextInput.text(m_Text);
|
||||
#endif
|
||||
}
|
||||
void TextInput::selectionRadiusChanged() {}
|
||||
|
||||
void TextInput::markPaintDirty() { addDirt(ComponentDirt::Paint); }
|
||||
|
||||
void TextInput::markShapeDirty() { addDirt(ComponentDirt::TextShape); }
|
||||
|
||||
AABB TextInput::localBounds() const
|
||||
{
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
return m_rawTextInput.bounds();
|
||||
#else
|
||||
return AABB();
|
||||
#endif
|
||||
}
|
||||
|
||||
StatusCode TextInput::onAddedClean(CoreContext* context)
|
||||
{
|
||||
Super::onAddedClean(context);
|
||||
|
||||
m_textStyle = children<TextStyle>().first();
|
||||
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
if (m_textStyle != nullptr && m_textStyle->font() != nullptr)
|
||||
{
|
||||
m_rawTextInput.font(m_textStyle->font());
|
||||
}
|
||||
m_rawTextInput.text(m_Text);
|
||||
#endif
|
||||
return m_textStyle == nullptr ? StatusCode::MissingObject : StatusCode::Ok;
|
||||
}
|
||||
|
||||
void TextInput::update(ComponentDirt value)
|
||||
{
|
||||
Super::update(value);
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
if (hasDirt(value, ComponentDirt::Paint | ComponentDirt::TextShape))
|
||||
{
|
||||
Factory* factory = artboard()->factory();
|
||||
RawTextInput::Flags changed = m_rawTextInput.update(factory);
|
||||
if ((changed & RawTextInput::Flags::shapeDirty) != 0)
|
||||
{
|
||||
m_worldBounds =
|
||||
worldTransform().mapBoundingBox(m_rawTextInput.bounds());
|
||||
|
||||
#ifdef WITH_RIVE_LAYOUT
|
||||
if (m_rawTextInput.sizing() == TextSizing::autoHeight)
|
||||
{
|
||||
markLayoutNodeDirty();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if ((changed & RawTextInput::Flags::selectionDirty) != 0)
|
||||
{
|
||||
for (auto child : children<TextInputDrawable>())
|
||||
{
|
||||
child->invalidateStrokeEffects();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Vec2D TextInput::measureLayout(float width,
|
||||
LayoutMeasureMode widthMode,
|
||||
float height,
|
||||
LayoutMeasureMode heightMode)
|
||||
{
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
AABB bounds =
|
||||
m_rawTextInput.measure(widthMode == LayoutMeasureMode::undefined
|
||||
? std::numeric_limits<float>::max()
|
||||
: width,
|
||||
heightMode == LayoutMeasureMode::undefined
|
||||
? std::numeric_limits<float>::max()
|
||||
: height);
|
||||
return bounds.size();
|
||||
#else
|
||||
return Vec2D();
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextInput::controlSize(Vec2D size,
|
||||
LayoutScaleType widthScaleType,
|
||||
LayoutScaleType heightScaleType,
|
||||
LayoutDirection direction)
|
||||
{
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
m_rawTextInput.maxWidth(size.x);
|
||||
m_rawTextInput.sizing(TextSizing::autoHeight);
|
||||
|
||||
addDirt(ComponentDirt::TextShape);
|
||||
#endif
|
||||
}
|
||||
16
src/text/text_input_cursor.cpp
Normal file
16
src/text/text_input_cursor.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "rive/text/text_input_cursor.hpp"
|
||||
#include "rive/math/mat2d.hpp"
|
||||
#include "rive/text/text_input.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextInputCursor::hitTest(HitInfo*, const Mat2D&) { return nullptr; }
|
||||
|
||||
ShapePaintPath* TextInputCursor::localClockwisePath()
|
||||
{
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
return textInput()->rawTextInput()->cursorPath();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
64
src/text/text_input_drawable.cpp
Normal file
64
src/text/text_input_drawable.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "rive/text/text_input_drawable.hpp"
|
||||
#include "rive/text/text_input.hpp"
|
||||
#include "rive/shapes/paint/shape_paint.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
TextInput* TextInputDrawable::textInput() const
|
||||
{
|
||||
return parent()->as<TextInput>();
|
||||
}
|
||||
|
||||
ShapePaintPath* TextInputDrawable::worldPath()
|
||||
{
|
||||
RIVE_UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StatusCode TextInputDrawable::onAddedClean(CoreContext* context)
|
||||
{
|
||||
if (!parent()->is<TextInput>())
|
||||
{
|
||||
return StatusCode::InvalidObject;
|
||||
}
|
||||
|
||||
return StatusCode::Ok;
|
||||
}
|
||||
|
||||
const Mat2D& TextInputDrawable::shapeWorldTransform() const
|
||||
{
|
||||
return worldTransform();
|
||||
}
|
||||
|
||||
void TextInputDrawable::draw(Renderer* renderer)
|
||||
{
|
||||
if (renderOpacity() == 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ClipResult clipResult = applyClip(renderer);
|
||||
|
||||
if (clipResult != ClipResult::emptyClip)
|
||||
{
|
||||
for (auto shapePaint : m_ShapePaints)
|
||||
{
|
||||
if (!shapePaint->isVisible())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto shapePaintPath = shapePaint->pickPath(this);
|
||||
if (shapePaintPath == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
shapePaint->draw(renderer,
|
||||
shapePaintPath,
|
||||
textInput()->worldTransform());
|
||||
}
|
||||
}
|
||||
|
||||
if (clipResult != ClipResult::noClip)
|
||||
{
|
||||
renderer->restore();
|
||||
}
|
||||
}
|
||||
16
src/text/text_input_selected_text.cpp
Normal file
16
src/text/text_input_selected_text.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "rive/text/text_input_selected_text.hpp"
|
||||
#include "rive/math/mat2d.hpp"
|
||||
#include "rive/text/text_input.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextInputSelectedText::hitTest(HitInfo*, const Mat2D&) { return nullptr; }
|
||||
|
||||
ShapePaintPath* TextInputSelectedText::localClockwisePath()
|
||||
{
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
return textInput()->rawTextInput()->selectedTextPath();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
16
src/text/text_input_selection.cpp
Normal file
16
src/text/text_input_selection.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "rive/text/text_input_selection.hpp"
|
||||
#include "rive/math/mat2d.hpp"
|
||||
#include "rive/text/text_input.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextInputSelection::hitTest(HitInfo*, const Mat2D&) { return nullptr; }
|
||||
|
||||
ShapePaintPath* TextInputSelection::localClockwisePath()
|
||||
{
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
return textInput()->rawTextInput()->selectionPath();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
16
src/text/text_input_text.cpp
Normal file
16
src/text/text_input_text.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "rive/text/text_input_text.hpp"
|
||||
#include "rive/math/mat2d.hpp"
|
||||
#include "rive/text/text_input.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
Core* TextInputText::hitTest(HitInfo*, const Mat2D&) { return nullptr; }
|
||||
|
||||
ShapePaintPath* TextInputText::localClockwisePath()
|
||||
{
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
return textInput()->rawTextInput()->textPath();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
23
src/text/text_interface.cpp
Normal file
23
src/text/text_interface.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "rive/text/text_interface.hpp"
|
||||
#include "rive/text/text_input.hpp"
|
||||
#include "rive/text/text.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
TextInterface* TextInterface::from(Core* component)
|
||||
{
|
||||
if (component == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
switch (component->coreType())
|
||||
{
|
||||
case Text::typeKey:
|
||||
return component->as<Text>();
|
||||
break;
|
||||
case TextInput::typeKey:
|
||||
return component->as<TextInput>();
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "rive/text/text_shape_modifier.hpp"
|
||||
#include "rive/text/text_modifier_range.hpp"
|
||||
#include "rive/text/glyph_lookup.hpp"
|
||||
#include "rive/text/text_style.hpp"
|
||||
#include "rive/text/text_style_paint.hpp"
|
||||
#include "rive/artboard.hpp"
|
||||
#include <limits>
|
||||
|
||||
@@ -288,7 +288,7 @@ TextRun TextModifierGroup::modifyShape(const Text& text,
|
||||
TextRun run,
|
||||
float strength)
|
||||
{
|
||||
const TextStyle* style = text.styleFromShaperId(run.styleId);
|
||||
const TextStylePaint* style = text.styleFromShaperId(run.styleId);
|
||||
if (style == nullptr || style->font() == nullptr)
|
||||
{
|
||||
return run;
|
||||
|
||||
@@ -1,43 +1,18 @@
|
||||
#include "rive/text/text_style.hpp"
|
||||
#include "rive/text/text_style_axis.hpp"
|
||||
#include "rive/text/text_style_feature.hpp"
|
||||
#include "rive/text/text_variation_helper.hpp"
|
||||
#include "rive/renderer.hpp"
|
||||
#include "rive/shapes/paint/feather.hpp"
|
||||
#include "rive/shapes/paint/shape_paint.hpp"
|
||||
#include "rive/backboard.hpp"
|
||||
#include "rive/importers/backboard_importer.hpp"
|
||||
#include "rive/text/text.hpp"
|
||||
#include "rive/artboard.hpp"
|
||||
#include "rive/factory.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
namespace rive
|
||||
{
|
||||
class TextVariationHelper : public Component
|
||||
{
|
||||
public:
|
||||
TextVariationHelper(TextStyle* style) : m_textStyle(style) {}
|
||||
TextStyle* style() const { return m_textStyle; }
|
||||
void buildDependencies() override
|
||||
{
|
||||
auto text = m_textStyle->parent();
|
||||
text->artboard()->addDependent(this);
|
||||
addDependent(text);
|
||||
}
|
||||
|
||||
void update(ComponentDirt value) override
|
||||
{
|
||||
m_textStyle->updateVariableFont();
|
||||
}
|
||||
|
||||
private:
|
||||
TextStyle* m_textStyle;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
// satisfy unique_ptr
|
||||
TextStyle::TextStyle() : m_path(true, FillRule::clockwise) {}
|
||||
TextStyle::TextStyle() = default;
|
||||
|
||||
void TextStyle::addVariation(TextStyleAxis* axis)
|
||||
{
|
||||
@@ -53,7 +28,7 @@ void TextStyle::onDirty(ComponentDirt dirt)
|
||||
{
|
||||
if ((dirt & ComponentDirt::TextShape) == ComponentDirt::TextShape)
|
||||
{
|
||||
parent()->as<Text>()->markShapeDirty();
|
||||
m_text->markShapeDirty();
|
||||
if (m_variationHelper != nullptr)
|
||||
{
|
||||
m_variationHelper->addDirt(ComponentDirt::TextShape);
|
||||
@@ -63,6 +38,9 @@ void TextStyle::onDirty(ComponentDirt dirt)
|
||||
|
||||
StatusCode TextStyle::onAddedClean(CoreContext* context)
|
||||
{
|
||||
// We know this is good because we validated it during validate().
|
||||
m_text = TextInterface::from(parent());
|
||||
|
||||
auto code = Super::onAddedClean(context);
|
||||
if (code != StatusCode::Ok)
|
||||
{
|
||||
@@ -138,94 +116,6 @@ void TextStyle::buildDependencies()
|
||||
Super::buildDependencies();
|
||||
}
|
||||
|
||||
void TextStyle::rewindPath()
|
||||
{
|
||||
m_path.rewind();
|
||||
m_hasContents = false;
|
||||
m_opacityPaths.clear();
|
||||
}
|
||||
|
||||
bool TextStyle::addPath(const RawPath& rawPath, float opacity)
|
||||
{
|
||||
bool hadContents = m_hasContents;
|
||||
m_hasContents = true;
|
||||
if (opacity > 0.0f)
|
||||
{
|
||||
|
||||
// m_path contains everything, so inner feather bounds can work.
|
||||
m_path.addPathClockwise(rawPath);
|
||||
|
||||
// Bucket by opacity
|
||||
auto itr = m_opacityPaths.find(opacity);
|
||||
ShapePaintPath* shapePaintPath = nullptr;
|
||||
if (itr != m_opacityPaths.end())
|
||||
{
|
||||
ShapePaintPath& path = itr->second;
|
||||
shapePaintPath = &path;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_opacityPaths[opacity] = ShapePaintPath(true, FillRule::clockwise);
|
||||
shapePaintPath = &m_opacityPaths.at(opacity);
|
||||
}
|
||||
shapePaintPath->addPathClockwise(rawPath);
|
||||
}
|
||||
|
||||
return !hadContents;
|
||||
}
|
||||
|
||||
void TextStyle::draw(Renderer* renderer, const Mat2D& worldTransform)
|
||||
{
|
||||
for (auto shapePaint : m_ShapePaints)
|
||||
{
|
||||
if (!shapePaint->shouldDraw())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
shapePaint->blendMode(parent()->as<Text>()->blendMode());
|
||||
|
||||
// For blend modes to work, opaque paths render first
|
||||
auto itr = m_opacityPaths.find(1.0f);
|
||||
if (itr != m_opacityPaths.end())
|
||||
{
|
||||
ShapePaintPath& path = itr->second;
|
||||
shapePaint->draw(renderer, &path, worldTransform, true);
|
||||
}
|
||||
|
||||
if (m_paintPool.size() < m_opacityPaths.size())
|
||||
{
|
||||
m_paintPool.reserve(m_opacityPaths.size());
|
||||
Factory* factory = artboard()->factory();
|
||||
while (m_paintPool.size() < m_opacityPaths.size())
|
||||
{
|
||||
m_paintPool.emplace_back(factory->makeRenderPaint());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t paintIndex = 0;
|
||||
for (itr = m_opacityPaths.begin(); itr != m_opacityPaths.end(); itr++)
|
||||
{
|
||||
// Don't render opaque paths twice
|
||||
if (itr->first == 1.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
RenderPaint* renderPaint = m_paintPool[paintIndex++].get();
|
||||
shapePaint->applyTo(renderPaint, itr->first);
|
||||
if (auto feather = shapePaint->feather())
|
||||
{
|
||||
renderPaint->feather(feather->strength());
|
||||
}
|
||||
ShapePaintPath& path = itr->second;
|
||||
shapePaint->draw(renderer,
|
||||
&path,
|
||||
worldTransform,
|
||||
true,
|
||||
renderPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TextStyle::assetId() { return this->fontAssetId(); }
|
||||
|
||||
void TextStyle::setAsset(FileAsset* asset)
|
||||
@@ -246,14 +136,11 @@ StatusCode TextStyle::import(ImportStack& importStack)
|
||||
return Super::import(importStack);
|
||||
}
|
||||
|
||||
void TextStyle::fontSizeChanged() { parent()->as<Text>()->markShapeDirty(); }
|
||||
void TextStyle::fontSizeChanged() { m_text->markShapeDirty(); }
|
||||
|
||||
void TextStyle::lineHeightChanged() { parent()->as<Text>()->markShapeDirty(); }
|
||||
void TextStyle::lineHeightChanged() { m_text->markShapeDirty(); }
|
||||
|
||||
void TextStyle::letterSpacingChanged()
|
||||
{
|
||||
parent()->as<Text>()->markShapeDirty();
|
||||
}
|
||||
void TextStyle::letterSpacingChanged() { m_text->markShapeDirty(); }
|
||||
|
||||
Core* TextStyle::clone() const
|
||||
{
|
||||
@@ -266,9 +153,7 @@ Core* TextStyle::clone() const
|
||||
return twin;
|
||||
}
|
||||
|
||||
const Mat2D& TextStyle::shapeWorldTransform() const
|
||||
bool TextStyle::validate(CoreContext* context)
|
||||
{
|
||||
return parent()->as<Text>()->shapeWorldTransform();
|
||||
}
|
||||
|
||||
Component* TextStyle::pathBuilder() { return parent(); }
|
||||
return TextInterface::from(context->resolve(parentId())) != nullptr;
|
||||
}
|
||||
117
src/text/text_style_paint.cpp
Normal file
117
src/text/text_style_paint.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "rive/text/text_style_paint.hpp"
|
||||
#include "rive/text/text.hpp"
|
||||
#include "rive/text/text_variation_helper.hpp"
|
||||
#include "rive/shapes/paint/shape_paint.hpp"
|
||||
#include "rive/shapes/paint/feather.hpp"
|
||||
#include "rive/artboard.hpp"
|
||||
#include "rive/factory.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
TextStylePaint::TextStylePaint() : m_path(true, FillRule::clockwise) {}
|
||||
|
||||
void TextStylePaint::rewindPath()
|
||||
{
|
||||
m_path.rewind();
|
||||
m_hasContents = false;
|
||||
m_opacityPaths.clear();
|
||||
}
|
||||
|
||||
bool TextStylePaint::addPath(const RawPath& rawPath, float opacity)
|
||||
{
|
||||
bool hadContents = m_hasContents;
|
||||
m_hasContents = true;
|
||||
if (opacity > 0.0f)
|
||||
{
|
||||
|
||||
// m_path contains everything, so inner feather bounds can work.
|
||||
m_path.addPathClockwise(rawPath);
|
||||
|
||||
// Bucket by opacity
|
||||
auto itr = m_opacityPaths.find(opacity);
|
||||
ShapePaintPath* shapePaintPath = nullptr;
|
||||
if (itr != m_opacityPaths.end())
|
||||
{
|
||||
ShapePaintPath& path = itr->second;
|
||||
shapePaintPath = &path;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_opacityPaths[opacity] = ShapePaintPath(true, FillRule::clockwise);
|
||||
shapePaintPath = &m_opacityPaths.at(opacity);
|
||||
}
|
||||
shapePaintPath->addPathClockwise(rawPath);
|
||||
}
|
||||
|
||||
return !hadContents;
|
||||
}
|
||||
|
||||
void TextStylePaint::draw(Renderer* renderer, const Mat2D& worldTransform)
|
||||
{
|
||||
for (auto shapePaint : m_ShapePaints)
|
||||
{
|
||||
if (!shapePaint->shouldDraw())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
shapePaint->blendMode(parent()->as<Text>()->blendMode());
|
||||
|
||||
// For blend modes to work, opaque paths render first
|
||||
auto itr = m_opacityPaths.find(1.0f);
|
||||
if (itr != m_opacityPaths.end())
|
||||
{
|
||||
ShapePaintPath& path = itr->second;
|
||||
shapePaint->draw(renderer, &path, worldTransform, true);
|
||||
}
|
||||
|
||||
if (m_paintPool.size() < m_opacityPaths.size())
|
||||
{
|
||||
m_paintPool.reserve(m_opacityPaths.size());
|
||||
Factory* factory = artboard()->factory();
|
||||
while (m_paintPool.size() < m_opacityPaths.size())
|
||||
{
|
||||
m_paintPool.emplace_back(factory->makeRenderPaint());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t paintIndex = 0;
|
||||
for (itr = m_opacityPaths.begin(); itr != m_opacityPaths.end(); itr++)
|
||||
{
|
||||
// Don't render opaque paths twice
|
||||
if (itr->first == 1.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
RenderPaint* renderPaint = m_paintPool[paintIndex++].get();
|
||||
shapePaint->applyTo(renderPaint, itr->first);
|
||||
if (auto feather = shapePaint->feather())
|
||||
{
|
||||
renderPaint->feather(feather->strength());
|
||||
}
|
||||
ShapePaintPath& path = itr->second;
|
||||
shapePaint->draw(renderer,
|
||||
&path,
|
||||
worldTransform,
|
||||
true,
|
||||
renderPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Mat2D& TextStylePaint::shapeWorldTransform() const
|
||||
{
|
||||
return parent()->as<Text>()->shapeWorldTransform();
|
||||
}
|
||||
|
||||
Component* TextStylePaint::pathBuilder() { return parent(); }
|
||||
|
||||
Core* TextStylePaint::clone() const
|
||||
{
|
||||
TextStylePaint* twin = TextStylePaintBase::clone()->as<TextStylePaint>();
|
||||
if (m_fileAsset != nullptr)
|
||||
{
|
||||
twin->setAsset(m_fileAsset);
|
||||
}
|
||||
|
||||
return twin;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "rive/core_context.hpp"
|
||||
#include "rive/text/text.hpp"
|
||||
#include "rive/text/text_style.hpp"
|
||||
#include "rive/text/text_style_paint.hpp"
|
||||
#include "rive/text/text_value_run.hpp"
|
||||
#include "rive/artboard.hpp"
|
||||
#include "rive/hittest_command_path.hpp"
|
||||
@@ -41,12 +41,12 @@ StatusCode TextValueRun::onAddedDirty(CoreContext* context)
|
||||
return code;
|
||||
}
|
||||
auto coreObject = context->resolve(styleId());
|
||||
if (coreObject == nullptr || !coreObject->is<TextStyle>())
|
||||
if (coreObject == nullptr || !coreObject->is<TextStylePaint>())
|
||||
{
|
||||
return StatusCode::MissingObject;
|
||||
}
|
||||
|
||||
m_style = static_cast<TextStyle*>(coreObject);
|
||||
m_style = static_cast<TextStylePaint*>(coreObject);
|
||||
|
||||
return StatusCode::Ok;
|
||||
}
|
||||
@@ -54,9 +54,9 @@ StatusCode TextValueRun::onAddedDirty(CoreContext* context)
|
||||
void TextValueRun::styleIdChanged()
|
||||
{
|
||||
auto coreObject = artboard()->resolve(styleId());
|
||||
if (coreObject != nullptr && coreObject->is<TextStyle>())
|
||||
if (coreObject != nullptr && coreObject->is<TextStylePaint>())
|
||||
{
|
||||
m_style = static_cast<TextStyle*>(coreObject);
|
||||
m_style = static_cast<TextStylePaint*>(coreObject);
|
||||
parent()->as<Text>()->markShapeDirty();
|
||||
}
|
||||
}
|
||||
|
||||
17
src/text/text_variation_helper.cpp
Normal file
17
src/text/text_variation_helper.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "rive/text/text_variation_helper.hpp"
|
||||
#include "rive/text/text_style.hpp"
|
||||
#include "rive/artboard.hpp"
|
||||
|
||||
using namespace rive;
|
||||
|
||||
void TextVariationHelper::buildDependencies()
|
||||
{
|
||||
auto text = m_textStyle->parent();
|
||||
text->artboard()->addDependent(this);
|
||||
addDependent(text);
|
||||
}
|
||||
|
||||
void TextVariationHelper::update(ComponentDirt value)
|
||||
{
|
||||
m_textStyle->updateVariableFont();
|
||||
}
|
||||
@@ -61,6 +61,7 @@ class SimpleFileListener : public CommandQueue::FileListener
|
||||
public:
|
||||
virtual void onArtboardsListed(
|
||||
const FileHandle fileHandle,
|
||||
RequestId requestId,
|
||||
std::vector<std::string> artboardNames) override
|
||||
{
|
||||
// we can guarantee that this is the only listener that will receive
|
||||
@@ -76,6 +77,7 @@ class SimpleArtboardListener : public CommandQueue::ArtboardListener
|
||||
public:
|
||||
virtual void onStateMachinesListed(
|
||||
const ArtboardHandle fileHandle,
|
||||
RequestId requestId,
|
||||
std::vector<std::string> stateMachineNames) override
|
||||
{
|
||||
// we can guarantee that this is the only listener that will receive
|
||||
@@ -106,6 +108,16 @@ static void input_thread(rcp<CommandQueue> commandQueue)
|
||||
commandQueue->disconnect();
|
||||
}
|
||||
|
||||
class DefaultFileAssetLoader : public rive::FileAssetLoader
|
||||
{
|
||||
virtual bool loadContents(FileAsset& asset,
|
||||
Span<const uint8_t> inBandBytes,
|
||||
Factory* factory)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// this is a seperate thread for testing, it could just as easily be in
|
||||
// input_thread or the main thread
|
||||
static void draw_thread(rcp<CommandQueue> commandQueue)
|
||||
@@ -114,8 +126,12 @@ static void draw_thread(rcp<CommandQueue> commandQueue)
|
||||
SimpleArtboardListener aListener;
|
||||
SimpleStateMachineListener stmListener;
|
||||
|
||||
FileHandle fileHandle =
|
||||
commandQueue->loadFile(std::move(rivBytes), &fListener);
|
||||
rcp<DefaultFileAssetLoader> defaultLoader =
|
||||
make_rcp<DefaultFileAssetLoader>();
|
||||
|
||||
FileHandle fileHandle = commandQueue->loadFile(std::move(rivBytes),
|
||||
defaultLoader.get(),
|
||||
&fListener);
|
||||
|
||||
ArtboardHandle artboardHandle =
|
||||
commandQueue->instantiateDefaultArtboard(fileHandle, &aListener);
|
||||
|
||||
BIN
tests/unit_tests/assets/text_input.riv
Normal file
BIN
tests/unit_tests/assets/text_input.riv
Normal file
Binary file not shown.
41
tests/unit_tests/runtime/child_iterator_test.cpp
Normal file
41
tests/unit_tests/runtime/child_iterator_test.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "rive/file.hpp"
|
||||
#include "rive/shapes/paint/shape_paint.hpp"
|
||||
#include "rive_file_reader.hpp"
|
||||
#include <catch.hpp>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
using namespace rive;
|
||||
|
||||
TEST_CASE("child typed iterators work", "[iterators]")
|
||||
{
|
||||
auto file = ReadRiveFile("assets/juice.riv");
|
||||
|
||||
auto artboard = file->artboardDefault();
|
||||
|
||||
// Expect only one node.
|
||||
size_t count = 0;
|
||||
for (auto child : artboard->children<Node>())
|
||||
{
|
||||
CHECK(child->name() == "root");
|
||||
count++;
|
||||
}
|
||||
CHECK(count == 1);
|
||||
|
||||
size_t shapePaintCount = 0;
|
||||
for (auto child : artboard->children<ShapePaint>())
|
||||
{
|
||||
shapePaintCount++;
|
||||
CHECK(!child->isTranslucent());
|
||||
}
|
||||
CHECK(shapePaintCount == 1);
|
||||
|
||||
count = 0;
|
||||
auto allShapePaints = artboard->objects<ShapePaint>();
|
||||
for (auto itr = allShapePaints.begin(); itr != allShapePaints.end(); ++itr)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
CHECK(allShapePaints.size() == 37);
|
||||
CHECK(allShapePaints.size() == count);
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "rive/animation/state_machine_instance.hpp"
|
||||
#include "rive/command_queue.hpp"
|
||||
#include "rive/command_server.hpp"
|
||||
#include "rive/file.hpp"
|
||||
#include "common/render_context_null.hpp"
|
||||
#include <fstream>
|
||||
|
||||
@@ -35,6 +36,35 @@ static void wait_for_server(CommandQueue* commandQueue)
|
||||
cv.wait(lock);
|
||||
}
|
||||
|
||||
class TestPODStream : public RefCnt<TestPODStream>
|
||||
{
|
||||
public:
|
||||
static constexpr int MAG_NUMBER = 0x99;
|
||||
int m_number = MAG_NUMBER;
|
||||
};
|
||||
|
||||
TEST_CASE("POD Stream RCP", "[PODStream]")
|
||||
{
|
||||
PODStream stream;
|
||||
rcp<TestPODStream> t1 = make_rcp<TestPODStream>();
|
||||
TestPODStream* orig = t1.get();
|
||||
stream << t1;
|
||||
|
||||
CHECK(t1.get() != nullptr);
|
||||
CHECK(t1.get() == orig);
|
||||
|
||||
rcp<TestPODStream> t2;
|
||||
stream >> t2;
|
||||
CHECK(t2.get() == orig);
|
||||
CHECK(t2->m_number == TestPODStream::MAG_NUMBER);
|
||||
|
||||
rcp<TestPODStream> t3;
|
||||
stream << t3;
|
||||
rcp<TestPODStream> t4;
|
||||
stream >> t4;
|
||||
CHECK(t4.get() == nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("artboard management", "[CommandQueue]")
|
||||
{
|
||||
auto commandQueue = make_rcp<CommandQueue>();
|
||||
@@ -486,13 +516,106 @@ TEST_CASE("disconnect", "[CommandQueue]")
|
||||
CHECK(!server.processCommands());
|
||||
}
|
||||
|
||||
static constexpr uint32_t MAGIC_NUMBER = 0x50;
|
||||
|
||||
class TestFileAssetLoader : public FileAssetLoader
|
||||
{
|
||||
public:
|
||||
virtual bool loadContents(FileAsset& asset,
|
||||
Span<const uint8_t> inBandBytes,
|
||||
Factory* factory)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t m_magicNumber = MAGIC_NUMBER;
|
||||
};
|
||||
|
||||
TEST_CASE("load file with asset loader", "[CommandQueue]")
|
||||
{
|
||||
auto commandQueue = make_rcp<CommandQueue>();
|
||||
std::unique_ptr<gpu::RenderContext> nullContext =
|
||||
RenderContextNULL::MakeContext();
|
||||
|
||||
CommandServer server(commandQueue, nullContext.get());
|
||||
rcp<TestFileAssetLoader> loader = make_rcp<TestFileAssetLoader>();
|
||||
|
||||
std::ifstream stream("assets/entry.riv", std::ios::binary);
|
||||
FileHandle fileHandle = commandQueue->loadFile(
|
||||
std::vector<uint8_t>(std::istreambuf_iterator<char>(stream), {}),
|
||||
loader);
|
||||
|
||||
CHECK(fileHandle != RIVE_NULL_HANDLE);
|
||||
|
||||
server.processCommands();
|
||||
|
||||
{
|
||||
auto aal = server.getFile(fileHandle)->testing_getAssetLoader();
|
||||
CHECK(aal == loader.get());
|
||||
CHECK(static_cast<TestFileAssetLoader*>(aal)->m_magicNumber ==
|
||||
MAGIC_NUMBER);
|
||||
}
|
||||
|
||||
std::ifstream hstream("assets/entry.riv", std::ios::binary);
|
||||
rcp<TestFileAssetLoader> heapLoader(new TestFileAssetLoader);
|
||||
FileHandle heapFileHandle = commandQueue->loadFile(
|
||||
std::vector<uint8_t>(std::istreambuf_iterator<char>(hstream), {}),
|
||||
heapLoader);
|
||||
|
||||
server.processCommands();
|
||||
|
||||
{
|
||||
auto aal = server.getFile(fileHandle)->testing_getAssetLoader();
|
||||
CHECK(aal == loader.get());
|
||||
CHECK(static_cast<TestFileAssetLoader*>(aal)->m_magicNumber ==
|
||||
MAGIC_NUMBER);
|
||||
}
|
||||
{
|
||||
auto aal = server.getFile(heapFileHandle)->testing_getAssetLoader();
|
||||
CHECK(aal == heapLoader.get());
|
||||
CHECK(static_cast<TestFileAssetLoader*>(aal)->m_magicNumber ==
|
||||
MAGIC_NUMBER);
|
||||
}
|
||||
|
||||
rcp<TestFileAssetLoader> nullLoader = nullptr;
|
||||
|
||||
std::ifstream nstream("assets/entry.riv", std::ios::binary);
|
||||
FileHandle nullFileHandle = commandQueue->loadFile(
|
||||
std::vector<uint8_t>(std::istreambuf_iterator<char>(nstream), {}),
|
||||
nullLoader);
|
||||
|
||||
server.processCommands();
|
||||
|
||||
{
|
||||
auto aal = server.getFile(fileHandle)->testing_getAssetLoader();
|
||||
CHECK(aal == loader.get());
|
||||
CHECK(static_cast<TestFileAssetLoader*>(aal)->m_magicNumber ==
|
||||
MAGIC_NUMBER);
|
||||
}
|
||||
{
|
||||
auto aal = server.getFile(heapFileHandle)->testing_getAssetLoader();
|
||||
CHECK(aal == heapLoader.get());
|
||||
CHECK(static_cast<TestFileAssetLoader*>(aal)->m_magicNumber ==
|
||||
MAGIC_NUMBER);
|
||||
}
|
||||
{
|
||||
auto aal = server.getFile(nullFileHandle)->testing_getAssetLoader();
|
||||
CHECK(aal == nullLoader.get());
|
||||
}
|
||||
|
||||
// How to test this better ??
|
||||
commandQueue->disconnect();
|
||||
}
|
||||
|
||||
class TestFileListener : public CommandQueue::FileListener
|
||||
{
|
||||
public:
|
||||
virtual void onArtboardsListed(
|
||||
const FileHandle handle,
|
||||
RequestId requestId,
|
||||
std::vector<std::string> artboardNames) override
|
||||
{
|
||||
CHECK(requestId == m_requestId);
|
||||
CHECK(handle == m_handle);
|
||||
CHECK(artboardNames.size() == m_artboardNames.size());
|
||||
for (auto i = 0; i < artboardNames.size(); ++i)
|
||||
@@ -503,6 +626,7 @@ public:
|
||||
m_hasCallback = true;
|
||||
}
|
||||
|
||||
RequestId m_requestId;
|
||||
FileHandle m_handle;
|
||||
std::vector<std::string> m_artboardNames;
|
||||
bool m_hasCallback = false;
|
||||
@@ -523,7 +647,7 @@ TEST_CASE("listArtboard", "[CommandQueue]")
|
||||
fileListener.m_artboardNames = {"New Artboard", "New Artboard"};
|
||||
fileListener.m_handle = goodFile;
|
||||
|
||||
commandQueue->requestArtboardNames(goodFile);
|
||||
fileListener.m_requestId = commandQueue->requestArtboardNames(goodFile);
|
||||
|
||||
wait_for_server(commandQueue.get());
|
||||
|
||||
@@ -553,8 +677,10 @@ class TestArtboardListener : public CommandQueue::ArtboardListener
|
||||
public:
|
||||
virtual void onStateMachinesListed(
|
||||
const ArtboardHandle handle,
|
||||
RequestId requestId,
|
||||
std::vector<std::string> stateMachineNames) override
|
||||
{
|
||||
CHECK(requestId == m_requestId);
|
||||
CHECK(handle == m_handle);
|
||||
CHECK(stateMachineNames.size() == m_stateMachineNames.size());
|
||||
for (auto i = 0; i < stateMachineNames.size(); ++i)
|
||||
@@ -565,6 +691,7 @@ public:
|
||||
m_hasCallback = true;
|
||||
}
|
||||
|
||||
RequestId m_requestId;
|
||||
ArtboardHandle m_handle;
|
||||
std::vector<std::string> m_stateMachineNames;
|
||||
bool m_hasCallback = false;
|
||||
@@ -588,7 +715,8 @@ TEST_CASE("listStateMachine", "[CommandQueue]")
|
||||
artboardListener.m_stateMachineNames = {"State Machine 1"};
|
||||
artboardListener.m_handle = artboardHandle;
|
||||
|
||||
commandQueue->requestStateMachineNames(artboardHandle);
|
||||
artboardListener.m_requestId =
|
||||
commandQueue->requestStateMachineNames(artboardHandle);
|
||||
|
||||
wait_for_server(commandQueue.get());
|
||||
|
||||
@@ -604,7 +732,8 @@ TEST_CASE("listStateMachine", "[CommandQueue]")
|
||||
artboardListener.m_handle = badArtbaord;
|
||||
artboardListener.m_hasCallback = false;
|
||||
|
||||
commandQueue->requestStateMachineNames(badArtbaord);
|
||||
artboardListener.m_requestId =
|
||||
commandQueue->requestStateMachineNames(badArtbaord);
|
||||
|
||||
wait_for_server(commandQueue.get());
|
||||
|
||||
@@ -619,12 +748,15 @@ TEST_CASE("listStateMachine", "[CommandQueue]")
|
||||
class DeleteFileListener : public CommandQueue::FileListener
|
||||
{
|
||||
public:
|
||||
virtual void onFileDeleted(const FileHandle handle) override
|
||||
virtual void onFileDeleted(const FileHandle handle,
|
||||
RequestId requestId) override
|
||||
{
|
||||
CHECK(requestId == m_requestId);
|
||||
CHECK(handle == m_handle);
|
||||
m_hasCallback = true;
|
||||
}
|
||||
|
||||
RequestId m_requestId;
|
||||
FileHandle m_handle;
|
||||
bool m_hasCallback = false;
|
||||
};
|
||||
@@ -632,12 +764,15 @@ public:
|
||||
class DeleteArtboardListener : public CommandQueue::ArtboardListener
|
||||
{
|
||||
public:
|
||||
virtual void onArtboardDeleted(const ArtboardHandle handle) override
|
||||
virtual void onArtboardDeleted(const ArtboardHandle handle,
|
||||
RequestId requestId) override
|
||||
{
|
||||
CHECK(requestId == m_requestId);
|
||||
CHECK(handle == m_handle);
|
||||
m_hasCallback = true;
|
||||
}
|
||||
|
||||
RequestId m_requestId;
|
||||
ArtboardHandle m_handle;
|
||||
bool m_hasCallback = false;
|
||||
};
|
||||
@@ -645,12 +780,15 @@ public:
|
||||
class DeleteStateMachineListener : public CommandQueue::StateMachineListener
|
||||
{
|
||||
public:
|
||||
virtual void onStateMachineDeleted(const StateMachineHandle handle) override
|
||||
virtual void onStateMachineDeleted(const StateMachineHandle handle,
|
||||
RequestId requestId) override
|
||||
{
|
||||
CHECK(requestId == m_requestId);
|
||||
CHECK(handle == m_handle);
|
||||
m_hasCallback = true;
|
||||
}
|
||||
|
||||
RequestId m_requestId;
|
||||
StateMachineHandle m_handle;
|
||||
bool m_hasCallback = false;
|
||||
};
|
||||
@@ -694,9 +832,10 @@ TEST_CASE("listenerDeleteCallbacks", "[CommandQueue]")
|
||||
CHECK(!artboardListener.m_hasCallback);
|
||||
CHECK(!stateMachineListener.m_hasCallback);
|
||||
|
||||
commandQueue->deleteStateMachine(stateMachineHandle);
|
||||
commandQueue->deleteArtboard(artboardHandle);
|
||||
commandQueue->deleteFile(goodFile);
|
||||
stateMachineListener.m_requestId =
|
||||
commandQueue->deleteStateMachine(stateMachineHandle);
|
||||
artboardListener.m_requestId = commandQueue->deleteArtboard(artboardHandle);
|
||||
fileListener.m_requestId = commandQueue->deleteFile(goodFile);
|
||||
|
||||
wait_for_server(commandQueue.get());
|
||||
commandQueue->processMessages();
|
||||
@@ -834,3 +973,22 @@ TEST_CASE("listenerLifeTimes", "[CommandQueue]")
|
||||
// artboardListener and stateMachineListener as they should gracefully
|
||||
// remove themselves from the commandQeueue even though the ref here is gone
|
||||
}
|
||||
|
||||
TEST_CASE("empty test for code cove", "[CommandQueue]")
|
||||
{
|
||||
CommandQueue::FileListener fileL;
|
||||
CommandQueue::ArtboardListener artboardL;
|
||||
CommandQueue::StateMachineListener statemachineL;
|
||||
|
||||
std::vector<std::string> emptyVector;
|
||||
|
||||
fileL.onFileDeleted(0, 0);
|
||||
fileL.onArtboardsListed(0, 0, emptyVector);
|
||||
|
||||
artboardL.onArtboardDeleted(0, 0);
|
||||
artboardL.onStateMachinesListed(0, 0, emptyVector);
|
||||
|
||||
statemachineL.onStateMachineDeleted(0, 0);
|
||||
|
||||
CHECK(true);
|
||||
}
|
||||
45
tests/unit_tests/runtime/text_input_test.cpp
Normal file
45
tests/unit_tests/runtime/text_input_test.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
#include "rive/text/cursor.hpp"
|
||||
#include "rive/text/font_hb.hpp"
|
||||
#include "rive/text/text_input.hpp"
|
||||
#include "rive/text/text_input_drawable.hpp"
|
||||
#include "rive/text/text_input_text.hpp"
|
||||
#include "rive/text/text_input_cursor.hpp"
|
||||
#include "rive/text/text_input_selection.hpp"
|
||||
#include "rive/text/text_input_selected_text.hpp"
|
||||
#include "rive_testing.hpp"
|
||||
#include "utils/no_op_factory.hpp"
|
||||
#include "rive_file_reader.hpp"
|
||||
#include "utils/serializing_factory.hpp"
|
||||
using namespace rive;
|
||||
|
||||
TEST_CASE("file with text input loads correctly", "[text_input]")
|
||||
{
|
||||
auto file = ReadRiveFile("assets/text_input.riv");
|
||||
CHECK(file != nullptr);
|
||||
auto artboard = file->artboardNamed("Text Input - Multiline");
|
||||
CHECK(artboard->objects<TextInput>().size() == 1);
|
||||
|
||||
auto textInput = artboard->objects<TextInput>().first();
|
||||
CHECK(textInput != nullptr);
|
||||
|
||||
CHECK(textInput->children<TextInputDrawable>().size() == 4);
|
||||
CHECK(textInput->children<TextInputText>().size() == 1);
|
||||
CHECK(textInput->children<TextInputSelection>().size() == 1);
|
||||
CHECK(textInput->children<TextInputCursor>().size() == 1);
|
||||
CHECK(textInput->children<TextInputSelectedText>().size() == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("file with text input renders correctly", "[silver]")
|
||||
{
|
||||
SerializingFactory silver;
|
||||
auto file = ReadRiveFile("assets/text_input.riv", &silver);
|
||||
auto artboard = file->artboardNamed("Text Input - Multiline");
|
||||
silver.frameSize(artboard->width(), artboard->height());
|
||||
|
||||
artboard->advance(0.0f);
|
||||
auto renderer = silver.makeRenderer();
|
||||
artboard->draw(renderer.get());
|
||||
CHECK(silver.matches("text_input"));
|
||||
}
|
||||
#endif
|
||||
BIN
tests/unit_tests/silvers/text_input.sriv
Normal file
BIN
tests/unit_tests/silvers/text_input.sriv
Normal file
Binary file not shown.
Reference in New Issue
Block a user