[Bf-extensions-cvs] [093e1eb5] master: Initial commit Animated Text: T51285
meta-androcto
noreply at git.blender.org
Sat Apr 22 11:51:10 CEST 2017
Commit: 093e1eb58a8908647b4342c08344042e54183f49
Author: meta-androcto
Date: Sat Apr 22 19:50:46 2017 +1000
Branches: master
https://developer.blender.org/rBAC093e1eb58a8908647b4342c08344042e54183f49
Initial commit Animated Text: T51285
===================================================================
A animation_text_types.py
===================================================================
diff --git a/animation_text_types.py b/animation_text_types.py
new file mode 100644
index 00000000..27106bcc
--- /dev/null
+++ b/animation_text_types.py
@@ -0,0 +1,599 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+## by LeoMoon Studios, Marcin Zielinski, Martin Wacker, Bassam Kurdali, Jared Felsman, meta-androcto ##
+
+bl_info = {
+ "name": "Animated Text",
+ "author": "LeoMoon Studios, Marcin Zielinski, Martin Wacker, "
+ "Bassam Kurdali, Jared Felsman, meta-androcto",
+ "version": (0, 3, 0),
+ "blender": (2, 74, 5),
+ "location": "Properties Editor > Font",
+ "description": "Typing & Counting Animated Text",
+ "warning": "",
+ "wiki_url": "",
+ "category": "Animation"
+}
+
+import bpy
+import string
+import random
+from bpy.props import (
+ FloatProperty, PointerProperty, BoolProperty,
+ IntProperty, EnumProperty, StringProperty
+)
+from bpy.app.handlers import persistent
+
+
+def formatCounter(input, timeSeparators, timeLeadZeroes, timeTrailZeroes, timeModulo):
+ f = 0
+ s = 0
+ m = 0
+ h = 0
+ out = ''
+ neg = ''
+ if input < 0:
+ neg = '-'
+ input = abs(input)
+
+ if timeSeparators >= 0:
+ if timeSeparators == 0:
+ out = int(input)
+ out = format(out, '0' + str(timeLeadZeroes) + 'd')
+ else:
+ s, f = divmod(int(input), timeModulo)
+ out = format(f, '0' + str(timeLeadZeroes) + 'd')
+
+ if timeSeparators >= 1:
+ if timeSeparators == 1:
+ out = format(s, '0' + str(timeTrailZeroes) + 'd') + ":" + out
+ else:
+ m, s = divmod(s, 60)
+ out = format(s, '02d') + ":" + out
+
+ if timeSeparators >= 2:
+ if timeSeparators == 2:
+ out = format(m, '0' + str(timeTrailZeroes) + 'd') + ":" + out
+ else:
+ h, m = divmod(m, 60)
+ out = format(m, '02d') + ":" + out
+
+ if timeSeparators >= 3:
+ out = format(h, '0' + str(timeTrailZeroes) + 'd') + ":" + out
+
+ return neg + out
+
+
+class TextCounter_Props(bpy.types.PropertyGroup):
+
+ def val_up(self, context):
+ textcounter_update_val(context.object, context.scene)
+
+ ifAnimated = BoolProperty(
+ name='Counter Active', default=False, update=val_up
+ )
+ counter = FloatProperty(
+ name='Counter', update=val_up
+ )
+ padding = IntProperty(
+ name='Padding', update=val_up, min=1
+ )
+ ifDecimal = BoolProperty(
+ name='Decimal', default=False, update=val_up
+ )
+ decimals = IntProperty(
+ name='Decimal', update=val_up, min=0
+ )
+ typeEnum = EnumProperty(
+ items=[
+ ('ANIMATED', 'Animated', 'Counter values from f-curves'),
+ ('DYNAMIC', 'Dynamic', 'Counter values from expression')
+ ],
+ name='Type', update=val_up, default='ANIMATED'
+ )
+ formattingEnum = EnumProperty(
+ items=[
+ ('NUMBER', 'Number', 'Counter values as numbers'),
+ ('TIME', 'Time', 'Counter values as time')
+ ],
+ name='Formatting Type', update=val_up, default='NUMBER'
+ )
+ expr = StringProperty(
+ name='Expression', update=val_up, default=''
+ )
+ prefix = StringProperty(
+ name='Prefix', update=val_up, default=''
+ )
+ sufix = StringProperty(
+ name='Sufix', update=val_up, default=''
+ )
+ ifTextFile = BoolProperty(
+ name='Override with Text File', default=False, update=val_up
+ )
+ textFile = StringProperty(
+ name='Text File', update=val_up, default=''
+ )
+ ifTextFormatting = BoolProperty(
+ name='Numerical Formatting', default=False, update=val_up
+ )
+ timeSeparators = IntProperty(
+ name='Separators', update=val_up, min=0, max=3
+ )
+ timeModulo = IntProperty(
+ name='Last Separator Modulo', update=val_up, min=1, default=24
+ )
+ timeLeadZeroes = IntProperty(
+ name='Leading Zeroes', update=val_up, min=1, default=2
+ )
+ timeTrailZeroes = IntProperty(
+ name='Trailing Zeroes', update=val_up, min=1, default=2
+ )
+
+ def dyn_get(self):
+ context = bpy.context
+ C = context
+ scene = C.scene
+
+ try:
+ return str(eval(self.expr))
+ except Exception as e:
+ print('Expr Error: ' + str(e.args))
+
+ dynamicCounter = StringProperty(name='Dynamic Counter', get=dyn_get, default='')
+
+ def form_up(self, context):
+ textcounter_update_val(context.object, context.scene)
+
+ def form_get(self):
+ f = 0
+ s = 0
+ m = 0
+ h = 0
+ out = ''
+ input = 0
+ if self.typeEnum == 'ANIMATED':
+ input = float(self.counter)
+ elif self.typeEnum == 'DYNAMIC':
+ input = float(self.dynamicCounter)
+ return formatCounter(input, self.timeSeparators, self.timeLeadZeroes, self.timeTrailZeroes, self.timeModulo)
+
+ def form_set(self, value):
+ counter = 0
+ separators = value.split(':')
+ for idx, i in enumerate(separators[:-1]):
+ counter += int(i) * 60**(len(separators) - 2 - idx) * self.timeModulo
+ counter += int(separators[-1])
+ self.counter = float(counter)
+
+ formattedCounter = StringProperty(name='Formatted Counter', get=form_get, set=form_set, default='')
+
+
+def textcounter_update_val(text, scene):
+ text.update_tag(refresh={'DATA'})
+ props = text.data.text_counter_props
+ counter = 0
+ line = ''
+ out = ''
+ neg = ''
+
+ if props.typeEnum == 'ANIMATED':
+ counter = props.counter
+ elif props.typeEnum == 'DYNAMIC':
+ try:
+ counter = eval(props.expr)
+ except Exception as e:
+ print('Expr Error: ' + str(e.args))
+
+ isNumeric = True # always true for counter not overrided
+ if props.ifTextFile:
+ txt = bpy.data.texts[props.textFile]
+ clampedCounter = max(0, min(int(counter), len(txt.lines) - 1))
+ line = txt.lines[clampedCounter].body
+ if props.ifTextFormatting:
+ try:
+ line = float(line)
+ except Exception:
+ isNumeric = False
+ out = line
+ else:
+ isNumeric = False
+ out = line
+ else:
+ line = counter
+
+ if isNumeric:
+ if props.formattingEnum == 'NUMBER':
+ # add minus before padding zeroes
+ neg = '-' if line < 0 else ''
+ line = abs(line)
+ # int / decimal
+ if not props.ifDecimal:
+ line = int(line)
+ out = ('{:.' + str(props.decimals) + 'f}').format(line)
+
+ # padding
+ arr = out.split('.')
+ arr[0] = arr[0].zfill(props.padding)
+ out = arr[0]
+ if len(arr) > 1:
+ out += '.' + arr[1]
+ elif props.formattingEnum == 'TIME':
+ out = formatCounter(line, props.timeSeparators, props.timeLeadZeroes, props.timeTrailZeroes, props.timeModulo)
+
+ # prefix/sufix
+ if props.ifTextFile:
+ text.data.body = out
+ if props.ifTextFormatting and isNumeric:
+ text.data.body = props.prefix + neg + out + props.sufix
+ else:
+ text.data.body = props.prefix + neg + out + props.sufix
+
+
+ at persistent
+def textcounter_text_update_frame(scene):
+ for text in scene.objects:
+ if text.type == 'FONT' and text.data.text_counter_props.ifAnimated:
+ textcounter_update_val(text, scene)
+
+### text scrambler ###
+
+
+ at persistent
+def textscrambler_update_frame(scene):
+ for text in scene.objects:
+ if text.type == 'FONT' and text.data.use_text_scrambler:
+ uptext(text.data)
+
+
+def update_func(self, context):
+ uptext(self)
+# Register all operators and panels
+
+
+def uptext(text):
+ source = text.source_text
+ if source in bpy.data.texts:
+ r = bpy.data.texts[source].as_string()
+ else:
+ r = source
+
+ base = len(r)
+ prog = text.scrambler_progress / 100.0
+
+ c = int(base * prog)
+
+ clean = r[:base - c]
+ scrambled = ""
+ for i in range(c):
+ scrambled += random.choice(text.characters)
+ text.body = clean + scrambled
+
+### Typing Text ###
+
+
+def animate_text(scene):
+
+ objects = scene.objects
+
+ for obj in objects:
+ if obj.type == "FONT" and "runAnimation" in obj and obj.runAnimation:
+ endFrame = obj.startFrame + (len(obj.defaultTextBody) * obj.typeSpeed)
+ if obj.manualEndFrame:
+ endFrame = obj.endFrame
+
+ if scene.frame_current < obj.startFrame:
+ obj.data.body = ""
+
+ elif scene.frame_current >= obj.startFrame and scene.frame_current <= endFrame:
+ frameStringLength = (scene.frame_current - obj.startFrame) / obj.typeSpeed
+ obj.data.body = obj.defaultTextBody[0:int(frameStringLength)]
+
+ elif scene.frame_current > endFrame:
+ obj.data.body = obj.defaultTextBody
+
+### Typewriter ###
+
+
+def uptext1(text):
+ '''
+ slice the source text up to the character_count
+ '''
+ source = text.source_text
+ if source in bpy.data.texts:
+ text.body = bpy.data.texts[source].as_string()[:text.character_count]
+ else:
+ text.body = source[:text.character_count]
+
+
+ at persistent
+def
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list