Skip to content

Allow create_text to accept multiple texts and materials fixes #1012#1101

Open
AdityaGupta716 wants to merge 16 commits intofury-gl:v2from
AdityaGupta716:text-3d-multi
Open

Allow create_text to accept multiple texts and materials fixes #1012#1101
AdityaGupta716 wants to merge 16 commits intofury-gl:v2from
AdityaGupta716:text-3d-multi

Conversation

@AdityaGupta716
Copy link
Contributor

Fixes #1012

Changes

  • Updated create_text in fury/actor/core.py to accept a list of
    strings and a list of materials
  • Returns a single Text actor for a string (backward compatible)
  • Returns a Group of Text actors for a list of strings
  • Added tests in fury/actor/tests/test_actor_text.py

Usage

# Single text (unchanged behavior)
t = create_text("Hello", material)

# Multiple texts
t = create_text(["Hello", "World", "FURY"], material)

# Multiple texts with individual materials
t = create_text(["Hello", "World"], [material1, material2])

@AdityaGupta716
Copy link
Contributor Author

AdityaGupta716 commented Feb 21, 2026

@maharshi-gor I've implemented the changes for this issue. Plz review

Comment on lines +272 to 275
The material object or list of material objects.
**kwargs : dict
Additional properties like font_size, anchor, etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also think about how do you provide all the other keyword arguments in the case of multiple text?

Will the position be same for all of them?

@maharshi-gor
Copy link
Contributor

Hi @AdityaGupta716 thanks for the work. Please take a look at the repository structure before submitting a PR.
The text actor testcases are present in actor\tests\test_core.py where the new tests should also reside.

@AdityaGupta716
Copy link
Contributor Author

@maharshi-gor, the kwargs are fully flexible — pass a single value and it broadcasts to all text objects, or pass a list for per-text control. For example font_size=24 applies to all, while position=[(0,0,0), (1,0,0)] sets each independently. Length mismatches raise a ValueError immediately. Let me know if you need anything else.

Copy link
Contributor

@maharshi-gor maharshi-gor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I suspect the PR needs to update different file and add the test cases at different location according to that.

>>> # Multiple texts, shared material and kwargs
>>> t = create_text(["Hello", "World", "FURY"], mat)

>>> # Multiple texts with individual materials and per-text positions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove comments from examples.

Comment on lines 264 to +359
def create_text(text, material, **kwargs):
"""Create a text object.
"""Create a text object or a group of text objects.

Parameters
----------
text : str
The text content.
material : TextMaterial
The material object.
text : str or list of str
The text content or list of text contents.
material : TextMaterial or list of TextMaterial
The material object or list of material objects.
**kwargs : dict
Additional properties like font_size, anchor, etc.
Additional properties like font_size, anchor, position, etc.
When ``text`` is a list, each kwarg can be either:
- A single value applied to all text objects, or
- A list of values (one per text) for per-text customization.

Returns
-------
Text
The text object.
Text or Group
A single Text object if text is a string, or a Group of Text
objects if text is a list.

Raises
------
TypeError
If text is not a string or material is not an instance of TextMaterial.
If text is not a string or list of strings, or material is not
an instance of TextMaterial or list of TextMaterial.
ValueError
If the length of material list or any kwarg list does not match
the length of the text list.

Examples
--------
>>> mat = TextMaterial()
>>> # Single text (unchanged behavior)
>>> t = create_text("Hello", mat)

>>> # Multiple texts, shared material and kwargs
>>> t = create_text(["Hello", "World", "FURY"], mat)

>>> # Multiple texts with individual materials and per-text positions
>>> t = create_text(
... ["Hello", "World"],
... [TextMaterial(), TextMaterial()],
... position=[(0, 0, 0), (1, 0, 0)],
... )
"""
if isinstance(text, list):
if not all(isinstance(t, str) for t in text):
raise TypeError("All items in text list must be strings.")

n = len(text)

if isinstance(material, list):
if len(material) != n:
raise ValueError(
"Length of material list must match length of text list."
)
if not all(isinstance(m, TextMaterial) for m in material):
raise TypeError(
"All items in material list must be instances of TextMaterial."
)
materials = material
else:
if not isinstance(material, TextMaterial):
raise TypeError("material must be an instance of TextMaterial.")
materials = [material] * n

# Normalize kwargs: expand scalars to per-text lists
norm_kwargs = {}
for k, v in kwargs.items():
if isinstance(v, list):
if len(v) != n:
raise ValueError(
f"Length of kwarg '{k}' list must match length of text list."
)
norm_kwargs[k] = v
else:
norm_kwargs[k] = [v] * n

group = Group()
for i, (t, m) in enumerate(zip(text, materials, strict=True)):
per_text_kwargs = {k: norm_kwargs[k][i] for k in norm_kwargs}
position = per_text_kwargs.pop("position", None)
actor = Text(text=t, material=m, **per_text_kwargs)
if position is not None:
actor.local.position = position
group.add(actor)
return group

if not isinstance(text, str):
raise TypeError("text must be a string.")

if not isinstance(material, TextMaterial):
raise TypeError("material must be an instance of TextMaterial.")

text = Text(text=text, material=material, **kwargs)
return text
return Text(text=text, material=material, **kwargs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this should not be done here. Please check the text method in the planar.py

def text(

This method should be updated to accept multiple text not this method. The text method is the one which people should use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants