12
12
from manimlib .animation .transform import Transform
13
13
from manimlib .mobject .mobject import Mobject
14
14
from manimlib .mobject .mobject import Group
15
- from manimlib .mobject .svg .mtex_mobject import MTex
15
+ from manimlib .mobject .svg .labelled_string import LabelledString
16
16
from manimlib .mobject .types .vectorized_mobject import VGroup
17
17
from manimlib .mobject .types .vectorized_mobject import VMobject
18
18
from manimlib .utils .config_ops import digest_config
@@ -153,51 +153,66 @@ def get_mobject_key(mobject: Tex) -> str:
153
153
return mobject .get_tex ()
154
154
155
155
156
- class TransformMatchingMTex (AnimationGroup ):
156
+ class TransformMatchingStrings (AnimationGroup ):
157
157
CONFIG = {
158
158
"key_map" : dict (),
159
+ "transform_mismatches" : False ,
159
160
}
160
161
161
- def __init__ (self , source_mobject : MTex , target_mobject : MTex , ** kwargs ):
162
+ def __init__ (self ,
163
+ source_mobject : LabelledString ,
164
+ target_mobject : LabelledString ,
165
+ ** kwargs
166
+ ):
162
167
digest_config (self , kwargs )
163
- assert isinstance (source_mobject , MTex )
164
- assert isinstance (target_mobject , MTex )
168
+ assert isinstance (source_mobject , LabelledString )
169
+ assert isinstance (target_mobject , LabelledString )
165
170
anims = []
166
- rest_source_submobs = source_mobject .submobjects .copy ()
167
- rest_target_submobs = target_mobject .submobjects .copy ()
168
-
169
- def add_anim_from (anim_class , func , source_attr , target_attr = None ):
170
- if target_attr is None :
171
- target_attr = source_attr
172
- source_parts = func (source_mobject , source_attr )
173
- target_parts = func (target_mobject , target_attr )
174
- filtered_source_parts = [
175
- submob_part for submob_part in source_parts
176
- if all ([
177
- submob in rest_source_submobs
178
- for submob in submob_part
179
- ])
180
- ]
181
- filtered_target_parts = [
182
- submob_part for submob_part in target_parts
183
- if all ([
184
- submob in rest_target_submobs
185
- for submob in submob_part
186
- ])
187
- ]
188
- if not (filtered_source_parts and filtered_target_parts ):
189
- return
190
- anims .append (anim_class (
191
- VGroup (* filtered_source_parts ),
192
- VGroup (* filtered_target_parts ),
193
- ** kwargs
194
- ))
195
- for submob in it .chain (* filtered_source_parts ):
196
- rest_source_submobs .remove (submob )
197
- for submob in it .chain (* filtered_target_parts ):
198
- rest_target_submobs .remove (submob )
199
-
200
- def get_submobs_from_keys (mobject , keys ):
171
+ rest_source_indices = list (range (len (source_mobject .submobjects )))
172
+ rest_target_indices = list (range (len (target_mobject .submobjects )))
173
+
174
+ def add_anims_from (anim_class , func , source_args , target_args = None ):
175
+ if target_args is None :
176
+ target_args = source_args .copy ()
177
+ for source_arg , target_arg in zip (source_args , target_args ):
178
+ source_parts = func (source_mobject , source_arg )
179
+ target_parts = func (target_mobject , target_arg )
180
+ source_indices_lists = source_mobject .indices_lists_of_parts (
181
+ source_parts
182
+ )
183
+ target_indices_lists = target_mobject .indices_lists_of_parts (
184
+ target_parts
185
+ )
186
+ filtered_source_indices_lists = list (filter (
187
+ lambda indices_list : all ([
188
+ index in rest_source_indices
189
+ for index in indices_list
190
+ ]), source_indices_lists
191
+ ))
192
+ filtered_target_indices_lists = list (filter (
193
+ lambda indices_list : all ([
194
+ index in rest_target_indices
195
+ for index in indices_list
196
+ ]), target_indices_lists
197
+ ))
198
+ if not all ([
199
+ filtered_source_indices_lists ,
200
+ filtered_target_indices_lists
201
+ ]):
202
+ continue
203
+ anims .append (anim_class (source_parts , target_parts , ** kwargs ))
204
+ for index in it .chain (* filtered_source_indices_lists ):
205
+ rest_source_indices .remove (index )
206
+ for index in it .chain (* filtered_target_indices_lists ):
207
+ rest_target_indices .remove (index )
208
+
209
+ def get_common_substrs (func ):
210
+ return sorted ([
211
+ substr for substr in func (source_mobject )
212
+ if substr and substr in func (target_mobject )
213
+ ], key = len , reverse = True )
214
+
215
+ def get_parts_from_keys (mobject , keys ):
201
216
if not isinstance (keys , tuple ):
202
217
keys = (keys ,)
203
218
indices = []
@@ -207,52 +222,55 @@ def get_submobs_from_keys(mobject, keys):
207
222
elif isinstance (key , range ):
208
223
indices .extend (key )
209
224
elif isinstance (key , str ):
210
- all_parts = mobject .get_parts_by_tex (key )
225
+ all_parts = mobject .get_parts_by_string (key )
211
226
indices .extend (it .chain (* [
212
227
mobject .indices_of_part (part ) for part in all_parts
213
228
]))
214
229
else :
215
230
raise TypeError (key )
216
231
return VGroup (VGroup (* [
217
- mobject [i ] for i in remove_list_redundancies (indices )
232
+ mobject [index ] for index in remove_list_redundancies (indices )
218
233
]))
219
234
220
- for source_key , target_key in self .key_map .items ():
221
- add_anim_from (
222
- ReplacementTransform , get_submobs_from_keys ,
223
- source_key , target_key
224
- )
225
-
226
- common_specified_substrings = sorted (list (
227
- set (source_mobject .get_specified_substrings ()).intersection (
228
- target_mobject .get_specified_substrings ()
229
- )
230
- ), key = len , reverse = True )
231
- for part_tex_string in common_specified_substrings :
232
- add_anim_from (
233
- FadeTransformPieces , MTex .get_parts_by_tex , part_tex_string
234
- )
235
-
236
- common_submob_tex_strings = {
237
- source_submob .get_tex () for source_submob in source_mobject
238
- }.intersection ({
239
- target_submob .get_tex () for target_submob in target_mobject
240
- })
241
- for tex_string in common_submob_tex_strings :
242
- add_anim_from (
243
- FadeTransformPieces ,
244
- lambda mobject , attr : VGroup (* [
245
- VGroup (mob ) for mob in mobject
246
- if mob .get_tex () == attr
247
- ]),
248
- tex_string
249
- )
250
-
251
- anims .append (FadeOutToPoint (
252
- VGroup (* rest_source_submobs ), target_mobject .get_center (), ** kwargs
253
- ))
254
- anims .append (FadeInFromPoint (
255
- VGroup (* rest_target_submobs ), source_mobject .get_center (), ** kwargs
256
- ))
235
+ add_anims_from (
236
+ ReplacementTransform , get_parts_from_keys ,
237
+ self .key_map .keys (), self .key_map .values ()
238
+ )
239
+ add_anims_from (
240
+ FadeTransformPieces ,
241
+ LabelledString .get_parts_by_string ,
242
+ get_common_substrs (LabelledString .get_specified_substrs )
243
+ )
244
+ add_anims_from (
245
+ FadeTransformPieces ,
246
+ LabelledString .get_parts_by_group_substr ,
247
+ get_common_substrs (LabelledString .get_group_substrs )
248
+ )
249
+
250
+ fade_source = VGroup (* [
251
+ source_mobject [index ]
252
+ for index in rest_source_indices
253
+ ])
254
+ fade_target = VGroup (* [
255
+ target_mobject [index ]
256
+ for index in rest_target_indices
257
+ ])
258
+ if self .transform_mismatches :
259
+ anims .append (ReplacementTransform (
260
+ fade_source ,
261
+ fade_target ,
262
+ ** kwargs
263
+ ))
264
+ else :
265
+ anims .append (FadeOutToPoint (
266
+ fade_source ,
267
+ target_mobject .get_center (),
268
+ ** kwargs
269
+ ))
270
+ anims .append (FadeInFromPoint (
271
+ fade_target ,
272
+ source_mobject .get_center (),
273
+ ** kwargs
274
+ ))
257
275
258
276
super ().__init__ (* anims )
0 commit comments