@@ -190,18 +190,46 @@ def shift_all_colors_in_trk1(self, file_name, j3d_file, h_shift, v_shift):
190190 # ChuChu eyes material animation, doesn't look right recolored so we just recolor the texture instead
191191 continue
192192
193- if not len (anim .r .keyframes ) == len (anim .g .keyframes ) == len (anim .b .keyframes ):
194- # Can't properly adjust colors in HSV when RGB don't come together in sets.
195- continue
193+ assert len (anim .r .keyframes ) > 0 and len (anim .g .keyframes ) > 0 and len (anim .b .keyframes ) > 0
194+
195+ # In some cases (specifically Gohma), there won't be an equal number of keyframes for R G and B, so we can't simply iterate over the list.
196+
197+ # First make a list of what times are present on the timeline for this animation.
198+ unique_keyframe_times = []
199+ for keyframe in (anim .r .keyframes + anim .g .keyframes + anim .b .keyframes ):
200+ if keyframe .time not in unique_keyframe_times :
201+ unique_keyframe_times .append (keyframe .time )
202+ unique_keyframe_times .sort ()
196203
197- for i in range (len (anim .r .keyframes )):
198- r = anim .r .keyframes [i ].value & 0xFF
199- g = anim .g .keyframes [i ].value & 0xFF
200- b = anim .b .keyframes [i ].value & 0xFF
204+ def get_keyframe_by_closest_time (keyframes , keyframe_time ):
205+ return min (keyframes , key = lambda kf : abs (kf .time - keyframe_time ))
206+
207+ def get_keyframe_by_exact_time (keyframes , keyframe_time ):
208+ return next ((kf for kf in keyframes if kf .time == keyframe_time ), None )
209+
210+ # Then make a list of what the modified colors at each time will be, but don't actually modify them yet since we may need to re-read the values of previous times if the next time is missing a channel.
211+ modified_colors_by_time = {}
212+ for keyframe_time in unique_keyframe_times :
213+ #print(" %d" % keyframe_time)
214+ r = get_keyframe_by_closest_time (anim .r .keyframes , keyframe_time ).value & 0xFF
215+ g = get_keyframe_by_closest_time (anim .g .keyframes , keyframe_time ).value & 0xFF
216+ b = get_keyframe_by_closest_time (anim .b .keyframes , keyframe_time ).value & 0xFF
217+ #print(" %d %d %d" % (r, g, b))
201218 r , g , b = texture_utils .hsv_shift_color ((r , g , b ), h_shift , v_shift )
202- anim .r .keyframes [i ].value = r
203- anim .g .keyframes [i ].value = g
204- anim .b .keyframes [i ].value = b
219+ modified_colors_by_time [keyframe_time ] = (r , g , b )
220+
221+ # Then actually modify the colors.
222+ for keyframe_time in unique_keyframe_times :
223+ r , g , b = modified_colors_by_time [keyframe_time ]
224+ r_keyframe = get_keyframe_by_exact_time (anim .r .keyframes , keyframe_time )
225+ if r_keyframe :
226+ r_keyframe .value = r
227+ g_keyframe = get_keyframe_by_exact_time (anim .g .keyframes , keyframe_time )
228+ if g_keyframe :
229+ g_keyframe .value = g
230+ b_keyframe = get_keyframe_by_exact_time (anim .b .keyframes , keyframe_time )
231+ if b_keyframe :
232+ b_keyframe .value = b
205233
206234def shift_all_colors_in_particle (self , particle , h_shift , v_shift ):
207235 #print("%04X" % particle_id)
0 commit comments