-
Notifications
You must be signed in to change notification settings - Fork 528
Add PAGX node channel reflection API, matrix animation, and in-place notifyChange refresh. #3505
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
bad2640
7679bfa
40d0a79
b0c24dd
4372aa3
f82d828
e555f6c
9b0808a
d107612
a94dbef
3cd2103
e632a80
92fa545
96e6b4b
1e85c1c
31b3355
ed3929f
988e207
7a89437
a1f7495
dfe1280
bb59eb0
a7d1467
4178748
11dfcd8
dc6fe49
17d15c3
23d0adc
953fd96
e9b1e6e
c74c6cf
b508a45
24e56fd
1a92f36
a044747
6f8ccf7
d8705dd
7924fa0
d2c1484
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| ///////////////////////////////////////////////////////////////////////////////////////////////// | ||
| // | ||
| // Tencent is pleased to support the open source community by making libpag available. | ||
| // | ||
| // Copyright (C) 2026 Tencent. All rights reserved. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file | ||
| // except in compliance with the License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // unless required by applicable law or agreed to in writing, software distributed under the | ||
| // license is distributed on an "as is" basis, without warranties or conditions of any kind, | ||
| // either express or implied. see the license for the specific language governing permissions | ||
| // and limitations under the license. | ||
| // | ||
| ///////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <string> | ||
| #include <vector> | ||
| #include "pagx/nodes/Channel.h" | ||
| #include "pagx/nodes/Node.h" | ||
|
|
||
| namespace pagx { | ||
|
|
||
| /** | ||
| * Reflective, by-name read/write access to a PAGX node's scalar properties. Channels use the same | ||
| * attribute names as PAGX XML (e.g. "alpha", "position.x", "blendMode"). This API edits a | ||
| * PAGXDocument; refresh any associated scene afterwards via PAGXDocument::notifyChange (use | ||
| * RequiresLayout to decide the layoutChanged flag). Typical use: editor property panels and | ||
| * data-driven CLI edits, where the caller holds a string channel name rather than a compile-time | ||
| * field reference. | ||
| * | ||
| * Value encoding (KeyValue alternatives): scalars map directly (float/bool/int/string/Color); | ||
| * enums are passed as their string name (e.g. blendMode = "multiply"); Point/Size fields are | ||
| * addressed component-wise via suffixed channels ("position.x", "size.width"). Multi-component | ||
| * fields without a component channel are not exposed. The set of channels available for each node | ||
| * type can be enumerated at runtime via ListChannels(); ChannelExists() is the corresponding | ||
| * existence predicate, useful to distinguish a typo from a known-but-not-animatable channel | ||
| * (IsAnimatableChannel and RequiresLayout both return false for unknown channels). | ||
| */ | ||
|
|
||
| /** | ||
| * Reads the value of the given channel on the node into out. | ||
| * @param node the node to read from; must not be null. | ||
| * @param channel the channel name (see the encoding notes above). | ||
| * @param out receives the value on success; must not be null. | ||
| * @return true on success; false if node/out is null, the channel is unknown for the node type, or | ||
| * an optional field is unset. | ||
| */ | ||
| bool GetNodeChannel(const Node* node, const std::string& channel, KeyValue* out); | ||
|
|
||
| /** | ||
| * Writes value into the node field identified by channel. Edits are applied to the document; | ||
| * refresh any associated scene separately via PAGXDocument::notifyChange. | ||
| * @param node the node to write to; must not be null. | ||
| * @param channel the channel name (see the encoding notes above). | ||
| * @param value the value to write; its KeyValue alternative must match the field's type. | ||
| * @return true on success; false if node is null, the channel is unknown for the node type, the | ||
| * KeyValue type does not match the field, or an enum string is invalid. | ||
| */ | ||
| bool SetNodeChannel(Node* node, const std::string& channel, const KeyValue& value); | ||
|
|
||
| /** | ||
| * Resets the node field identified by channel to its default — the value a freshly created node of | ||
| * the same type carries. Use this to "clear" a previously edited channel: for optional fields | ||
| * (e.g. a TextModifier's strokeWidth) the default is the unset state, so resetting removes the | ||
| * value. Only the addressed component is reset for component-wise channels ("position.x" resets x | ||
| * but leaves y). Refresh any associated scene separately via PAGXDocument::notifyChange. | ||
| * @param node the node to reset; must not be null. | ||
| * @param channel the channel name (see the encoding notes above). | ||
| * @return true on success; false if node is null or the channel is unknown for the node type. | ||
| */ | ||
| bool ResetNodeChannel(Node* node, const std::string& channel); | ||
|
|
||
| /** | ||
| * Returns true if the given channel can be driven by an animation channel (i.e. an animation may | ||
| * target it during playback). Returns false for channels that only take effect through a | ||
| * layout/content rebuild and for unknown channels. Independent of RequiresLayout: a geometry | ||
| * channel such as a shape's "size.width" is both animatable during playback and layout-affecting | ||
| * when edited on the document. | ||
| * @param type the node type. | ||
| * @param channel the channel name. | ||
| */ | ||
| bool IsAnimatableChannel(NodeType type, const std::string& channel); | ||
|
|
||
| /** | ||
| * Returns true if editing the given channel on the document requires a layout pass before the | ||
| * change is visible in a scene. Callers that mutate a channel via SetNodeChannel should pass this | ||
| * as the layoutChanged flag to PAGXDocument::notifyChange. Returns false for channels that refresh | ||
| * without layout and for unknown channels. | ||
| * @param type the node type. | ||
| * @param channel the channel name. | ||
| */ | ||
| bool RequiresLayout(NodeType type, const std::string& channel); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Minor] 反射 API 缺少『列出/查询合法 channel』的 introspection 接口
编辑器场景下 channel 名 typo(如 建议新增至少一个 introspection API:
或把
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 认同,已加 introspection 接口 + 补 LOGE。 新增的 public APIbool ChannelExists(NodeType type, const std::string& channel);
std::vector<std::string> ListChannels(NodeType type);
没改 GetNodeChannel 失败补 LOGE跟 |
||
|
|
||
| /** | ||
| * Returns true if the given channel name is defined for the node type, regardless of its flags. | ||
| * Use this to distinguish a typo (channel does not exist) from a channel that exists but is not | ||
| * animatable / does not require layout — IsAnimatableChannel and RequiresLayout collapse both into | ||
| * false. Editor scenarios that pass user-provided channel names through Get/SetNodeChannel should | ||
| * validate with this first to surface typos as a distinct error. | ||
| * @param type the node type. | ||
| * @param channel the channel name. | ||
| */ | ||
| bool ChannelExists(NodeType type, const std::string& channel); | ||
|
|
||
| /** | ||
| * Returns the list of channel names defined for the given node type. The returned names match the | ||
| * strings accepted by Get/SetNodeChannel/ResetNodeChannel and the queries above. Order is stable | ||
| * within a release but is not guaranteed across releases. Returns an empty vector for node types | ||
| * that expose no reflectable scalar channels. | ||
| * @param type the node type. | ||
| */ | ||
| std::vector<std::string> ListChannels(NodeType type); | ||
|
|
||
| } // namespace pagx | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,6 +104,17 @@ class LayoutNode { | |
| /** Returns true if any constraint attribute is set. */ | ||
| bool hasConstraints() const; | ||
|
|
||
| /** | ||
| * Clears the layout-computed outputs (preferred and resolved position/size) so the node is | ||
| * re-measured on the next layout pass. Authored inputs (width/height, constraints, percent sizes) | ||
| * are left unchanged. | ||
| * | ||
| * Called automatically by `PAGXDocument::applyLayout` before re-running layout on an | ||
| * already-laid-out document, so callers normally do not invoke this directly. Calling it without | ||
| * a subsequent layout pass leaves the node without resolved geometry. | ||
| */ | ||
| void resetLayout(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Nit] 注释说『Used when re-running layout on an already-laid-out document after edits』,但没说明:
PAGXDocument.h:147-149 已经描述了 applyLayout 的 reset 行为,但
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 认同,已补。
|
||
|
|
||
| /** | ||
| * Returns the layout-resolved bounds of this node in its parent's coordinate space. | ||
| * Only valid after applyLayout() has been called. Before layout, returns an empty Rect. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Nit]
refreshNodes/syncChildren/spawnTimelines/resetTimelines应改为 private这 4 个新增方法当前是 protected,但仓库中
pagx::PAGComposition没有任何子类(同名pag::PAGComposition是不同命名空间的旧 SDK 类型,不相关)。注释也明确写了Called by PAGScene::onNodesChanged等——它们是 friend 内部协作的实现细节,不是给子类继承的扩展点。protected 暴露了不必要的扩展面,提高了未来误用风险。建议改为 private,已有
friend class PAGScene足以访问。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
认同,已改 private。
refreshNodes/syncChildren/spawnTimelines/resetTimelines这 4 个都是 PAGScene/PAGComposition 内部协作的实现细节,没有"给子类继承的扩展点"语义;改成 private 后由现有的friend class PAGScene提供必要访问,扩展面收紧。MakeChild/buildChildren/findChildForLayer仍保留在 protected:它们是构造或 hit-test 路径上 PAGComposition 自身递归的方法,未来若有子类做 hit-test 增强还可能依赖;这次没动它们,避免动到不在 review 关注范围内的访问性。