├── wiki ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png └── bake-options.png ├── panel-1.0.png ├── old ├── panel images │ ├── panel-0.5v.png │ ├── panel-0.91v.png │ ├── panel-0.93v.png │ ├── panel-0.99v.png │ ├── panel-0.99vRC2.png │ ├── panel-0.99vRC3.png │ └── panel-0.99vRC4.png ├── GXAudioVisualisation0.31.py ├── GXAudioVisualisation0.31_edit_by_Silvea12.py ├── Audio Visualisation0.py ├── GXAudioVisualisation0.2.py └── GXAudioVisualisation0.5.py ├── audio-files-4-testing ├── 10x200-96000-mono.flac ├── 10s0-10000slide-mono.flac ├── 10s0-2000slide-mono.flac └── 10x1000-96000-mono.flac ├── tercja.py ├── README └── GxAV.py /wiki/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/wiki/1.png -------------------------------------------------------------------------------- /wiki/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/wiki/2.png -------------------------------------------------------------------------------- /wiki/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/wiki/3.png -------------------------------------------------------------------------------- /wiki/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/wiki/4.png -------------------------------------------------------------------------------- /wiki/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/wiki/5.png -------------------------------------------------------------------------------- /panel-1.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/panel-1.0.png -------------------------------------------------------------------------------- /wiki/bake-options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/wiki/bake-options.png -------------------------------------------------------------------------------- /old/panel images/panel-0.5v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/old/panel images/panel-0.5v.png -------------------------------------------------------------------------------- /old/panel images/panel-0.91v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/old/panel images/panel-0.91v.png -------------------------------------------------------------------------------- /old/panel images/panel-0.93v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/old/panel images/panel-0.93v.png -------------------------------------------------------------------------------- /old/panel images/panel-0.99v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/old/panel images/panel-0.99v.png -------------------------------------------------------------------------------- /old/panel images/panel-0.99vRC2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/old/panel images/panel-0.99vRC2.png -------------------------------------------------------------------------------- /old/panel images/panel-0.99vRC3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/old/panel images/panel-0.99vRC3.png -------------------------------------------------------------------------------- /old/panel images/panel-0.99vRC4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/old/panel images/panel-0.99vRC4.png -------------------------------------------------------------------------------- /audio-files-4-testing/10x200-96000-mono.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/audio-files-4-testing/10x200-96000-mono.flac -------------------------------------------------------------------------------- /audio-files-4-testing/10s0-10000slide-mono.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/audio-files-4-testing/10s0-10000slide-mono.flac -------------------------------------------------------------------------------- /audio-files-4-testing/10s0-2000slide-mono.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/audio-files-4-testing/10s0-2000slide-mono.flac -------------------------------------------------------------------------------- /audio-files-4-testing/10x1000-96000-mono.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gethiox/GXAudioVisualisation/HEAD/audio-files-4-testing/10x1000-96000-mono.flac -------------------------------------------------------------------------------- /tercja.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | __author__ = "Xevaquor" 4 | 5 | from math import pow, log 6 | 7 | # import numpy as np 8 | # import matplotlib.pyplot as plt 9 | 10 | base = pow(2, (1. / 3)) 11 | 12 | 13 | def compute(xarg): 14 | """ 15 | Computes value of tercja function ignoring set bounds 16 | :param xarg: x argument for func 17 | :return: computed y value 18 | """ 19 | return base ** xarg 20 | 21 | 22 | def compute_inverse(yarg): 23 | """ 24 | Computes inverse of tercja 25 | :param yarg: y argument for func 26 | :return: corresponding x value 27 | """ 28 | # non positive numbers are out of domain of log func 29 | #we are silently ignoring it 30 | if yarg <= 0: 31 | return 0 32 | return log(yarg, base) 33 | 34 | 35 | def get_value_from_x(xx, minimum_x, maximum_x): 36 | """ 37 | Computes value from percentage in interval. For more details please see: 38 | https://github.com/Xevaquor/GXAudioVisualisation/wiki/Tercja 39 | Eg: .42 means 42% 40 | :param xx: Percent in interval. Must be in range [0,1] 41 | :param minimum_x: Lower x bound 42 | :param maximum_x: Upper x bound 43 | :return: corresponding value of Tercja func 44 | """ 45 | assert (0 <= xx <= 1) 46 | return compute(xx * (maximum_x - minimum_x) + minimum_x) 47 | 48 | 49 | if __name__ == "__main__": 50 | print("For usage info please visit: https://github.com/Xevaquor/GXAudioVisualisation/wiki/Tercja") 51 | 52 | # uncomment following for plot 53 | 54 | # steps = 500 55 | # a = 7 56 | # b = 15 57 | # 58 | # assert get_value_from_x(.0 == compute(a), a, b) 59 | # assert get_value_from_x(1. == compute(b), a, b) 60 | # assert get_value_from_x(0.5 == compute((a + b) / 2.), a, b) 61 | # 62 | # x = np.linspace(a, b, steps, True) 63 | # y = compute(x) 64 | # z = [compute_inverse(i) for i in y] 65 | # 66 | # for i, v in enumerate(range(0, 34)): 67 | # print(str(i) + ":" + str(compute(i))) 68 | # 69 | # plt.plot(x, y, lw=3.7, c='orange') 70 | # plt.plot(y, z, lw=3.7, c='purple') 71 | # plt.plot(np.linspace(0, max(y)), np.linspace(0, max(y)), '--k') 72 | # plt.legend(["Tercja", "Inverse of Tercja"]) 73 | # 74 | # plt.show() 75 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | GXAudioVisualisation (GxAV) - Generate Audio Visualization in Blender! 2 | User manual on the wiki - https://github.com/gethiox/GXAudioVisualisation/wiki 3 | Check promotion video! https://youtu.be/cXTEqtcLDKU 4 | 5 | #### 21.08.2014 - 1.0 STABLE \o/ #### 6 | - 'Tercja bake engine' has been fully implemented, many thanks to Xevaquor for tercja.py module! 7 | - again small gui improvements :v 8 | - that's all folks, patches are welcome 9 | 10 | #### 09.08.2014 - 0.99v RC4 #### 11 | - Gui improvements 12 | - removed "freq debug" 13 | - 'Tercja' still isn't implemented :VVV, try to work on it 14 | 15 | #### 30.07.2014 - 0.99v RC3 #### 16 | - added bake progress information 17 | - added 'slash' feature 18 | - 'Tercja' is not yet fully implemented :v 19 | 20 | #### 26.07.2014 - 0.99v RC2 #### 21 | - all known bugs has been fixed \o/ 22 | - added box of 'Bake sound to F-Curves' variables 23 | - Next targets: 24 | * I hope 'TERCJA' baking mode going to stable 25 | * "history bars" feature (http://youtu.be/ZOYp0FfVE4Q) 26 | 27 | #### 25.07.2014 - 0.99v RC1 #### 28 | - few bugs has been repaired 29 | - added new 2 visualisation mode (object, center object) 30 | - code optimilisations 31 | - improved panel usability 32 | 33 | #### 25.07.2014 - 0.93v beta #### 34 | - added 'freq info' feature (for debug) 35 | - a little bit change in panel (and usability, now you don't need to press "init variables" anymore, yay \o/ 36 | 37 | #### 24.07.2014 - 0.92v beta #### 38 | - added dynamically changed driver-power control 39 | - initial implementation of 'professional' bake algorithm, temporarily named "TERCJA", 40 | more info about it: (PL) https://pl.wikipedia.org/wiki/Tercja_(akustyka) 41 | 42 | #### 22.07.2014 - 0.91v beta #### 43 | - reorganized panel 44 | - added Logarithm bake mode (and choose list in panel) 45 | - min/max freq works well 46 | - still a little bit buggy, chaos in the code 47 | - check wiki for using guide 48 | 49 | #### 21.07.2014 - 0.9v beta #### 50 | - initial version of new, re-writed script (very basic features) 51 | - now script can be loaded as addon (acces by properties_window>scene) 52 | - dynamicly changing variables and immediately see results 53 | - script need more features and many optimizations (coming soon) 54 | 55 | #### 11.02.2014 - 0.5v #### 56 | 57 | - added 2 vis-modes - cube_scale and center_cube_scale 58 | - added "debug mode" - additional emptys with frequency in names 59 | - added PANEL!!!! sadfsjfhasfgdsagfagsfjhsfjas 60 | 61 | #### Unknown Date #### 62 | 63 | NOTES: script still must be run in text editor, no addon-mode yet, agrh (api change, bpy.context restrictions 64 | safsfsfa) 65 | I was fighting with it so long… I lose my coding power (my coding power never exist). 66 | 67 | TODO: 68 | - Create GitWiki 69 | - MAKE SCRIPT AS ADDON! 70 | 71 | faaaaaaar future: 72 | - make script as dynamic, change variables refreshing 3d_view 73 | - cycles/internal material create (with fancy options \o/) 74 | - more visualisation options! MORE MORE MORE, still far future. 75 | -------------------------------------------------------------------------------- /old/GXAudioVisualisation0.31.py: -------------------------------------------------------------------------------- 1 | # by Gethiox, CC-BY, pre-beta-alpha version 2 | # version 0.31 3 | # 16.08.2013 4 | 5 | import bpy 6 | 7 | ############# 8 | ### FILES ### 9 | ############# 10 | 11 | """ 12 | # "Bake Sound to F-Curves" doesn't support choosing audio chanels 13 | # from audio files like left or right channel, so if you want to have a 14 | # stereo visualisatnion, then You must separate your stereo audio file 15 | # to two mono files (e.g. in audacity), or You can use same file for 16 | # left and right channel 17 | """ 18 | 19 | # left file chanel ("C:\Folder\music.flac" or "/media/music.ogg") 20 | file_l = "/media/music.ogg" 21 | # right file chanel 22 | file_r = "/media/music.ogg" 23 | 24 | ################# 25 | # basic options # 26 | ################# 27 | 28 | # always when you run script, you must delete 29 | # generated objects before you run script again 30 | 31 | bake = 1 # bake sound to f-curves, 1=yes 0=no, useful for tesing 32 | stereo = 3 # channels to bake, 1=only left, 2=only right, 3=stereo 33 | 34 | value_x = 8 # value of cubes on X axis (must be over 0!) 35 | value_y = 1 # value of cubes on Y axis (must be over 0!) 36 | space_x = 3 # space between objects in X axis (orgins) 37 | space_y = 3 # space betweeb objects in Y axis (orgins) 38 | space_array = 1.3 # value of "Relative Offset" in array modifier, Z axis 39 | scale = [1,0.8,0.5] # Dimensions of the cube (default object) 40 | 41 | s = 1 # Start frame of visualisation 42 | offset = 1 # delay in frames between changes 'count' value of array modificator (jumps, strobe effect) 43 | center_space = 1 # adding some space between right and left row of the visualisation 44 | slash = 0 # adding transform for objects in X axis line, looks like "V" char 45 | 46 | drivmod = 20.0 # driver "amplifier" (Imprecise column height) 47 | low = 200 # min freq, doesn't work yet (removed broken code) 48 | herz = 20000 # max frequency value, dafault 20000 49 | question = 1 # 1-exponential frequency, 2-linear frequency 50 | 51 | # magic, i don't know how exactly it works 52 | # just kidding, I know but I can't explain it 53 | pow = (8/value_x)+1 # parametr for "parabolic with frequency" (?) 54 | 55 | # less important settings 56 | ouu = -1 # offset for emptys in Z axis range 57 | 58 | ######################## 59 | # end of basic options # 60 | ######################## 61 | 62 | def drivering(): 63 | obj = bpy.data.objects[nc + "_" + ny + "_" + nx] 64 | mdf = obj.modifiers['Array'].driver_add('count') 65 | drv = mdf.driver 66 | drv.type = 'AVERAGE' 67 | var = drv.variables.new() 68 | var.name = 'name' 69 | var.type = 'TRANSFORMS' 70 | targ = var.targets[0] 71 | targ.id = bpy.data.objects[no + "_" + ny + "_" + nx] 72 | targ.transform_type = 'SCALE_Z' 73 | targ.bone_target = 'Driver' 74 | fmod = mdf.modifiers[0] 75 | fmod.poly_order = 1 76 | if question == 2: 77 | fmod.coefficients = (0.0, drivmod+(2*(rx+1))) 78 | else: 79 | fmod.coefficients = (0.0, drivmod) 80 | 81 | def curve_modifier(): 82 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[2].modifiers.new('STEPPED') 83 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[2].modifiers.active.frame_step = offset 84 | 85 | ######### 86 | # RIGHT # 87 | ######### 88 | 89 | if stereo == 2 or stereo == 3: 90 | float_rx = 0 + center_space 91 | float_ry = 0 92 | step = 0 93 | start = s 94 | for ry in range(0, value_y): 95 | for rx in range(0, value_x): 96 | bpy.context.scene.frame_current = start 97 | bpy.ops.object.add(location=(float_rx + space_x/2, float_ry, ouu)) 98 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 99 | bpy.context.area.type = 'GRAPH_EDITOR' 100 | step2 = step 101 | if bake == 1: 102 | if question == 1: 103 | step = herz 104 | for what in range (0, value_x-rx): 105 | step = step / pow 106 | bpy.ops.graph.sound_bake(filepath=file_r, low=(step2), high=step) 107 | elif question == 2: 108 | step = (rx+1)*(herz/value_x) 109 | bpy.ops.graph.sound_bake(filepath=file_r, low=(step2), high=step) 110 | bpy.context.area.type = 'TEXT_EDITOR' 111 | nx = rx + 1; nx = str(nx) 112 | ny = ry + 1; ny = str(ny) 113 | no = "obj_R" 114 | bpy.context.active_object.name = (no + "_" + ny + "_" + nx) 115 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[0].hide = True 116 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[1].hide = True 117 | bpy.ops.mesh.primitive_cube_add(location=(float_rx + space_x/2, float_ry, 0)) 118 | bpy.ops.transform.resize(value=(scale[0],scale[1],scale[2])) 119 | bpy.ops.object.transform_apply(scale=True) 120 | nc = "cub_R" 121 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) 122 | if bake == 1: 123 | bpy.ops.object.modifier_add(type='ARRAY') 124 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[0] = 0 125 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[2] = space_array 126 | drivering() 127 | if offset >= 2: 128 | curve_modifier() 129 | float_rx = float_rx+space_x 130 | float_ry = float_ry+slash 131 | float_ry = float_ry+space_y-(slash*value_x) 132 | float_rx = float_rx - space_x * value_x 133 | start = start+offset 134 | step = 0 135 | 136 | ######## 137 | # LEFT # 138 | ######## 139 | 140 | if stereo == 1 or stereo == 3: 141 | float_rx = 0 + center_space 142 | float_ry = 0 143 | step = 0 144 | start = s 145 | for ry in range(0, value_y): 146 | for rx in range(0, value_x): 147 | bpy.context.scene.frame_current = start 148 | bpy.ops.object.add(location=(-float_rx - space_x/2, float_ry, ouu)) 149 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 150 | bpy.context.area.type = 'GRAPH_EDITOR' 151 | step2 = step 152 | if bake == 1: 153 | if question == 1: 154 | step = herz 155 | for what in range (0, value_x-rx): 156 | step = step / pow 157 | bpy.ops.graph.sound_bake(filepath=file_l, low=(step2), high=step) 158 | elif question == 2: 159 | step = (rx+1)*(herz/value_x) 160 | bpy.ops.graph.sound_bake(filepath=file_l, low=(step2), high=step) 161 | bpy.context.area.type = 'TEXT_EDITOR' 162 | nx = rx + 1; nx = str(nx) 163 | ny = ry + 1; ny = str(ny) 164 | no = "obj_L" 165 | bpy.context.active_object.name = (no + "_" + ny + "_" + nx) 166 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[0].hide = True 167 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[1].hide = True 168 | bpy.ops.mesh.primitive_cube_add(location=(-float_rx - space_x/2, float_ry, 0)) 169 | bpy.ops.transform.resize(value=(scale[0],scale[1],scale[2])) 170 | bpy.ops.object.transform_apply(scale=True) 171 | nc = "cub_L" 172 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) 173 | if bake == 1: 174 | bpy.ops.object.modifier_add(type='ARRAY') 175 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[0] = 0 176 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[2] = space_array 177 | drivering() 178 | if offset >= 2: 179 | curve_modifier() 180 | float_rx = float_rx+space_x 181 | float_ry = float_ry+slash 182 | float_ry = float_ry+space_y-(slash*value_x) 183 | float_rx = float_rx - space_x * value_x 184 | start = start+offset 185 | step = 0 186 | -------------------------------------------------------------------------------- /old/GXAudioVisualisation0.31_edit_by_Silvea12.py: -------------------------------------------------------------------------------- 1 | # by Gethiox, CC-BY, pre-beta-alpha version 2 | # version 0.31 3 | # 16.08.2013 4 | 5 | import bpy 6 | 7 | ############# 8 | ### FILES ### 9 | ############# 10 | 11 | """ 12 | # "Bake Sound to F-Curves" doesn't support choosing audio chanels 13 | # from audio files like left or right channel, so if you want to have a 14 | # stereo visualisatnion, then You must separate your stereo audio file 15 | # to two mono files (e.g. in audacity), or You can use same file for 16 | # left and right channel 17 | """ 18 | 19 | # left file chanel ("C:\Folder\music.flac" or "/media/music.ogg") 20 | file_l = "/home/silvea/Downloads/stratum_ext.mp3" 21 | # right file chanel 22 | file_r = "/home/silvea/Downloads/stratum_ext.mp3" 23 | 24 | ################# 25 | # basic options # 26 | ################# 27 | 28 | # always when you run script, you must delete 29 | # generated objects before you run script again 30 | 31 | bake = 1 # bake sound to f-curves, 1=yes 0=no, useful for tesing 32 | stereo = 3 # channels to bake, 1=only left, 2=only right, 3=stereo 33 | 34 | value_x = 64 # value of cubes on X axis (must be over 0!) 35 | value_y = 1 # value of cubes on Y axis (must be over 0!) 36 | space_x = 2 # space between objects in X axis (orgins) 37 | space_y = 2 # space betweeb objects in Y axis (orgins) 38 | space_array = 1.3 # value of "Relative Offset" in array modifier, Z axis 39 | scale = [1,1,0.5] # Dimensions of the cube (default object) 40 | 41 | s = 1 # Start frame of visualisation 42 | offset = 1 # delay in frames between changes 'count' value of array modificator (jumps, strobe effect) 43 | center_space = 1 # adding some space between right and left row of the visualisation 44 | slash = 0 # adding transform for objects in X axis line, looks like "V" char 45 | 46 | drivmod = 100.0 # driver "amplifier" (Imprecise column height) 47 | low = 200 # min freq, doesn't work yet (removed broken code) 48 | herz = 20000 # max frequency value, dafault 20000 49 | 50 | question = 1 # 1-exponential frequency, 2-linear frequency 51 | # magic, i don't know how exactly it works 52 | # just kidding, I know but I can't explain it 53 | pow = (8/value_x)+1 # parametr for "parabolic with frequency" (?) 54 | 55 | # less important settings 56 | ouu = -1 # offset for emptys in Z axis range 57 | 58 | ######################## 59 | # end of basic options # 60 | ######################## 61 | 62 | def drivering(): 63 | obj = bpy.data.objects[nc + "_" + ny + "_" + nx] 64 | mdf = obj.driver_add('scale', 2) 65 | drv = mdf.driver 66 | drv.type = 'AVERAGE' 67 | var = drv.variables.new() 68 | var.name = 'name' 69 | var.type = 'TRANSFORMS' 70 | targ = var.targets[0] 71 | targ.id = bpy.data.objects[no + "_" + ny + "_" + nx] 72 | targ.transform_type = 'SCALE_Z' 73 | targ.bone_target = 'Driver' 74 | fmod = mdf.modifiers[0] 75 | fmod.poly_order = 1 76 | if question == 2: 77 | fmod.coefficients = (0.0, drivmod+(2*(rx+1))) 78 | else: 79 | fmod.coefficients = (0.0, drivmod) 80 | 81 | def curve_modifier(): 82 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[2].modifiers.new('STEPPED') 83 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[2].modifiers.active.frame_step = offset 84 | 85 | ######### 86 | # RIGHT # 87 | ######### 88 | 89 | if stereo == 2 or stereo == 3: 90 | matR = bpy.data.materials.new('visualisationMatR') 91 | float_rx = 0 + center_space 92 | float_ry = 0 93 | step = 0 94 | start = s 95 | for ry in range(0, value_y): 96 | for rx in range(0, value_x): 97 | bpy.context.scene.frame_current = start 98 | bpy.ops.object.add(location=(float_rx + space_x/2, float_ry, ouu)) 99 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 100 | bpy.context.area.type = 'GRAPH_EDITOR' 101 | step2 = step 102 | if bake == 1: 103 | if question == 1: 104 | step = herz 105 | for what in range (0, value_x-rx): 106 | step = step / pow 107 | bpy.ops.graph.sound_bake(filepath=file_r, low=(step2), high=step) 108 | elif question == 2: 109 | step = (rx+1)*(herz/value_x) 110 | bpy.ops.graph.sound_bake(filepath=file_r, low=(step2), high=step) 111 | bpy.context.area.type = 'TEXT_EDITOR' 112 | nx = rx + 1; nx = str(nx) 113 | ny = ry + 1; ny = str(ny) 114 | no = "obj_R" 115 | bpy.context.active_object.name = (no + "_" + ny + "_" + nx) 116 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[0].hide = True 117 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[1].hide = True 118 | bpy.ops.mesh.primitive_cube_add(location=(float_rx + space_x/2, float_ry, 0)) 119 | bpy.ops.transform.resize(value=(scale[0],scale[1],scale[2])) 120 | bpy.ops.object.transform_apply(scale=True) 121 | nc = "cub_R" 122 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) 123 | bpy.context.object.data.materials.append(matR) 124 | cursor = bpy.context.scene.cursor_location[:] 125 | bpy.context.scene.cursor_location = (float_rx + space_x/2, float_ry, -scale[2]) 126 | bpy.ops.object.origin_set(type='ORIGIN_CURSOR') 127 | bpy.context.scene.cursor_location = cursor 128 | if bake == 1: 129 | drivering() 130 | if offset >= 2: 131 | curve_modifier() 132 | float_rx = float_rx+space_x 133 | float_ry = float_ry+slash 134 | float_ry = float_ry+space_y-(slash*value_x) 135 | float_rx = float_rx - space_x * value_x 136 | start = start+offset 137 | step = 0 138 | 139 | ######## 140 | # LEFT # 141 | ######## 142 | 143 | if stereo == 1 or stereo == 3: 144 | matL = bpy.data.materials.new('visualisationMatL') 145 | float_rx = 0 + center_space 146 | float_ry = 0 147 | step = 0 148 | start = s 149 | for ry in range(0, value_y): 150 | for rx in range(0, value_x): 151 | bpy.context.scene.frame_current = start 152 | bpy.ops.object.add(location=(-float_rx - space_x/2, float_ry, ouu)) 153 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 154 | bpy.context.area.type = 'GRAPH_EDITOR' 155 | step2 = step 156 | if bake == 1: 157 | if question == 1: 158 | step = herz 159 | for what in range (0, value_x-rx): 160 | step = step / pow 161 | bpy.ops.graph.sound_bake(filepath=file_l, low=(step2), high=step) 162 | elif question == 2: 163 | step = (rx+1)*(herz/value_x) 164 | bpy.ops.graph.sound_bake(filepath=file_l, low=(step2), high=step) 165 | bpy.context.area.type = 'TEXT_EDITOR' 166 | nx = rx + 1; nx = str(nx) 167 | ny = ry + 1; ny = str(ny) 168 | no = "obj_L" 169 | bpy.context.active_object.name = (no + "_" + ny + "_" + nx) 170 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[0].hide = True 171 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[1].hide = True 172 | bpy.ops.mesh.primitive_cube_add(location=(-float_rx - space_x/2, float_ry, 0)) 173 | bpy.ops.transform.resize(value=(scale[0],scale[1],scale[2])) 174 | bpy.ops.object.transform_apply(scale=True) 175 | nc = "cub_L" 176 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) 177 | bpy.context.object.data.materials.append(matL) 178 | cursor = bpy.context.scene.cursor_location[:] 179 | bpy.context.scene.cursor_location = (-float_rx - space_x/2, float_ry, -scale[2]) 180 | bpy.ops.object.origin_set(type='ORIGIN_CURSOR') 181 | bpy.context.scene.cursor_location = cursor 182 | if bake == 1: 183 | drivering() 184 | if offset >= 2: 185 | curve_modifier() 186 | float_rx = float_rx+space_x 187 | float_ry = float_ry+slash 188 | float_ry = float_ry+space_y-(slash*value_x) 189 | float_rx = float_rx - space_x * value_x 190 | start = start+offset 191 | step = 0 -------------------------------------------------------------------------------- /old/Audio Visualisation0.py: -------------------------------------------------------------------------------- 1 | # little thanks for from #blender 2 | # zmień sobie tylko ścieżki do pliku oraz "value_x" i "value_y" dla kolejno: ilości słupków w rzędzie i ilość rzędów, polecam zacząć od np, 8x4 3 | """ 4 | # comment for you */ < who wrote this? :V 5 | ### comment for me 6 | """ 7 | 8 | import bpy 9 | 10 | ############# 11 | ### FILES ### 12 | ############# 13 | 14 | # dla kanalu lewego, 15 | file_l = "/media/gx-data/Gethiox/Blender/BlenderWork/wizualizator v2/music_left.ogg" 16 | # dla kanalu prawego, 17 | file_r = "/media/gx-data/Gethiox/Blender/BlenderWork/wizualizator v2/music_right.ogg" 18 | # 19 | 20 | 21 | ################# 22 | # basic options # 23 | ################# 24 | 25 | value_x = 32 # 14 ilosc slupkow w rzedzie dla kazdego z kanalow, 26 | value_y = 16 # 4 ilosc slupkow w kolumnie 27 | 28 | bake = 1 # bake sound? 0-no, 1-yes 29 | question = 1 # 1-parabolic, 2-linear 30 | herz = 20000 # max frequency 31 | space_x = 3 # space x 32 | space_y = 3 # space y 33 | space_array = 1.2 # array "z" parametr 34 | ouu = -1 # offset for empty 35 | pow = (8/value_x)+1 ### parabolic "/' value: 2, 1.8, 1.6 etc 36 | 37 | ### pow for value_x==32 = 1.25 38 | ### pow for value_x==16 = 1.5 39 | ### pow for value_x==8 = 2 40 | 41 | scale = [1,0.8,0.5] # xyz cube scale 42 | s = 1 # start keyframe 43 | offset = 1 # delay for animation next columns (1 looks the best) 44 | center_space = 1 # additional center space - left and right chanel 45 | 46 | ################ 47 | # Bake details # 48 | ################ 49 | 50 | filter_blender=False 51 | filter_image=False 52 | filter_movie=True 53 | filter_python=False 54 | filter_font=False 55 | filter_sound=True 56 | filter_text=False 57 | filter_btx=False 58 | filter_collada=False 59 | filter_folder=True 60 | filemode=9 61 | attack=0.5 ### 62 | release=0.2 63 | threshold=0.0 64 | accumulate=False 65 | use_additive=False 66 | square=False 67 | sthreshold=0.1 68 | 69 | """ 70 | DEFAULT: 71 | 72 | filter_blender=False 73 | filter_image=False 74 | filter_movie=True 75 | filter_python=False 76 | filter_font=False 77 | filter_sound=True 78 | filter_text=False 79 | filter_btx=False 80 | filter_collada=False 81 | filter_folder=True 82 | filemode=9 83 | attack=0.015 84 | release=0.2 85 | threshold=0.0 86 | accumulate=False 87 | use_additive=False 88 | square=False 89 | sthreshold=0.1 90 | """ 91 | 92 | ############# 93 | # Podprogram # 94 | ############# 95 | 96 | def drivering(): 97 | rig = bpy.data.objects[nc + "_" + ny + "_" + nx] 98 | fcurve = rig.modifiers['Array'].driver_add('count') 99 | drv = fcurve.driver 100 | drv.type = 'AVERAGE' 101 | 102 | var = drv.variables.new() 103 | var.name = 'name' 104 | var.type = 'TRANSFORMS' 105 | 106 | targ = var.targets[0] 107 | targ.id = bpy.data.objects[no + "_" + ny + "_" + nx] 108 | targ.transform_type = 'SCALE_Z' 109 | targ.bone_target = 'Driver' 110 | 111 | 112 | fmod = fcurve.modifiers[0] 113 | 114 | fmod.poly_order = 1 115 | 116 | 117 | fmod.coefficients = (0.0, 100.0) 118 | 119 | 120 | ############# 121 | # zerowanie # 122 | ############# 123 | 124 | float_rx = 0 + center_space 125 | float_ry = 0 126 | step = 0 127 | start = s 128 | 129 | for ry in range(0, value_y): 130 | for rx in range(0, value_x): 131 | bpy.context.scene.frame_current = start # 132 | 133 | bpy.ops.object.add(location=(float_rx + space_x/2, float_ry, ouu), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) 134 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 135 | 136 | bpy.context.area.type = 'GRAPH_EDITOR' 137 | 138 | step2 = step 139 | if bake == 1: 140 | if question == 1: 141 | step = herz 142 | for what in range (0, value_x-rx): 143 | step = step / pow 144 | 145 | bpy.ops.graph.sound_bake(filepath=file_r, low=(step2+1), high=step, filter_blender=filter_blender, filter_image=filter_image, filter_movie=filter_movie, filter_python=filter_python, filter_font=filter_font, filter_sound=filter_sound, filter_text=filter_text, filter_btx=filter_btx, filter_collada=filter_collada, filter_folder=filter_folder, filemode=filemode, attack=attack, release=release, threshold=threshold, accumulate=accumulate, use_additive=use_additive, square=square, sthreshold=sthreshold) 146 | elif question == 2: 147 | step = (rx+1)*(herz/value_x) 148 | bpy.ops.graph.sound_bake(filepath=file_r, low=(step2+1), high=step, filter_blender=filter_blender, filter_image=filter_image, filter_movie=filter_movie, filter_python=filter_python, filter_font=filter_font, filter_sound=filter_sound, filter_text=filter_text, filter_btx=filter_btx, filter_collada=filter_collada, filter_folder=filter_folder, filemode=filemode, attack=attack, release=release, threshold=threshold, accumulate=accumulate, use_additive=use_additive, square=square, sthreshold=sthreshold) 149 | else: 150 | error 151 | 152 | bpy.context.area.type = 'TEXT_EDITOR' 153 | 154 | nx = rx + 1; nx = str(nx) 155 | ny = ry + 1; ny = str(ny) 156 | no = "obj_R" 157 | bpy.context.active_object.name = (no + "_" + ny + "_" + nx) 158 | 159 | bpy.ops.mesh.primitive_cube_add(location=(float_rx + space_x/2, float_ry, 0), layers=(False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) 160 | bpy.ops.transform.resize(value=(scale[0],scale[1],scale[2])) 161 | bpy.ops.object.transform_apply(scale=True) 162 | 163 | nc = "cub_R" 164 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) 165 | 166 | bpy.ops.object.modifier_add(type='ARRAY') 167 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[0] = 0 168 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[2] = space_array 169 | drivering() 170 | 171 | ################### 172 | bpy.context.area.type = 'GRAPH_EDITOR' 173 | bpy.context.area.type = 'TEXT_EDITOR' 174 | ################### 175 | 176 | float_rx = float_rx+space_x 177 | #### 178 | float_ry = float_ry+space_y 179 | float_rx = float_rx - space_x * value_x 180 | start = start+offset 181 | step = 0 182 | 183 | ###################################### 184 | ###################################### 185 | 186 | float_rx = 0 + center_space 187 | float_ry = 0 188 | step = 0 189 | start = s 190 | 191 | for ry in range(0, value_y): 192 | for rx in range(0, value_x): 193 | bpy.context.scene.frame_current = start # 194 | 195 | bpy.ops.object.add(location=(-float_rx - space_x/2, float_ry, ouu), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) 196 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 197 | 198 | bpy.context.area.type = 'GRAPH_EDITOR' 199 | 200 | step2 = step 201 | if bake == 1: 202 | if question == 1: 203 | step = herz 204 | for what in range (0, value_x-rx): 205 | step = step / pow 206 | 207 | bpy.ops.graph.sound_bake(filepath=file_l, low=(step2+1), high=step, filter_blender=filter_blender, filter_image=filter_image, filter_movie=filter_movie, filter_python=filter_python, filter_font=filter_font, filter_sound=filter_sound, filter_text=filter_text, filter_btx=filter_btx, filter_collada=filter_collada, filter_folder=filter_folder, filemode=filemode, attack=attack, release=release, threshold=threshold, accumulate=accumulate, use_additive=use_additive, square=square, sthreshold=sthreshold) 208 | elif question == 2: 209 | step = (rx+1)*(herz/value_x) 210 | bpy.ops.graph.sound_bake(filepath=file_l, low=(step2+1), high=step, filter_blender=filter_blender, filter_image=filter_image, filter_movie=filter_movie, filter_python=filter_python, filter_font=filter_font, filter_sound=filter_sound, filter_text=filter_text, filter_btx=filter_btx, filter_collada=filter_collada, filter_folder=filter_folder, filemode=filemode, attack=attack, release=release, threshold=threshold, accumulate=accumulate, use_additive=use_additive, square=square, sthreshold=sthreshold) 211 | else: 212 | error 213 | 214 | bpy.context.area.type = 'TEXT_EDITOR' 215 | 216 | nx = rx + 1; nx = str(nx) 217 | ny = ry + 1; ny = str(ny) 218 | no = "obj_L" 219 | bpy.context.active_object.name = (no + "_" + ny + "_" + nx) 220 | 221 | bpy.ops.mesh.primitive_cube_add(location=(-float_rx - space_x/2, float_ry, 0), layers=(False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) 222 | bpy.ops.transform.resize(value=(scale[0],scale[1],scale[2])) 223 | bpy.ops.object.transform_apply(scale=True) 224 | 225 | nc = "cub_L" 226 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) ## thanks for this to from #blender 227 | 228 | bpy.ops.object.modifier_add(type='ARRAY') 229 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[0] = 0 230 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[2] = space_array 231 | drivering() 232 | 233 | ################### 234 | bpy.context.area.type = 'GRAPH_EDITOR' 235 | bpy.context.area.type = 'TEXT_EDITOR' 236 | ################### 237 | 238 | float_rx = float_rx+space_x 239 | #### 240 | float_ry = float_ry+space_y 241 | float_rx = float_rx - space_x * value_x 242 | start = start+offset 243 | step = 0 244 | 245 | step = 0 246 | start = s 247 | float_rx = 0 + center_space 248 | float_ry = 0 249 | 250 | -------------------------------------------------------------------------------- /old/GXAudioVisualisation0.2.py: -------------------------------------------------------------------------------- 1 | # by Gethiox, CC-BY, pre-beta-alpha version 2 | 3 | import bpy 4 | 5 | ############# 6 | ### FILES ### 7 | ############# 8 | 9 | """ 10 | we have two files because blender "not see" mutli chanels in audio files. 11 | You can insert here two chanels, before separate it in e.g. audacity, 12 | or insert original file for two chanel (mono visulation) 13 | 14 | You must have active first and second layer for working script 15 | 16 | please testing with "bake = 0" - it is faster, 17 | or "bake = 1" for testing bake parametrs and final work - it is longer. 18 | """ 19 | 20 | # left file chanel 21 | file_l = "/media/music_left.ogg" 22 | # right file chanel 23 | file_r = "/media/music_right.ogg" 24 | 25 | ################# 26 | # basic options # 27 | ################# 28 | 29 | value_x = 8 # cubes in X axis for one chanel 30 | value_y = 4 # cubes in Y axis for one chanel 31 | 32 | bake = 1 # bake sound? 0-no, 1-yes (for testing "how it looks?") 33 | question = 1 # 1-parabolic frequency, 2-linear (doesn't work!) 34 | space_x = 3 # space for any objects in X axis 35 | space_y = 3 # space for any objects in Y axis 36 | space_array = 1.2 # array space :) (for new, "copying" objects of array) 37 | scale = [1,0.8,0.5] # cube scale 38 | s = 1 # where is start animation? 39 | offset = 2 # delay (frames) for next changes of array (jumps) 40 | center_space = 1 # add center space, left chanel move left, right move right firection 41 | slash = 0 # add move for objects in X axis line, like char "V" looks 42 | drivmod = 100.0 # driver "amplifier" 43 | 44 | # ths valueas are ok 45 | herz = 20000 # max frequency value 46 | pow = (8/value_x)+1 # parametr for "parabolic with frequency" 47 | ouu = -1 # offset for emptys in Z axis range 48 | 49 | ################ 50 | # Bake details # 51 | ################ 52 | 53 | filter_blender=False 54 | filter_image=False 55 | filter_movie=True 56 | filter_python=False 57 | filter_font=False 58 | filter_sound=True 59 | filter_text=False 60 | filter_btx=False 61 | filter_collada=False 62 | filter_folder=True 63 | filemode=9 64 | attack=0.5 ### 65 | release=0.2 66 | threshold=0.0 67 | accumulate=False 68 | use_additive=False 69 | square=False 70 | sthreshold=0.1 71 | 72 | """ 73 | DEFAULT: 74 | 75 | filter_blender=False 76 | filter_image=False 77 | filter_movie=True 78 | filter_python=False 79 | filter_font=False 80 | filter_sound=True 81 | filter_text=False 82 | filter_btx=False 83 | filter_collada=False 84 | filter_folder=True 85 | filemode=9 86 | attack=0.015 87 | release=0.2 88 | threshold=0.0 89 | accumulate=False 90 | use_additive=False 91 | square=False 92 | sthreshold=0.1 93 | """ 94 | 95 | ################ 96 | ################ 97 | ################ 98 | 99 | # add driver and change properties 100 | def drivering(): 101 | obj = bpy.data.objects[nc + "_" + ny + "_" + nx] 102 | mdf = obj.modifiers['Array'].driver_add('count') 103 | drv = mdf.driver 104 | 105 | # change driver type 106 | drv.type = 'AVERAGE' 107 | 108 | var = drv.variables.new() 109 | 110 | # change Variable name 111 | var.name = 'name' 112 | # change Variable type 113 | var.type = 'TRANSFORMS' 114 | 115 | targ = var.targets[0] 116 | targ.id = bpy.data.objects[no + "_" + ny + "_" + nx] 117 | 118 | # change variable transform type 119 | targ.transform_type = 'SCALE_Z' 120 | # change variable target 121 | targ.bone_target = 'Driver' 122 | 123 | fmod = mdf.modifiers[0] 124 | 125 | # change first modifier parametr "Poly Prder" 126 | fmod.poly_order = 1 127 | 128 | # parabolic power for linear bake question 129 | if question == 2: 130 | fmod.coefficients = (0.0, 100+(20*(rx+1))) 131 | 132 | # standard value 133 | else: 134 | fmod.coefficients = (0.0, drivmod) 135 | 136 | # add "stepped" modifier for curve "Z" from sound baking 137 | def curve_modifier(): 138 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[2].modifiers.new('STEPPED') 139 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[2].modifiers.active.frame_step = offset 140 | 141 | 142 | # float_rx - value X axis for insert objects + canter_space - insert "extra" space in center 143 | float_rx = 0 + center_space 144 | # float_ry - value Y axis for insert objects 145 | float_ry = 0 146 | # reset value 147 | step = 0 148 | # set start frame value for float value 149 | start = s 150 | 151 | for ry in range(0, value_y): 152 | for rx in range(0, value_x): 153 | # set start frame for scene 154 | bpy.context.scene.frame_current = start 155 | # add Empty in first layer 156 | bpy.ops.object.add(location=(float_rx + space_x/2, float_ry, ouu), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) 157 | # add scaling keyframe for active scene frame 158 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 159 | 160 | # change to "graph editro" for baking 161 | bpy.context.area.type = 'GRAPH_EDITOR' 162 | 163 | # (bake sound parametrs) step2 for first freq value, step for second freq value 164 | step2 = step 165 | 166 | # bake question 167 | if bake == 1: 168 | # parabolic with frequency 169 | if question == 1: 170 | step = herz 171 | for what in range (0, value_x-rx): 172 | step = step / pow 173 | bpy.ops.graph.sound_bake(filepath=file_r, low=(step2), high=step, filter_blender=filter_blender, filter_image=filter_image, filter_movie=filter_movie, filter_python=filter_python, filter_font=filter_font, filter_sound=filter_sound, filter_text=filter_text, filter_btx=filter_btx, filter_collada=filter_collada, filter_folder=filter_folder, filemode=filemode, attack=attack, release=release, threshold=threshold, accumulate=accumulate, use_additive=use_additive, square=square, sthreshold=sthreshold) 174 | # linear (later with parabolic power in "def drivering():" 175 | elif question == 2: 176 | step = (rx+1)*(herz/value_x) 177 | bpy.ops.graph.sound_bake(filepath=file_r, low=(step2), high=step, filter_blender=filter_blender, filter_image=filter_image, filter_movie=filter_movie, filter_python=filter_python, filter_font=filter_font, filter_sound=filter_sound, filter_text=filter_text, filter_btx=filter_btx, filter_collada=filter_collada, filter_folder=filter_folder, filemode=filemode, attack=attack, release=release, threshold=threshold, accumulate=accumulate, use_additive=use_additive, square=square, sthreshold=sthreshold) 178 | 179 | # back to this text editor 180 | bpy.context.area.type = 'TEXT_EDITOR' 181 | 182 | # create parametrs for name generating 183 | nx = rx + 1; nx = str(nx) 184 | ny = ry + 1; ny = str(ny) 185 | no = "obj_R" 186 | # change active empty name 187 | bpy.context.active_object.name = (no + "_" + ny + "_" + nx) 188 | 189 | # hide curve X and Y 190 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[0].hide = True 191 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[1].hide = True 192 | 193 | # add new cube, scond layer 194 | bpy.ops.mesh.primitive_cube_add(location=(float_rx + space_x/2, float_ry, 0), layers=(False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) 195 | # scaling cube, (scale float parametrs) 196 | bpy.ops.transform.resize(value=(scale[0],scale[1],scale[2])) 197 | # apply scaling (active size is changing for default value 1 in object editor) 198 | bpy.ops.object.transform_apply(scale=True) 199 | 200 | # add nev name parametrs for cube 201 | nc = "cub_R" 202 | # change active cube name 203 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) 204 | 205 | # add "array" modifier, change "copying" parametr for Z axis, set array space 206 | if bake == 1: 207 | bpy.ops.object.modifier_add(type='ARRAY') 208 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[0] = 0 209 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[2] = space_array 210 | drivering() 211 | 212 | 213 | if offset >= 2: 214 | curve_modifier() 215 | 216 | # adding space for loop end (X axis) 217 | float_rx = float_rx+space_x 218 | float_ry = float_ry+slash 219 | 220 | # adding space for loop end (Y axis) 221 | float_ry = float_ry+space_y-(slash*value_x) 222 | # reset float value for next line of objects 223 | float_rx = float_rx - space_x * value_x 224 | # add "frames" value for next line of objects 225 | start = start+offset 226 | step = 0 227 | 228 | ###################################### 229 | 230 | float_rx = 0 + center_space 231 | float_ry = 0 232 | step = 0 233 | start = s 234 | 235 | for ry in range(0, value_y): 236 | for rx in range(0, value_x): 237 | bpy.context.scene.frame_current = start 238 | 239 | bpy.ops.object.add(location=(-float_rx - space_x/2, float_ry, ouu), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) 240 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 241 | 242 | bpy.context.area.type = 'GRAPH_EDITOR' 243 | 244 | step2 = step 245 | if bake == 1: 246 | if question == 1: 247 | step = herz 248 | for what in range (0, value_x-rx): 249 | step = step / pow 250 | 251 | bpy.ops.graph.sound_bake(filepath=file_l, low=(step2), high=step, filter_blender=filter_blender, filter_image=filter_image, filter_movie=filter_movie, filter_python=filter_python, filter_font=filter_font, filter_sound=filter_sound, filter_text=filter_text, filter_btx=filter_btx, filter_collada=filter_collada, filter_folder=filter_folder, filemode=filemode, attack=attack, release=release, threshold=threshold, accumulate=accumulate, use_additive=use_additive, square=square, sthreshold=sthreshold) 252 | elif question == 2: 253 | step = (rx+1)*(herz/value_x) 254 | bpy.ops.graph.sound_bake(filepath=file_l, low=(step2), high=step, filter_blender=filter_blender, filter_image=filter_image, filter_movie=filter_movie, filter_python=filter_python, filter_font=filter_font, filter_sound=filter_sound, filter_text=filter_text, filter_btx=filter_btx, filter_collada=filter_collada, filter_folder=filter_folder, filemode=filemode, attack=attack, release=release, threshold=threshold, accumulate=accumulate, use_additive=use_additive, square=square, sthreshold=sthreshold) 255 | 256 | bpy.context.area.type = 'TEXT_EDITOR' 257 | 258 | nx = rx + 1; nx = str(nx) 259 | ny = ry + 1; ny = str(ny) 260 | no = "obj_L" 261 | bpy.context.active_object.name = (no + "_" + ny + "_" + nx) 262 | 263 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[0].hide = True 264 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[1].hide = True 265 | 266 | bpy.ops.mesh.primitive_cube_add(location=(-float_rx - space_x/2, float_ry, 0), layers=(False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) 267 | bpy.ops.transform.resize(value=(scale[0],scale[1],scale[2])) 268 | bpy.ops.object.transform_apply(scale=True) 269 | 270 | nc = "cub_L" 271 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) 272 | 273 | if bake == 1: 274 | bpy.ops.object.modifier_add(type='ARRAY') 275 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[0] = 0 276 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[2] = space_array 277 | drivering() 278 | if offset >= 2: 279 | curve_modifier() 280 | float_rx = float_rx+space_x 281 | float_ry = float_ry+slash 282 | 283 | float_ry = float_ry+space_y-(slash*value_x) 284 | float_rx = float_rx - space_x * value_x 285 | start = start+offset 286 | step = 0 287 | 288 | step = 0 289 | start = s 290 | float_rx = 0 + center_space 291 | float_ry = 0 292 | -------------------------------------------------------------------------------- /old/GXAudioVisualisation0.5.py: -------------------------------------------------------------------------------- 1 | # License: GPLv3 2 | # Version: 0.5 3 | # Relase Date: 11.02.2014 4 | 5 | import bpy 6 | from bpy.props import * 7 | from math import * 8 | #from bpy.types import Operator 9 | #from bpy.props import FloatVectorProperty, FloatProperty 10 | 11 | """ 12 | GXAudioVisualisation - Blender Music Visualizer 13 | Copyright (C) 2013 Sławomir Kur (Gethiox) 14 | 15 | This program is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as published by 17 | the Free Software Foundation, either version 3 of the License, or 18 | (at your option) any later version. 19 | 20 | This program is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with this program. If not, see http://www.gnu.org/licenses/ 27 | """ 28 | 29 | bl_info = { 30 | "name": "GXAudioVisualisation", 31 | "author": "Sławomir Kur (Gethiox)", 32 | "version": (0, 5), 33 | "blender": (2, 6, 0), 34 | "location": "View3D > Tools menu", 35 | "description": "Bake Spectrum Visualizer with sound file", 36 | "category": "Animation", 37 | "wiki_url": "https://github.com/gethiox/GXAudioVisualisation/wiki", 38 | "tracker_url": ""} 39 | 40 | def initSceneProperties(scn): 41 | bpy.types.Scene.Bake = BoolProperty( 42 | name = "Bake", 43 | description = "Bake animation from file") 44 | scn['Bake'] = False 45 | 46 | bpy.types.Scene.Debug = BoolProperty( 47 | name = "Freq Info", 48 | description = "Create additional emptys with frequency information") 49 | scn['Debug'] = False 50 | 51 | bpy.types.Scene.Channels = EnumProperty( 52 | items = [('0', 'Both', 'Left and Right channel'), 53 | ('1', 'Left', 'Left channel'), 54 | ('2', 'Right', 'Right channel')], 55 | name = "Channels") 56 | scn['Channels'] = 0 57 | 58 | bpy.types.Scene.Mode = EnumProperty( 59 | items = [('0', 'Array', 'Array modifier visualisation based'), 60 | ('1', 'Cube Scale', 'Cube with scaling in bottom'), 61 | ('2', 'Center Cube Scale', 'Cube with scaling in center')], 62 | name = "Based-Mode") 63 | scn['Mode'] = 0 64 | 65 | bpy.types.Scene.LeftFile = StringProperty( 66 | name = "Left File", 67 | #default = "", 68 | description = "Define path of the left channel file", 69 | subtype = 'FILE_PATH') 70 | 71 | bpy.types.Scene.RightFile = StringProperty( 72 | name = "Right File", 73 | #default = "", 74 | description = "Define path of the right channel file", 75 | subtype = 'FILE_PATH') 76 | 77 | bpy.types.Scene.value_x = IntProperty( 78 | name = "Count X", 79 | default = 8, 80 | soft_min = 1, 81 | soft_max = 32, 82 | description = "Enter an integer") 83 | scn['value_x'] = 8 84 | 85 | bpy.types.Scene.value_y = IntProperty( 86 | name = "Count Y", 87 | default = 1, 88 | soft_min = 1, 89 | soft_max = 32, 90 | description = "Enter an integer") 91 | scn['value_y'] = 1 92 | 93 | bpy.types.Scene.space_x = FloatProperty( 94 | name = "Space X", 95 | description = "Space between objects orgins in X axis", 96 | default = 3.0, 97 | min = 0,) 98 | scn['space_x'] = 3.0 99 | 100 | bpy.types.Scene.space_y = FloatProperty( 101 | name = "Space Y", 102 | description = "Space between objects orgins in Y axis", 103 | default = 3.0, 104 | min = 0,) 105 | scn['space_y'] = 3.0 106 | 107 | bpy.types.Scene.space_array = FloatProperty( 108 | name = "Array Relative Offet", 109 | description = "Array Modifier Relative Offet", 110 | default = 1.3, 111 | min = 0,) 112 | scn['space_array'] = 1.3 113 | 114 | bpy.types.Scene.scale_x = FloatProperty( 115 | name = "X", 116 | description = "Dimensions of the cube (default object)", 117 | default = 1.0, 118 | min = 0,) 119 | scn['scale_x'] = 1.0 120 | 121 | bpy.types.Scene.scale_y = FloatProperty( 122 | name = "Y", 123 | description = "Dimensions of the cube (default object)", 124 | default = 0.8, 125 | min = 0,) 126 | scn['scale_y'] = 0.8 127 | 128 | bpy.types.Scene.scale_z = FloatProperty( 129 | name = "Z", 130 | description = "Dimensions of the cube (default object)", 131 | default = 0.5, 132 | min = 0,) 133 | scn['scale_z'] = 0.5 134 | 135 | bpy.types.Scene.start_frame = IntProperty( 136 | name = "Start Frame", 137 | default = 1, 138 | soft_min = 0, 139 | description = "Start frame of isualization") 140 | scn['start_frame'] = 1 141 | 142 | 143 | bpy.types.Scene.attack = FloatProperty( 144 | name = "attack", 145 | description = "attack", 146 | default = 0.005, 147 | min = 0,) 148 | scn['attack'] = 0.005 149 | 150 | bpy.types.Scene.release = FloatProperty( 151 | name = "release", 152 | description = "release", 153 | default = 0.2, 154 | min = 0,) 155 | scn['release'] = 0.2 156 | 157 | bpy.types.Scene.threshold = FloatProperty( 158 | name = "threshold", 159 | description = "threshold", 160 | default = 0.0, 161 | min = 0,) 162 | scn['threshold'] = 0.0 163 | 164 | bpy.types.Scene.sthreshold = FloatProperty( 165 | name = "sthreshold", 166 | description = "sthreshold", 167 | default = 0.5, 168 | min = 0,) 169 | scn['sthreshold'] = 0.5 170 | 171 | bpy.types.Scene.use_accumulate = BoolProperty( 172 | name = "accumulate", 173 | description = "accumulate") 174 | scn['use_accumulate'] = False 175 | 176 | bpy.types.Scene.use_additive = BoolProperty( 177 | name = "additive", 178 | description = "additive") 179 | scn['use_additive'] = False 180 | 181 | bpy.types.Scene.use_square = BoolProperty( 182 | name = "square", 183 | description = "square") 184 | scn['use_square'] = False 185 | 186 | bpy.types.Scene.offset = IntProperty( 187 | name = "Jumps Frames", 188 | default = 1, 189 | soft_min = 1, 190 | description = "delay in frames between changes 'count' value of array modificator (jumps, strobe effect)") 191 | scn['offset'] = 1 192 | 193 | bpy.types.Scene.center_space = FloatProperty( 194 | name = "Segments Space", 195 | default = 1.0, 196 | min = 0, 197 | description = "Additional space between left and right channel segments") 198 | scn['center_space'] = 1.0 199 | 200 | bpy.types.Scene.FreqMode = EnumProperty( 201 | items = [('0', 'Logarithm', 'log'), 202 | ('1', 'Linear', 'linear')], 203 | name = "Frequency Mode") 204 | scn['FreqMode'] = 0 205 | 206 | bpy.types.Scene.drivmod = FloatProperty( 207 | name = "Driver Power", 208 | description = "driver 'amplifier' - Imprecise column height", 209 | default = 20.0, 210 | min = 1,) 211 | scn['drivmod'] = 20.0 212 | 213 | bpy.types.Scene.slash = FloatProperty( 214 | name = "Slash", 215 | default = 0.0, 216 | min = 0, 217 | description = "additional transform for objects in X axis line, looks like 'V' char") 218 | scn['slash'] = 0.0 219 | 220 | bpy.types.Scene.max_herz = IntProperty( 221 | name = "Maximum Frequency", 222 | default = 20000, 223 | soft_min = 0, 224 | description = "max frequency value to analyze, dafault 20000") 225 | scn['max_herz'] = 20000 226 | 227 | bpy.types.Scene.slash_rotate = BoolProperty( 228 | name = "slash rotate", 229 | description = "additional rotation for object when slash option is used") 230 | scn['slash_rotate'] = False 231 | 232 | 233 | class GXAudioVisualisationPanel(bpy.types.Panel): 234 | """Creates a Panel in the scene context of the properties editor""" 235 | bl_label = "GXAudioVisualisation" 236 | bl_idname = "SCENE_PT_layout" 237 | bl_space_type = 'VIEW_3D' 238 | bl_region_type = 'TOOLS' 239 | 240 | def draw(self, context): 241 | scene = context.scene 242 | 243 | layout = self.layout 244 | row = layout.row() 245 | row.operator("scene.bake_visualisation", text="Create Visualizer", icon="RADIO") 246 | row = layout.row() 247 | row.prop(scn, 'Bake') 248 | row.prop(scn, 'Debug') 249 | 250 | box = layout.box() 251 | box.label("Channels to bake and audio files path:") 252 | box.prop(scn, 'Channels') 253 | box.prop(scn, 'LeftFile') 254 | box.prop(scn, 'RightFile') 255 | 256 | row = layout.row() 257 | row = layout.row() 258 | row.prop(scn, 'Mode') 259 | row = layout.row() 260 | row.prop(scn, 'FreqMode') 261 | 262 | split = layout.split() 263 | 264 | col = split.column(align=True) 265 | col.label(text="Objects Grid") 266 | col.prop(scn, 'value_x') 267 | col.prop(scn, 'value_y') 268 | 269 | col = split.column(align=True) 270 | col.label(text="Space Between Objects") 271 | col.prop(scn, 'space_x') 272 | col.prop(scn, 'space_y') 273 | 274 | split = layout.split() 275 | row = layout.row() 276 | row.prop(scn, 'center_space') 277 | row = layout.row() 278 | row.prop(scn, 'slash') 279 | row.prop(scn, 'slash_rotate') 280 | 281 | row = layout.row(align=True) 282 | row.label(text="Object Scale:") 283 | row.prop(scn, 'scale_x') 284 | row.prop(scn, 'scale_y') 285 | row.prop(scn, 'scale_z') 286 | 287 | row = layout.row() 288 | row.prop(scn, 'space_array') 289 | 290 | row = layout.row() 291 | row.prop(scn, 'start_frame') 292 | row.prop(scn, 'offset') 293 | 294 | row = layout.row() 295 | row.prop(scn, 'drivmod') 296 | row = layout.row() 297 | row.prop(scn, 'max_herz') 298 | 299 | row = layout.row() 300 | box = layout.box() 301 | box.label(text="'Bake Sound to F-Curves' function options:") 302 | split = box.split() 303 | col = split.column(align=True) 304 | col.prop(scn, 'attack') 305 | col.prop(scn, 'release') 306 | col = split.column(align=True) 307 | col.prop(scn, 'threshold') 308 | col.prop(scn, 'sthreshold') 309 | split = box.split() 310 | col = split.column() 311 | 312 | col.prop(scn, 'use_accumulate') 313 | col = split.column() 314 | col.prop(scn, 'use_additive') 315 | col = split.column() 316 | col.prop(scn, 'use_square') 317 | 318 | scn = bpy.context.scene 319 | initSceneProperties(bpy.context.scene); 320 | 321 | class GXAudioVisualisation(bpy.types.Operator): 322 | bl_idname = 'scene.bake_visualisation' 323 | bl_label = 'bake_visualisation' 324 | bl_description = 'bake_visualisation' 325 | bl_options = {'REGISTER', 'UNDO'} 326 | 327 | def execute(self, context): 328 | bake(); 329 | return{'FINISHED'} 330 | 331 | def bake(): 332 | low = 0 # min freq, doesn't work yet (removed broken code, disabled) 333 | ouu = -2 # offset for emptys in Z axis range (nothing important to modify) 334 | 335 | if scn['Channels'] == 1: 336 | loop_count = 1; kanau = 1 337 | elif scn['Channels'] == 2: 338 | loop_count = 1; kanau = 2 339 | elif scn['Channels'] == 0: 340 | loop_count = 2; 341 | 342 | stereo_memory = scn['Channels'] 343 | for loop in range(0, loop_count): 344 | if scn['Channels'] == 0 and loop == 0: kanau = 1 345 | if scn['Channels'] == 0 and loop == 1: kanau = 2 346 | 347 | float_rx = 0 + scn['center_space'] 348 | float_ry = 0 349 | start = scn['start_frame'] 350 | for ry in range(0, scn['value_y']): 351 | step2 = low 352 | for rx in range(0, scn['value_x']): 353 | bpy.context.scene.frame_current = start 354 | if kanau == 1: bpy.ops.object.empty_add(type='SPHERE', location=(-float_rx - scn['space_x']/2, float_ry, ouu)); 355 | elif kanau == 2: bpy.ops.object.empty_add(type='SPHERE', location=(float_rx + scn['space_x']/2, float_ry, ouu)); 356 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 357 | step1 = step2 358 | if scn['FreqMode'] == 0: 359 | step2 = scn['max_herz'] 360 | for what in range (0, scn['value_x']-rx-1): 361 | step2 = step2 / ((8/scn['value_x'])+1) 362 | if rx == 0: #additional module for correct math range problem, but not so fine 363 | step1 = step2 / ((8/scn['value_x'])+1) 364 | #step2 = step2 / 2 365 | elif scn['FreqMode'] == 1: 366 | step2 = (rx+1)*(scn['max_herz']/scn['value_x']) 367 | if scn['Bake'] == True: 368 | bpy.context.area.type = 'GRAPH_EDITOR' 369 | if kanau == 1: bpy.ops.graph.sound_bake(filepath=scn['LeftFile'],\ 370 | low=step1,\ 371 | high=step2,\ 372 | attack=scn['attack'],\ 373 | release=scn['release'],\ 374 | threshold=scn['threshold'],\ 375 | use_accumulate=scn['use_accumulate'],\ 376 | use_additive=scn['use_additive'],\ 377 | use_square=scn['use_square'],\ 378 | sthreshold=scn['sthreshold']) 379 | elif kanau == 2: bpy.ops.graph.sound_bake(filepath=scn['RightFile'],\ 380 | low=step1,\ 381 | high=step2,\ 382 | attack=scn['attack'],\ 383 | release=scn['release'],\ 384 | threshold=scn['threshold'],\ 385 | use_accumulate=scn['use_accumulate'],\ 386 | use_additive=scn['use_additive'],\ 387 | use_square=scn['use_square'],\ 388 | sthreshold=scn['sthreshold']) 389 | bpy.context.area.type = 'VIEW_3D' 390 | nx = rx + 1; nx = str(nx) 391 | ny = ry + 1; ny = str(ny) 392 | if kanau == 1: no = "obj_L" 393 | elif kanau == 2: no = "obj_R" 394 | bpy.context.active_object.name = (no + "_" + ny + "_" + nx) 395 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[0].hide = True 396 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[1].hide = True 397 | 398 | if scn['Mode'] == 0: 399 | if kanau == 1: bpy.ops.mesh.primitive_cube_add(location=(-float_rx - scn['space_x']/2, float_ry, 0)) 400 | elif kanau == 2: bpy.ops.mesh.primitive_cube_add(location=(float_rx + scn['space_x']/2, float_ry, 0)) 401 | bpy.ops.transform.resize(value=(scn['scale_x'],scn['scale_y'],scn['scale_z'])) 402 | bpy.ops.object.transform_apply(scale=True) 403 | if scn['slash'] >= 0.0 and scn['slash_rotate'] == True: 404 | face = pow(scn['space_x'],2) + pow(scn['slash'],2) 405 | face = sqrt(face) 406 | iks = scn['slash']/face 407 | iks = asin(iks) 408 | if kanau == 1: bpy.ops.transform.rotate(value=-iks, axis=(0,0,1)) 409 | elif kanau == 2: bpy.ops.transform.rotate(value=iks, axis=(0,0,1)) 410 | if kanau == 1: nc = "cub_L" 411 | elif kanau == 2: nc = "cub_R" 412 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) 413 | bpy.ops.object.modifier_add(type='ARRAY') 414 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[0] = 0 415 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[2] = scn['space_array'] 416 | obj = bpy.data.objects[nc + "_" + ny + "_" + nx] #def drivering 417 | mdf = obj.modifiers['Array'].driver_add('count') 418 | drv = mdf.driver 419 | drv.type = 'AVERAGE' 420 | var = drv.variables.new() 421 | var.name = 'name' 422 | var.type = 'TRANSFORMS' 423 | targ = var.targets[0] 424 | targ.id = bpy.data.objects[no + "_" + ny + "_" + nx] 425 | targ.transform_type = 'SCALE_Z' 426 | targ.bone_target = 'Driver' 427 | fmod = mdf.modifiers[0] 428 | fmod.poly_order = 1 429 | if scn['FreqMode'] == 0: 430 | fmod.coefficients = (0.0, scn['drivmod']) 431 | elif scn['FreqMode'] == 1: 432 | #fmod.coefficients = (0.0, scn['drivmod']+(2*(rx+1))): 433 | fmod.coefficients = (0.0, scn['drivmod']) 434 | elif scn['Mode'] == 1 or scn['Mode'] == 2: 435 | if kanau == 1: bpy.ops.mesh.primitive_cube_add(location=(-float_rx - scn['space_x']/2, float_ry, 0)) 436 | elif kanau == 2: bpy.ops.mesh.primitive_cube_add(location=(float_rx + scn['space_x']/2, float_ry, 0)) 437 | bpy.context.scene.cursor_location = bpy.context.active_object.location 438 | bpy.ops.transform.resize(value=(scn['scale_x'],scn['scale_y'],scn['scale_z'])) 439 | if scn['slash'] >= 0.0 and scn['slash_rotate'] == True: 440 | face = pow(scn['space_x'],2) + pow(scn['slash'],2) 441 | face = sqrt(face) 442 | iks = scn['slash']/face 443 | iks = asin(iks) 444 | if kanau == 1: bpy.ops.transform.rotate(value=-iks, axis=(0,0,1)) 445 | elif kanau == 2: bpy.ops.transform.rotate(value=iks, axis=(0,0,1)) 446 | bpy.ops.object.transform_apply(scale=True) 447 | if scn['Mode'] == 1: 448 | bpy.ops.transform.transform(value=(0, 0, scn['scale_z'], 0)) 449 | bpy.ops.object.origin_set(type='ORIGIN_CURSOR') 450 | if kanau == 1: nc = "cub_L" 451 | elif kanau == 2: nc = "cub_R" 452 | bpy.context.active_object.name = (nc + "_" + ny + "_" + nx) 453 | obj = bpy.data.objects[nc + "_" + ny + "_" + nx] #def drivering 454 | mdf = obj.driver_add('scale', 2) 455 | drv = mdf.driver 456 | drv.type = 'AVERAGE' 457 | var = drv.variables.new() 458 | var.name = 'name' 459 | var.type = 'TRANSFORMS' 460 | targ = var.targets[0] 461 | targ.id = bpy.data.objects[no + "_" + ny + "_" + nx] 462 | targ.transform_type = 'SCALE_Z' 463 | targ.bone_target = 'Driver' 464 | fmod = mdf.modifiers[0] 465 | fmod.poly_order = 1 466 | if scn['FreqMode'] == 0: 467 | fmod.coefficients = (0.0, scn['drivmod']) 468 | elif scn['FreqMode'] == 1: 469 | #fmod.coefficients = (0.0, scn['drivmod']+(2*(rx+1))): 470 | fmod.coefficients = (0.0, scn['drivmod']) 471 | 472 | if scn['offset'] >= 2: 473 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[2].modifiers.new('STEPPED') 474 | bpy.data.objects[no + "_" + ny + "_" + nx].animation_data.action.fcurves[2].modifiers.active.frame_step = scn['offset'] 475 | 476 | if scn['Debug'] == True and ry == 0: 477 | ds1 = round(step1,2); ds1 = str(ds1) 478 | ds2 = round(step2,2); ds2 = str(ds2) 479 | if kanau == 1: 480 | bpy.ops.object.empty_add(location=(-float_rx - scn['space_x']/2, float_ry, ouu*2)); 481 | bpy.context.active_object.name = ("L " + ds1 + "Hz - " + ds2 + "Hz"); 482 | elif kanau == 2: 483 | bpy.ops.object.empty_add(location=(float_rx + scn['space_x']/2, float_ry, ouu*2)); 484 | bpy.context.active_object.name = ("R "+ ds1 + "Hz - " + ds2 + "Hz"); 485 | 486 | float_rx = float_rx+scn['space_x'] 487 | float_ry = float_ry+scn['slash'] 488 | float_ry = float_ry+scn['space_y']-(scn['slash']*scn['value_x']) 489 | float_rx = float_rx - scn['space_x'] * scn['value_x'] 490 | start = start + scn['offset'] 491 | 492 | def register(): 493 | bpy.utils.register_class(GXAudioVisualisationPanel) 494 | bpy.utils.register_class(GXAudioVisualisation) 495 | 496 | def unregister(): 497 | bpy.utils.unregister_class(GXAudioVisualisationPanel) 498 | bpy.utils.unregister_class(GXAudioVisualisation) 499 | 500 | if __name__ == "__main__": 501 | register() 502 | -------------------------------------------------------------------------------- /GxAV.py: -------------------------------------------------------------------------------- 1 | """ 2 | GXAudioVisualisation - Blender Music Visualizer 3 | Copyright (C) 2013 Sławomir Kur (Gethiox) 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/ 17 | """ 18 | 19 | bl_info = { 20 | "name": "GxAV", 21 | "author": "Sławomir Kur (Gethiox)", 22 | "version": (1, 0), 23 | "blender": (2, 7, 1), 24 | "location": "Properties > Scene", 25 | "description": "Bake Spectrum Visualizer by sound file", 26 | "category": "Animation", 27 | "wiki_url": "https://github.com/gethiox/GXAudioVisualisation/wiki", 28 | "tracker_url": "https://github.com/gethiox/GXAudioVisualisation/issues"} 29 | 30 | import bpy 31 | import math 32 | 33 | #__author__ = "Xevaquor" 34 | 35 | base = math.pow(2, (1. / 3)) 36 | 37 | def compute(xarg): 38 | """ 39 | Computes value of tercja function ignoring set bounds 40 | :param xarg: x argument for func 41 | :return: computed y value 42 | """ 43 | return base ** xarg 44 | 45 | def compute_inverse(yarg): 46 | """ 47 | Computes inverse of tercja 48 | :param yarg: y argument for func 49 | :return: corresponding x value 50 | """ 51 | # non positive numbers are out of domain of log func 52 | #we are silently ignoring it 53 | if yarg <= 0: 54 | return 0 55 | return math.log(yarg, base) 56 | 57 | 58 | def get_value_from_x(xx, minimum_x, maximum_x): 59 | """ 60 | Computes value from percentage in interval. For more details please see: 61 | https://github.com/Xevaquor/GXAudioVisualisation/wiki/Tercja 62 | Eg: .42 means 42% 63 | :param xx: Percent in interval. Must be in range [0,1] 64 | :param minimum_x: Lower x bound 65 | :param maximum_x: Upper x bound 66 | :return: corresponding value of Tercja func 67 | """ 68 | assert (0 <= xx <= 1) 69 | return compute(xx * (maximum_x - minimum_x) + minimum_x) 70 | 71 | #\__author__ = "Xevaquor" 72 | 73 | def initprop(): 74 | bpy.types.Scene.gx_slash_rotate = bpy.props.BoolProperty( 75 | name = "Rotation", 76 | description = "Slash Rotation", 77 | update=update_slash) 78 | 79 | bpy.types.Scene.gx_slash = bpy.props.FloatProperty( 80 | name = "Slash", 81 | default = 0.0, 82 | description = "Enter an float", 83 | update=update_slash) 84 | 85 | bpy.types.Scene.gx_zenit = bpy.props.BoolProperty( 86 | name = "Zenit", 87 | description = "Zenit") 88 | 89 | bpy.types.Scene.gx_accumulate = bpy.props.BoolProperty( 90 | name = "Accumulate", 91 | description = "Accumulate") 92 | 93 | bpy.types.Scene.gx_additive = bpy.props.BoolProperty( 94 | name = "Use additive", 95 | description = "Use additive") 96 | 97 | bpy.types.Scene.gx_square = bpy.props.BoolProperty( 98 | name = "Square", 99 | description = "Square") 100 | 101 | bpy.types.Scene.gx_sthreshold = bpy.props.FloatProperty( 102 | name = "Sthreshold", 103 | default = 0.1) 104 | 105 | bpy.types.Scene.gx_threshold = bpy.props.FloatProperty( 106 | name = "Threshold", 107 | default = 0.0) 108 | 109 | bpy.types.Scene.gx_release = bpy.props.FloatProperty( 110 | name = "Release", 111 | default = 0.2) 112 | 113 | bpy.types.Scene.gx_attack = bpy.props.FloatProperty( 114 | name = "Attack", 115 | default = 0.005) 116 | 117 | bpy.types.Scene.gx_cube_scale_x = bpy.props.FloatProperty( 118 | name = "Scale X", 119 | default = 1.0, 120 | min = 0, 121 | step = 1, 122 | precision = 2, 123 | description = "Enter an float", 124 | update=update_scale) 125 | 126 | bpy.types.Scene.gx_cube_scale_y = bpy.props.FloatProperty( 127 | name = "Scale Y", 128 | default = 1.0, 129 | min = 0, 130 | step = 1, 131 | precision = 2, 132 | description = "Enter an float", 133 | update=update_scale) 134 | 135 | bpy.types.Scene.gx_cube_scale_z = bpy.props.FloatProperty( 136 | name = "Scale Z", 137 | default = 5.6, 138 | min = 0, 139 | step = 1, 140 | precision = 2, 141 | description = "Enter an float", 142 | update=update_scale) 143 | 144 | bpy.types.Scene.gx_type = bpy.props.EnumProperty( 145 | items = [('0', 'Array', 'array'), 146 | ('1', 'Object scaling', 'object'), 147 | ('2', 'Center object scaling', 'center_object')], 148 | name = "Visualisation Type", 149 | update=update_channels) 150 | 151 | bpy.types.Scene.gx_freq_debug = bpy.props.BoolProperty( 152 | name = "Freq Debug", 153 | description = "Enter an bool lul") 154 | 155 | bpy.types.Scene.gx_driver_power = bpy.props.FloatProperty( 156 | name = "Driver Power", 157 | default = 20.0, 158 | min = 0, 159 | step = 5, 160 | precision = 2, 161 | description = "Enter an float", 162 | update=update_drivers3) 163 | 164 | bpy.types.Scene.gx_mode = bpy.props.EnumProperty( 165 | items = [('0', 'Logarithm', 'log'), 166 | ('1', 'Linear', 'linear'), 167 | ('2', 'Tercja (recomended)', 'tercja')], 168 | name = "Frequency Mode") 169 | 170 | bpy.types.Scene.gx_min_freq = bpy.props.FloatProperty( 171 | name = "Min Freq", 172 | default = 100.0, 173 | min = 0, 174 | step = 1000, 175 | precision = 2, 176 | description = "Enter an float") 177 | 178 | bpy.types.Scene.gx_max_freq = bpy.props.FloatProperty( 179 | name = "Max Freq", 180 | default = 20000.0, 181 | min = 0, 182 | step = 1000, 183 | precision = 2, 184 | description = "Enter an float") 185 | 186 | bpy.types.Scene.gx_space_array = bpy.props.FloatProperty( 187 | name = "Space Array", 188 | default = 1.5, 189 | min = 0, 190 | step = 1, 191 | precision = 2, 192 | description = "Enter an float", 193 | update=update_space_array) 194 | 195 | bpy.types.Scene.gx_start = bpy.props.IntProperty( 196 | name = "Start Frame", 197 | default = 1, 198 | min = 1, 199 | description = "Enter an integer") 200 | 201 | bpy.types.Scene.gx_left_file = bpy.props.StringProperty( 202 | name = "Left File", 203 | #default = "", 204 | description = "Define path of the left channel file", 205 | subtype = 'FILE_PATH') 206 | 207 | bpy.types.Scene.gx_right_file = bpy.props.StringProperty( 208 | name = "Right File", 209 | #default = "", 210 | description = "Define path of the right channel file", 211 | subtype = 'FILE_PATH') 212 | 213 | bpy.types.Scene.gx_scale_x = bpy.props.FloatProperty( 214 | name = "Scale X", 215 | default = 0.7, 216 | min = 0, 217 | step = 1, 218 | precision = 2, 219 | description = "Enter an float", 220 | update=update_scale) 221 | 222 | bpy.types.Scene.gx_scale_y = bpy.props.FloatProperty( 223 | name = "Scale Y", 224 | default = 0.6, 225 | min = 0, 226 | step = 1, 227 | precision = 2, 228 | description = "Enter an float", 229 | update=update_scale) 230 | 231 | bpy.types.Scene.gx_scale_z = bpy.props.FloatProperty( 232 | name = "Scale Z", 233 | default = 0.4, 234 | min = 0, 235 | step = 1, 236 | precision = 2, 237 | description = "Enter an float", 238 | update=update_scale) 239 | 240 | bpy.types.Scene.gx_channels = bpy.props.EnumProperty( 241 | items = [('0', 'Stereo', 'Left and Right channel'), 242 | ('1', 'Left', 'Left channel'), 243 | ('2', 'Right', 'Right channel')], 244 | name = "Channels", 245 | update=update_channels) 246 | 247 | bpy.types.Scene.gx_center_space = bpy.props.FloatProperty( 248 | name = "Center Space", 249 | default = 2.0, 250 | min = 0, 251 | description = "Enter an float", 252 | update=update_space_x) 253 | 254 | bpy.types.Scene.gx_space_x = bpy.props.FloatProperty( 255 | name = "Space X", 256 | default = 2.0, 257 | min = 0, 258 | step = 1, 259 | precision = 2, 260 | description = "Enter an float", 261 | update=update_space_x) 262 | 263 | bpy.types.Scene.gx_count_x = bpy.props.IntProperty( 264 | name = "Count X", 265 | default = 5, 266 | min = 1, 267 | options={'ANIMATABLE'}, 268 | description = "Enter an integer", 269 | update=update_count) 270 | 271 | def initpropvalues(): 272 | bpy.context.scene['gx_space_x'] = 0.2 273 | bpy.context.scene['gx_count_x'] = 32 274 | bpy.context.scene['gx_center_space'] = 0.2 275 | bpy.context.scene['gx_channels'] = 2 276 | bpy.context.scene['gx_scale_x'] = 0.07 277 | bpy.context.scene['gx_scale_y'] = 0.06 278 | bpy.context.scene['gx_scale_z'] = 0.04 279 | bpy.context.scene['gx_start'] = 100 280 | bpy.context.scene['gx_space_array'] = 1.7 281 | bpy.context.scene['gx_min_freq'] = 10.0 282 | bpy.context.scene['gx_max_freq'] = 20000.0 283 | bpy.context.scene['gx_mode'] = 2 284 | bpy.context.scene['gx_driver_power'] = 20.0 285 | bpy.context.scene['gx_freq_debug'] = False 286 | bpy.context.scene['gx_type'] = 0 287 | bpy.context.scene['gx_cube_scale_x'] = 0.07 288 | bpy.context.scene['gx_cube_scale_y'] = 0.06 289 | bpy.context.scene['gx_cube_scale_z'] = 0.20 290 | bpy.context.scene['gx_zenit'] = False 291 | bpy.context.scene['gx_slash'] = 0.0 292 | bpy.context.scene['gx_slash_rotate'] = True 293 | 294 | bpy.context.scene['gx_attack'] = 0.005 295 | bpy.context.scene['gx_release'] = 0.2 296 | bpy.context.scene['gx_threshold'] = 0.0 297 | bpy.context.scene['gx_accumulate'] = False 298 | bpy.context.scene['gx_additive'] = False 299 | bpy.context.scene['gx_square'] = False 300 | bpy.context.scene['gx_sthreshold'] = 0.1 301 | 302 | bpy.context.scene['gx_init'] = 1 303 | 304 | calc = 1 305 | 306 | class GXAVPanel(bpy.types.Panel): 307 | """Creates a Panel in the scene context of the properties editor""" 308 | bl_label = "GXAudioVisualisation" 309 | bl_idname = "SCENE_PT_layout" 310 | bl_space_type = 'PROPERTIES' 311 | bl_region_type = 'WINDOW' 312 | bl_context = "scene" 313 | 314 | def draw(self, context): 315 | layout = self.layout 316 | scene = context.scene 317 | row = layout.row() 318 | row.operator("object.gx_create_base", icon="MODIFIER", text="(re)Create Visualizer Base") 319 | try: 320 | if bpy.context.scene['gx_init'] == 1: 321 | layout.label(text="Parameters:", icon="UI") 322 | row = layout.row() 323 | row.prop(scene, "gx_center_space") 324 | row = layout.row(align=True) 325 | row.prop(scene, "gx_count_x") 326 | row.prop(scene, "gx_space_x") 327 | row = layout.row() 328 | row.prop(scene, "gx_slash") 329 | row.prop(scene, "gx_slash_rotate", icon="MAN_ROT") 330 | 331 | 332 | try: 333 | if bpy.context.scene['gx_type'] == 0: 334 | row = layout.row() 335 | row.prop(scene, "gx_type", icon="MOD_ARRAY", text="Mode") 336 | split = layout.split() 337 | col = split.column() 338 | col.label(text="Object Scale:", icon="MANIPUL") 339 | col = split.column(align=True) 340 | col.prop(scene, 'gx_scale_x', text="X") 341 | col.prop(scene, 'gx_scale_y', text="Y") 342 | col.prop(scene, 'gx_scale_z', text="Z") 343 | row = layout.row() 344 | row.label(text="Array modifier space:", icon="UNLINKED") 345 | row.prop(scene, "gx_space_array") 346 | else: 347 | row = layout.row() 348 | row.prop(scene, "gx_type", icon="MESH_CUBE", text="Mode") 349 | split = layout.split() 350 | col = split.column() 351 | col.label(text="Object Scale:", icon="MANIPUL") 352 | col = split.column(align=True) 353 | col.prop(scene, 'gx_cube_scale_x', text="X") 354 | col.prop(scene, 'gx_cube_scale_y', text="Y") 355 | #col.prop(scene, 'gx_cube_scale_z', text="Z") 356 | col.label(text="") 357 | row = layout.row() 358 | row.label(text="") 359 | except: 360 | layout.label(text="Missing variables, please report bug") 361 | 362 | row = layout.row() 363 | row = layout.row() 364 | row.prop(scene, "gx_driver_power") 365 | 366 | row = layout.row() 367 | box = layout.box() 368 | box.label("Channels to bake and audio files path:", icon="SOUND") 369 | if bpy.context.scene['gx_channels'] == 0: 370 | box.prop(scene, "gx_channels", icon="ARROW_LEFTRIGHT") 371 | elif bpy.context.scene['gx_channels'] == 1: 372 | box.prop(scene, "gx_channels", icon="BACK") 373 | elif bpy.context.scene['gx_channels'] == 2: 374 | box.prop(scene, "gx_channels", icon="FORWARD") 375 | box.prop(scene, "gx_left_file") 376 | box.prop(scene, "gx_right_file") 377 | row = layout.row() 378 | row.prop(scene, "gx_mode", icon="RNDCURVE") 379 | row = layout.row() 380 | row.prop(scene, "gx_start") 381 | row = layout.row() 382 | row.prop(scene, "gx_min_freq") 383 | row.prop(scene, "gx_max_freq") 384 | #row = layout.row() 385 | #row.prop(scene, "gx_freq_debug") 386 | row = layout.row() 387 | row.operator("object.gx_bake", icon="RADIO", text="(re)Bake animation data") 388 | row = layout.row() 389 | row.label(text="") 390 | 391 | box = layout.box() 392 | box.label(text="'Bake Sound to F-Curves' options:", icon="UI") 393 | split = box.split() 394 | col = split.column(align=True) 395 | col.prop(scene, 'gx_attack') 396 | col.prop(scene, 'gx_release') 397 | col = split.column(align=True) 398 | col.prop(scene, 'gx_threshold') 399 | col.prop(scene, 'gx_sthreshold') 400 | split = box.split() 401 | col = split.column() 402 | 403 | col.prop(scene, 'gx_accumulate') 404 | col = split.column() 405 | col.prop(scene, 'gx_additive') 406 | col = split.column() 407 | col.prop(scene, 'gx_square') 408 | #row = layout.row() 409 | #row.prop(scene, 'gx_zenit') 410 | row = layout.row() 411 | row.operator("object.gx_init_variables", icon="COLOR", text="Init/Reset Variables") 412 | except: 413 | False 414 | 415 | def gxstart(): 416 | try: 417 | bpy.context.scene['gx_init'] 418 | except: 419 | initpropvalues() 420 | 421 | bpy.ops.object.select_all(action="DESELECT") 422 | try: 423 | for i in range(bpy.context.scene['gx_count_x']): 424 | name = "bar_r_" + str(i+1) 425 | bpy.data.objects[name].select = True 426 | bpy.ops.object.delete() 427 | except: 428 | False 429 | try: 430 | for i in range(bpy.context.scene['gx_count_x']): 431 | name = "bar_l_" + str(i+1) 432 | bpy.data.objects[name].select = True 433 | bpy.ops.object.delete() 434 | except: 435 | False 436 | 437 | for i in range(bpy.context.scene['gx_count_x']): 438 | generate_objects(i) 439 | 440 | 441 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 442 | bpy.context.scene.objects.active = bpy.data.objects["bar_l_" + str(bpy.context.scene['gx_count_x'])] 443 | bpy.ops.object.select_pattern(pattern="bar_l_" + str(bpy.context.scene['gx_count_x'])) 444 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 445 | bpy.context.scene.objects.active = bpy.data.objects["bar_r_" + str(bpy.context.scene['gx_count_x'])] 446 | bpy.ops.object.select_pattern(pattern="bar_r_" + str(bpy.context.scene['gx_count_x'])) 447 | 448 | bpy.types.Scene.allobjects = bpy.context.scene['gx_count_x'] 449 | update_drivers() 450 | update_slash(True, True) 451 | update_space_x(True, True) 452 | 453 | def gxbake(): 454 | ### calculate for tercja 455 | tercja_x_min = compute_inverse(bpy.context.scene['gx_min_freq']) 456 | tercja_x_max = compute_inverse(bpy.context.scene['gx_max_freq']) 457 | tercja_step = (1/bpy.context.scene['gx_count_x']) 458 | ### 459 | 460 | try: 461 | bpy.types.Scene.bakedobjects 462 | except: 463 | bpy.types.Scene.bakedobjects = 0 464 | 465 | bpy.ops.object.select_all(action="DESELECT") 466 | try: 467 | for i in range(bpy.types.Scene.bakedobjects): 468 | name = "obj_r_" + str(i+1) 469 | bpy.data.objects[name].select = True 470 | bpy.ops.object.delete() 471 | except: 472 | False 473 | try: 474 | for i in range(bpy.types.Scene.bakedobjects): 475 | name = "obj_l_" + str(i+1) 476 | bpy.data.objects[name].select = True 477 | bpy.ops.object.delete() 478 | except: 479 | False 480 | 481 | b = bpy.context.scene['gx_min_freq'] 482 | c = (bpy.context.scene['gx_max_freq']-bpy.context.scene['gx_min_freq'])/bpy.context.scene['gx_count_x'] 483 | 484 | bpy.context.window_manager.progress_begin(0, 100) 485 | bpy.context.window_manager.progress_update(0) 486 | for i in range(bpy.context.scene['gx_count_x']): 487 | if bpy.context.scene['gx_mode'] == 2: 488 | a = b 489 | b = get_value_from_x((i+1)*tercja_step, tercja_x_min, tercja_x_max) 490 | elif bpy.context.scene['gx_mode'] == 1: 491 | b = ((bpy.context.scene['gx_max_freq']-bpy.context.scene['gx_min_freq'])-c*(bpy.context.scene['gx_count_x']-i-1)) + bpy.context.scene['gx_min_freq'] 492 | a = ((bpy.context.scene['gx_max_freq']-bpy.context.scene['gx_min_freq'])-c*(bpy.context.scene['gx_count_x']-i)) + bpy.context.scene['gx_min_freq'] 493 | elif bpy.context.scene['gx_mode'] == 0: 494 | b = ((1 - math.log(bpy.context.scene['gx_count_x']-i, bpy.context.scene['gx_count_x']+1)) * (bpy.context.scene['gx_max_freq']-bpy.context.scene['gx_min_freq'])) + bpy.context.scene['gx_min_freq'] 495 | a = ((1 - math.log(bpy.context.scene['gx_count_x']-i+1, bpy.context.scene['gx_count_x']+1)) * (bpy.context.scene['gx_max_freq']-bpy.context.scene['gx_min_freq'])) + bpy.context.scene['gx_min_freq'] 496 | 497 | print(str(i) + ": " + str(round(a, 1)) + " Hz - " + str(round(b, 1)) + " Hz") 498 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 499 | bpy.context.scene.frame_current = bpy.context.scene['gx_start'] 500 | bpy.ops.object.add(location=(-(i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2), bpy.context.scene['gx_slash'] * i, -2)) 501 | name = "obj_l_" + str(i+1) 502 | bpy.context.active_object.name = name 503 | 504 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 505 | if calc == 1: 506 | bpy.context.area.type = 'GRAPH_EDITOR' 507 | try: 508 | bpy.ops.graph.sound_bake(filepath=bpy.context.scene['gx_left_file'], 509 | low=a, high=b, 510 | attack = bpy.context.scene['gx_attack'], 511 | release = bpy.context.scene['gx_release'], 512 | threshold = bpy.context.scene['gx_threshold'], 513 | use_accumulate = bpy.context.scene['gx_accumulate'], 514 | use_additive = bpy.context.scene['gx_additive'], 515 | use_square = bpy.context.scene['gx_square'], 516 | sthreshold = bpy.context.scene['gx_sthreshold']) 517 | except: 518 | False 519 | bpy.context.area.type = 'PROPERTIES' 520 | 521 | if bpy.context.scene['gx_channels'] == 0: 522 | bpy.context.window_manager.progress_update((i+0.5)/bpy.context.scene['gx_count_x']) 523 | 524 | if bpy.context.scene['gx_freq_debug'] == 1: 525 | bpy.ops.object.add(location=(-(i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2), bpy.context.scene['gx_slash'] * i, -4)) 526 | name = (str(i) + ": " + str(round(a, 1)) + " Hz - " + str(round(b, 1)) + " Hz") 527 | bpy.context.active_object.name = name 528 | 529 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 530 | bpy.context.scene.frame_current = bpy.context.scene['gx_start'] 531 | bpy.ops.object.add(location=(i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2, bpy.context.scene['gx_slash'] * i, -2)) 532 | name = "obj_r_" + str(i+1) 533 | bpy.context.active_object.name = name 534 | 535 | bpy.ops.anim.keyframe_insert_menu(type='Scaling') 536 | if calc == 1: 537 | bpy.context.area.type = 'GRAPH_EDITOR' 538 | try: 539 | bpy.ops.graph.sound_bake(filepath=bpy.context.scene['gx_right_file'], 540 | low=a, high=b, 541 | attack = bpy.context.scene['gx_attack'], 542 | release = bpy.context.scene['gx_release'], 543 | threshold = bpy.context.scene['gx_threshold'], 544 | use_accumulate = bpy.context.scene['gx_accumulate'], 545 | use_additive = bpy.context.scene['gx_additive'], 546 | use_square = bpy.context.scene['gx_square'], 547 | sthreshold = bpy.context.scene['gx_sthreshold']) 548 | except: 549 | False 550 | bpy.context.area.type = 'PROPERTIES' 551 | 552 | if bpy.context.scene['gx_channels'] == 0: 553 | bpy.context.window_manager.progress_update((i+1)/bpy.context.scene['gx_count_x']) 554 | 555 | if bpy.context.scene['gx_freq_debug'] == 1: 556 | bpy.ops.object.add(location=(i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2, bpy.context.scene['gx_slash'] * i, -4)) 557 | name = (str(i) + ": " + str(round(a, 1)) + " Hz - " + str(round(b, 1)) + " Hz") 558 | bpy.context.active_object.name = name 559 | 560 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 2: 561 | bpy.context.window_manager.progress_update((i+1)/bpy.context.scene['gx_count_x']) 562 | 563 | bpy.context.window_manager.progress_end() 564 | bpy.types.Scene.bakedobjects = bpy.context.scene['gx_count_x'] 565 | 566 | class GxInitVariables(bpy.types.Operator): 567 | 568 | bl_idname = "object.gx_init_variables" 569 | bl_label = "GxInitVariables" 570 | bl_options = {'REGISTER', 'UNDO'} 571 | 572 | def execute(self, context): 573 | initpropvalues() 574 | return {'FINISHED'} 575 | 576 | class GxCreateBase(bpy.types.Operator): 577 | 578 | bl_idname = "object.gx_create_base" 579 | bl_label = "GxCreateBase" 580 | bl_options = {'REGISTER', 'UNDO'} 581 | 582 | def execute(self, context): 583 | gxstart() 584 | return {'FINISHED'} 585 | 586 | class GxBake(bpy.types.Operator): 587 | 588 | bl_idname = "object.gx_bake" 589 | bl_label = "GxBake" 590 | bl_options = {'REGISTER', 'UNDO'} 591 | 592 | def execute(self, context): 593 | gxbake() 594 | update_drivers() 595 | 596 | return {'FINISHED'} 597 | 598 | def update_space_array(self, context): 599 | for i in range(bpy.context.scene['gx_count_x']): 600 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 601 | name = "bar_l_" + str(i+1) 602 | bpy.data.objects[name].modifiers['Array'].relative_offset_displace[2] = bpy.context.scene['gx_space_array'] 603 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 604 | name = "bar_r_" + str(i+1) 605 | bpy.data.objects[name].modifiers['Array'].relative_offset_displace[2] = bpy.context.scene['gx_space_array'] 606 | 607 | def update_slash(self, context): 608 | for i in range(bpy.context.scene['gx_count_x']): 609 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 610 | name = "bar_l_" + str(i+1) 611 | bpy.data.objects[name].location[1] = bpy.context.scene['gx_slash'] * i 612 | if bpy.context.scene['gx_slash_rotate'] == True: 613 | bpy.data.objects[name].rotation_euler[2] = -math.asin(bpy.context.scene['gx_slash']/math.sqrt(math.pow(bpy.context.scene['gx_space_x'],2) + math.pow(bpy.context.scene['gx_slash'],2))) 614 | else: 615 | bpy.data.objects[name].rotation_euler[2] = 0 616 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 617 | name = "bar_r_" + str(i+1) 618 | bpy.data.objects[name].location[1] = bpy.context.scene['gx_slash'] * i 619 | if bpy.context.scene['gx_slash_rotate'] == True: 620 | bpy.data.objects[name].rotation_euler[2] = math.asin(bpy.context.scene['gx_slash']/math.sqrt(math.pow(bpy.context.scene['gx_space_x'],2) + math.pow(bpy.context.scene['gx_slash'],2))) 621 | else: 622 | bpy.data.objects[name].rotation_euler[2] = 0 623 | try: 624 | bpy.types.Scene.bakedobjects 625 | for i in range(bpy.types.Scene.bakedobjects): 626 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 627 | name = "obj_l_" + str(i+1) 628 | bpy.data.objects[name].location[1] = bpy.context.scene['gx_slash'] * i 629 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 630 | name = "obj_r_" + str(i+1) 631 | bpy.data.objects[name].location[1] = bpy.context.scene['gx_slash'] * i 632 | except: 633 | False 634 | 635 | def drivering(i): 636 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 637 | name = "bar_l_" + str(i+1) 638 | name2 = "obj_l_" + str(i+1) 639 | try: 640 | bpy.data.objects[name2] 641 | if bpy.context.scene['gx_type'] == 0: 642 | try: 643 | bpy.data.objects[name].modifiers['Array'].driver_remove('count') 644 | except: 645 | False 646 | obj = bpy.data.objects[name] #def drivering 647 | mdf = obj.modifiers['Array'].driver_add('count') 648 | drv = mdf.driver 649 | drv.type = 'AVERAGE' 650 | var = drv.variables.new() 651 | var.name = 'name' 652 | var.type = 'TRANSFORMS' 653 | targ = var.targets[0] 654 | targ.id = bpy.data.objects[name2] 655 | targ.transform_type = 'SCALE_Z' 656 | targ.bone_target = 'Driver' 657 | fmod = mdf.modifiers[0] 658 | fmod.poly_order = 1 659 | fmod.coefficients = (0.0, bpy.context.scene['gx_driver_power']) 660 | 661 | elif bpy.context.scene['gx_type'] == 1 or bpy.context.scene['gx_type'] == 2: 662 | try: 663 | bpy.data.objects[name].driver_remove('scale', 2) 664 | except: 665 | False 666 | obj = bpy.data.objects[name] #def drivering 667 | mdf = obj.driver_add('scale', 2) 668 | drv = mdf.driver 669 | drv.type = 'AVERAGE' 670 | var = drv.variables.new() 671 | var.name = 'name' 672 | var.type = 'TRANSFORMS' 673 | targ = var.targets[0] 674 | targ.id = bpy.data.objects[name2] 675 | targ.transform_type = 'SCALE_Z' 676 | targ.bone_target = 'Driver' 677 | fmod = mdf.modifiers[0] 678 | fmod.poly_order = 1 679 | fmod.coefficients = (0.0, bpy.context.scene['gx_driver_power']) 680 | except: 681 | False 682 | 683 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 684 | name = "bar_r_" + str(i+1) 685 | name2 = "obj_r_" + str(i+1) 686 | try: 687 | bpy.data.objects[name2] 688 | if bpy.context.scene['gx_type'] == 0: 689 | try: 690 | bpy.data.objects[name].modifiers['Array'].driver_remove('count') 691 | except: 692 | False 693 | obj = bpy.data.objects[name] #def drivering 694 | mdf = obj.modifiers['Array'].driver_add('count') 695 | drv = mdf.driver 696 | drv.type = 'AVERAGE' 697 | var = drv.variables.new() 698 | var.name = 'name' 699 | var.type = 'TRANSFORMS' 700 | targ = var.targets[0] 701 | targ.id = bpy.data.objects[name2] 702 | targ.transform_type = 'SCALE_Z' 703 | targ.bone_target = 'Driver' 704 | fmod = mdf.modifiers[0] 705 | fmod.poly_order = 1 706 | fmod.coefficients = (0.0, bpy.context.scene['gx_driver_power']) 707 | 708 | elif bpy.context.scene['gx_type'] == 1 or bpy.context.scene['gx_type'] == 2: 709 | try: 710 | bpy.data.objects[name].driver_remove('scale', 2) 711 | except: 712 | False 713 | obj = bpy.data.objects[name] #def drivering 714 | mdf = obj.driver_add('scale', 2) 715 | drv = mdf.driver 716 | drv.type = 'AVERAGE' 717 | var = drv.variables.new() 718 | var.name = 'name' 719 | var.type = 'TRANSFORMS' 720 | targ = var.targets[0] 721 | targ.id = bpy.data.objects[name2] 722 | targ.transform_type = 'SCALE_Z' 723 | targ.bone_target = 'Driver' 724 | fmod = mdf.modifiers[0] 725 | fmod.poly_order = 1 726 | fmod.coefficients = (0.0, bpy.context.scene['gx_driver_power']) 727 | except: 728 | False 729 | 730 | def update_drivers(): 731 | try: 732 | bpy.types.Scene.bakedobjects 733 | for i in range(bpy.types.Scene.bakedobjects): 734 | drivering(i) 735 | except: 736 | False 737 | 738 | def update_drivers3(self, context): 739 | try: 740 | bpy.types.Scene.bakedobjects 741 | for i in range(bpy.types.Scene.bakedobjects): 742 | drivering(i) 743 | except: 744 | False 745 | 746 | def update_drivers2(): 747 | try: 748 | bpy.types.Scene.bakedobjects 749 | for i in range(bpy.types.Scene.allobjects, bpy.types.Scene.bakedobjects): 750 | drivering(i) 751 | except: 752 | False 753 | 754 | def update_channels(self, context): 755 | gxstart() 756 | 757 | def update_space_x(self, context): 758 | for i in range(bpy.context.scene['gx_count_x']): 759 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 760 | name = "bar_l_" + str(i+1) 761 | bpy.data.objects[name].location[0] = -(i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2) 762 | if bpy.context.scene['gx_slash_rotate'] == True and (bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_slash']) != 0: 763 | bpy.data.objects[name].rotation_euler[2] = -math.asin(bpy.context.scene['gx_slash']/math.sqrt(math.pow(bpy.context.scene['gx_space_x'],2) + math.pow(bpy.context.scene['gx_slash'],2))) 764 | else: 765 | bpy.data.objects[name].rotation_euler[2] = 0 766 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 767 | name = "bar_r_" + str(i+1) 768 | bpy.data.objects[name].location[0] = i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2 769 | if bpy.context.scene['gx_slash_rotate'] == True and (bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_slash']) != 0: 770 | bpy.data.objects[name].rotation_euler[2] = math.asin(bpy.context.scene['gx_slash']/math.sqrt(math.pow(bpy.context.scene['gx_space_x'],2) + math.pow(bpy.context.scene['gx_slash'],2))) 771 | else: 772 | bpy.data.objects[name].rotation_euler[2] = 0 773 | try: 774 | bpy.types.Scene.bakedobjects 775 | for i in range(bpy.types.Scene.bakedobjects): 776 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 777 | name = "obj_l_" + str(i+1) 778 | bpy.data.objects[name].location[0] = -(i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2) 779 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 780 | name = "obj_r_" + str(i+1) 781 | bpy.data.objects[name].location[0] = i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2 782 | except: 783 | False 784 | 785 | def update_scale(self, context): 786 | for i in range(bpy.context.scene['gx_count_x']): 787 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 788 | name = "bar_l_" + str(i+1) 789 | if bpy.context.scene['gx_type'] == 0: 790 | bpy.data.objects[name].scale = (bpy.context.scene['gx_scale_x'], bpy.context.scene['gx_scale_y'], bpy.context.scene['gx_scale_z']) 791 | elif bpy.context.scene['gx_type'] == 1: 792 | bpy.data.objects[name].scale = (bpy.context.scene['gx_cube_scale_x'], bpy.context.scene['gx_cube_scale_y'], bpy.context.scene['gx_cube_scale_z']) 793 | #bpy.ops.object.transform_apply(scale=True) 794 | elif bpy.context.scene['gx_type'] == 2: 795 | bpy.data.objects[name].scale = (bpy.context.scene['gx_cube_scale_x'], bpy.context.scene['gx_cube_scale_y'], bpy.context.scene['gx_cube_scale_z']*2) 796 | #bpy.ops.object.transform_apply(scale=True) 797 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 798 | name = "bar_r_" + str(i+1) 799 | if bpy.context.scene['gx_type'] == 0: 800 | bpy.data.objects[name].scale = (bpy.context.scene['gx_scale_x'], bpy.context.scene['gx_scale_y'], bpy.context.scene['gx_scale_z']) 801 | elif bpy.context.scene['gx_type'] == 1: 802 | bpy.data.objects[name].scale = (bpy.context.scene['gx_cube_scale_x'], bpy.context.scene['gx_cube_scale_y'], bpy.context.scene['gx_cube_scale_z']) 803 | #bpy.ops.object.transform_apply(scale=True) 804 | elif bpy.context.scene['gx_type'] == 2: 805 | bpy.data.objects[name].scale = (bpy.context.scene['gx_cube_scale_x'], bpy.context.scene['gx_cube_scale_y'], bpy.context.scene['gx_cube_scale_z']*2) 806 | #bpy.ops.object.transform_apply(scale=True) 807 | 808 | def generate_objects(i): 809 | gx_save = bpy.context.scene.cursor_location.copy() 810 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 811 | bpy.ops.mesh.primitive_cube_add(location=(-(i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2), bpy.context.scene['gx_slash'] * i, 0)) 812 | if bpy.context.scene['gx_slash_rotate'] == True: 813 | bpy.context.active_object.rotation_euler[2] = -math.asin(bpy.context.scene['gx_slash']/math.sqrt(math.pow(bpy.context.scene['gx_space_x'],2) + math.pow(bpy.context.scene['gx_slash'],2))) 814 | 815 | if bpy.context.scene['gx_type'] == 0: 816 | bpy.context.active_object.scale = (bpy.context.scene['gx_scale_x'], bpy.context.scene['gx_scale_y'], bpy.context.scene['gx_scale_z']) 817 | elif bpy.context.scene['gx_type'] == 1: 818 | bpy.context.active_object.scale = (1, 1, 0.06) 819 | bpy.ops.object.transform_apply(scale=True) 820 | bpy.context.active_object.location[2] = 0.06 821 | bpy.context.scene.cursor_location = (-(i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2), bpy.context.scene['gx_slash'] * i, 0) 822 | bpy.ops.object.origin_set(type='ORIGIN_CURSOR') 823 | bpy.context.active_object.scale = (bpy.context.scene['gx_cube_scale_x'], bpy.context.scene['gx_cube_scale_y'], bpy.context.scene['gx_cube_scale_z']) 824 | elif bpy.context.scene['gx_type'] == 2: 825 | bpy.context.active_object.scale = (1, 1, 0.06*2) 826 | bpy.ops.object.transform_apply(scale=True) 827 | bpy.context.active_object.scale = (bpy.context.scene['gx_cube_scale_x'], bpy.context.scene['gx_cube_scale_y'], bpy.context.scene['gx_cube_scale_z']*2) 828 | 829 | name = "bar_l_" + str(i+1) 830 | bpy.context.active_object.name = name 831 | 832 | if bpy.context.scene['gx_type'] == 0: 833 | bpy.ops.object.modifier_add(type='ARRAY') 834 | bpy.context.active_object.modifiers['Array'].count = 10 835 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[0] = 0 836 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[2] = bpy.context.scene['gx_space_array'] 837 | 838 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 839 | bpy.ops.mesh.primitive_cube_add(location=(i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2, bpy.context.scene['gx_slash'] * i, 0)) 840 | if bpy.context.scene['gx_slash_rotate'] == True: 841 | bpy.context.active_object.rotation_euler[2] = math.asin(bpy.context.scene['gx_slash']/math.sqrt(math.pow(bpy.context.scene['gx_space_x'],2) + math.pow(bpy.context.scene['gx_slash'],2))) 842 | 843 | if bpy.context.scene['gx_type'] == 0: 844 | bpy.context.active_object.scale = (bpy.context.scene['gx_scale_x'], bpy.context.scene['gx_scale_y'], bpy.context.scene['gx_scale_z']) 845 | elif bpy.context.scene['gx_type'] == 1: 846 | bpy.context.active_object.scale = (1, 1, 0.06) 847 | bpy.ops.object.transform_apply(scale=True) 848 | bpy.context.active_object.location[2] = 0.06 849 | bpy.context.scene.cursor_location = (i*bpy.context.scene['gx_space_x'] + bpy.context.scene['gx_center_space']/2, bpy.context.scene['gx_slash'] * i, 0) 850 | bpy.ops.object.origin_set(type='ORIGIN_CURSOR') 851 | bpy.context.active_object.scale = (bpy.context.scene['gx_cube_scale_x'], bpy.context.scene['gx_cube_scale_y'], bpy.context.scene['gx_cube_scale_z']) 852 | elif bpy.context.scene['gx_type'] == 2: 853 | bpy.context.active_object.scale = (1, 1, 0.06*2) 854 | bpy.ops.object.transform_apply(scale=True) 855 | bpy.context.active_object.scale = (bpy.context.scene['gx_cube_scale_x'], bpy.context.scene['gx_cube_scale_y'], bpy.context.scene['gx_cube_scale_z']*2) 856 | 857 | name = "bar_r_" + str(i+1) 858 | bpy.context.active_object.name = name 859 | 860 | if bpy.context.scene['gx_type'] == 0: 861 | bpy.ops.object.modifier_add(type='ARRAY') 862 | bpy.context.active_object.modifiers['Array'].count = 10 863 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[0] = 0 864 | bpy.context.active_object.modifiers['Array'].relative_offset_displace[2] = bpy.context.scene['gx_space_array'] 865 | bpy.context.scene.cursor_location = gx_save 866 | 867 | def update_count(self, context): 868 | if bpy.types.Scene.allobjects > bpy.context.scene['gx_count_x']: 869 | bpy.ops.object.select_all(action="DESELECT") 870 | for i in range(bpy.context.scene['gx_count_x'], bpy.types.Scene.allobjects): 871 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 872 | name = "bar_l_" + str(i+1) 873 | bpy.data.objects[name].select = True 874 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 875 | name = "bar_r_" + str(i+1) 876 | bpy.data.objects[name].select = True 877 | bpy.ops.object.delete() 878 | 879 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 880 | bpy.context.scene.objects.active = bpy.data.objects["bar_l_" + str(bpy.context.scene['gx_count_x'])] 881 | bpy.ops.object.select_pattern(pattern="bar_l_" + str(bpy.context.scene['gx_count_x'])) 882 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 883 | bpy.context.scene.objects.active = bpy.data.objects["bar_r_" + str(bpy.context.scene['gx_count_x'])] 884 | bpy.ops.object.select_pattern(pattern="bar_r_" + str(bpy.context.scene['gx_count_x'])) 885 | 886 | bpy.types.Scene.allobjects = bpy.context.scene['gx_count_x'] 887 | elif bpy.types.Scene.allobjects < bpy.context.scene['gx_count_x']: 888 | for i in range(bpy.types.Scene.allobjects, bpy.context.scene['gx_count_x']): 889 | 890 | generate_objects(i) 891 | try: 892 | if bpy.types.Scene.allobjects < bpy.types.Scene.bakedobjects: 893 | update_drivers2() 894 | except: 895 | False 896 | 897 | if bpy.context.scene['gx_channels'] == 1 or bpy.context.scene['gx_channels'] == 0: 898 | bpy.context.scene.objects.active = bpy.data.objects["bar_l_" + str(bpy.context.scene['gx_count_x'])] 899 | bpy.ops.object.select_pattern(pattern="bar_l_" + str(bpy.context.scene['gx_count_x'])) 900 | if bpy.context.scene['gx_channels'] == 2 or bpy.context.scene['gx_channels'] == 0: 901 | bpy.context.scene.objects.active = bpy.data.objects["bar_r_" + str(bpy.context.scene['gx_count_x'])] 902 | bpy.ops.object.select_pattern(pattern="bar_r_" + str(bpy.context.scene['gx_count_x'])) 903 | 904 | bpy.types.Scene.allobjects = bpy.context.scene['gx_count_x'] 905 | else: 906 | False 907 | 908 | def register(): 909 | bpy.utils.register_class(GxCreateBase) 910 | bpy.utils.register_class(GxInitVariables) 911 | bpy.utils.register_class(GxBake) 912 | bpy.utils.register_class(GXAVPanel) 913 | initprop() 914 | def unregister(): 915 | bpy.utils.unregister_class(GxCreateBase) 916 | bpy.utils.unregister_class(GxInitVariables) 917 | bpy.utils.unregister_class(GxBake) 918 | bpy.utils.unregister_class(GXAVPanel) 919 | 920 | if __name__ == "__main__": 921 | register() 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | --------------------------------------------------------------------------------